Hoppa till huvudinnehållet

Adding shapefiles to map using workflow (filepicker)

Kommentarer

8 kommentarer

  • Julia van Ravenswaaij

    It used to be posssible with Geocortex Essentials Workflow using the Shapefile To FeatureSet Activity. Such a shame that that activity wasn't added to the new Studio Workflow

    0
  • Ryan Kelley

    One way I've gotten around this was just to hook the Workflow into a Geoprocessing Service I wrote, and return the results to the Workflow to add the graphics to the screen or create some sort of geometry to use in a process.

    1
  • Julia van Ravenswaaij

    Thanks Ryan Kelley
    The work-around I'm using now is to upload a JSON file using the FilePicker, followed by Get Text From File and Get Feature Set From JSON. The JSON file was easy enough to make in ArcGIS Pro (export to JSON).

    1
  • Gareth Finney

    Hi Julia van Ravenswaaij

    I was having the same issues (I think), so I reached out to our local rep, and he pointed me in the right direction. 

    I've only uploaded a simple shapefile to a graphic, and flash that on the map, as a quick test. 

    I wish there was a way of attaching the json, but here it is below. Hope that helps?

    {"_properties":{"isServerWorkflow":false},"components":[{"id":2,"steps":[{"id":3,"inputs":{},"position":"0,0","purpose":"start","title":"Start","transitions":[{"id":11,"inputs":{},"position":"90,60 90,110","target":{"id":9}}]},{"action":"gcx:wf:forms:form:DisplayForm","id":9,"inputs":{"form":{"accessors":[],"code":"resources.forms[values.id]","values":{"id":10}}},"name":"formMainImport","position":"-30,110","title":"Display Form","transitions":[{"id":13,"inputs":{},"position":"90,230 90,270","sourceConnector":"bottom","target":{"id":12}}]},{"action":"gcx:wf:app::RunOperation","id":12,"inputs":{"operationName":"results.from-shapefile","operationParameter":{"accessors":["$formMainImport"],"annotations":[{"count":15,"index":0,"kind":"idref"}],"code":"$formMainImport.state.fileShapeFilePicker.value.files[0]","source":"$formMainImport.state.fileShapeFilePicker.value.files[0]"}},"name":"runOperationGetShpFile","position":"-30,270","title":"Run Operation","transitions":[{"id":15,"inputs":{},"position":"90,340 90,370","sourceConnector":"bottom","target":{"id":14}}]},{"action":"gcx:wf:app::RunOperation","id":14,"inputs":{"operationName":"results.to-graphics","operationParameter":{"accessors":["$runOperationGetShpFile"],"annotations":[{"count":23,"index":0,"kind":"idref"}],"code":"$runOperationGetShpFile.result","source":"$runOperationGetShpFile.result"}},"name":"runOperationShpToGraphics","position":"-30,370","title":"Run Operation","transitions":[{"id":23,"position":"90,440 90,480","sourceConnector":"bottom","target":{"id":22}}]},{"action":"gcx:wf:arcgis::AddGraphicsLayerFeatures","id":22,"inputs":{"features":{"accessors":["$runOperationShpToGraphics"],"annotations":[{"count":26,"index":0,"kind":"idref"}],"code":"$runOperationShpToGraphics.result","source":"$runOperationShpToGraphics.result"}},"name":"addGraphics","position":"-30,480","title":"Add Graphics","transitions":[{"id":25,"position":"90,550 90,600","sourceConnector":"bottom","target":{"id":24}}]},{"action":"gcx:wf:core::Delay","id":24,"inputs":{"duration":5000},"position":"-30,600","title":"Delay","transitions":[{"id":27,"position":"90,630 90,660","sourceConnector":"bottom","target":{"id":26}}]},{"action":"gcx:wf:arcgis::ClearGraphicsLayer","id":26,"inputs":{},"position":"-30,660","title":"Clear Graphics"}]}],"deploymentConfig":{"supportedApps":{"GWV":true}},"designerVersion":"5.32.0+12","forms":[{"defaults":{},"elements":{"fileShapeFilePicker":{"enabled":true,"index":0,"prompt":{"markdown":"Add File"},"rowIndex":0,"rowNumber":0,"title":{"markdown":"File Picker"},"type":"FilePicker"},"footer":{"enabled":true,"items":{"0":{"default":true,"index":0,"label":{"markdown":"Submit"},"validates":true,"value":"submit"},"1":{"index":1,"label":{"markdown":"Cancel"},"validates":false,"value":"cancel"}},"section":"footer","type":"ButtonBar"},"header":{"section":"header","title":{"markdown":"Upload Shapefile"},"type":"Header"}},"id":10}],"licenseInfo":{"licenseUrl":"xxx"/vertigisstudio/workflow/service/auth/license"},"start":{"id":3}}

    2
  • Alan Clack

    This can be done with vanilla VertiGIS. You were on the right track to use `results.from-shapefile`. However, you will want to use it as an operation since commands only run, they produce no output. You, of course, will want the output of your Shapefiles so you can use `Run Operation` instead. If you wanted to use the individual components, this can be done as well, but will likely require a server-side workflow to handle the multiple files required for the Shapefile schema.

    Beyond that there are a ton of considerations between how users upload files, the logic you want to apply to them, and/or what data you need from them.

    Below is a JSON snippet of a component we use to visualize and use Shapefiles (.zip) that are user selected. It will allow you to select multiple Shapefiles (.zip) and will zoom to and symbolize them as they are added/removed. Currently will likely only symbolize polygons and only grabs geometry but the component has a fair amount of notes to hopefully flesh out the exact logic, syntax, and capability you are looking for.
    The only way I can get a link available: https://alanlclack.blob.core.windows.net/storage/VertiGIS/Component - Shapefile Uploader.json
    Hopefully a nice hosting/sharing option becomes available from VertiGIS at some point.
    The full JSON is also below as preferred method to check/create the file to Import into VertiGIS, either way, I hope you and/or people visiting this get a good solution.

    {"_properties":{"isServerWorkflow":false},"components":[{"id":2,"steps":[{"id":3,"inputs":{},"position":"0,-160","purpose":"start","title":"Start","transitions":[{"id":1145,"position":"90,-100 90,-70","sourceConnector":"bottom","target":{"id":1144},"targetConnector":"top"}]},{"action":"gcx:wf:forms:form:DisplayForm","description":"The logic and form that handles uploading Shapefile with the Item Picker and automatically converting them to features, displaying them on the web map, and zooming to their overall extent.","id":231,"inputs":{"form":{"accessors":[],"code":"resources.forms[values.id]","values":{"id":229}}},"name":"formShapefileUploader","position":"-30,340","title":"Shapefile Uploader","transitions":[{"id":1082,"position":"90,600 90,630","sourceConnector":"bottom","target":{"id":864},"targetConnector":"top"}]},{"action":"gcx:wf:core::Exit","id":383,"inputs":{},"position":"0,760","title":"Exit"},{"action":"gcx:wf:arcgis::ClearGraphicsLayer","description":"*Clear Temporary Shapefile*\nClean up the graphics if the tool is closed.","id":864,"inputs":{"layerId":{"accessors":["$valueTemporaryShapefileLayerName"],"annotations":[{"count":33,"index":0,"kind":"idref"}],"code":"$valueTemporaryShapefileLayerName.result","source":"$valueTemporaryShapefileLayerName.result"}},"position":"-30,630","title":"Clear Graphics","transitions":[{"id":881,"inputs":{},"position":"90,730 90,760","sourceConnector":"bottom","target":{"id":383},"targetConnector":"top"}]},{"action":"gcx:wf:arcgis::ClearGraphicsLayer","description":"**Clear Temporary Shapefile**\n\nErase the workflow's previous layer to keep things clean in case the tool quit or crashed without clearing first.","id":1079,"inputs":{"layerId":{"accessors":["$valueTemporaryShapefileLayerName"],"annotations":[{"count":33,"index":0,"kind":"idref"}],"code":"$valueTemporaryShapefileLayerName.result","source":"$valueTemporaryShapefileLayerName.result"}},"position":"-30,150","title":"Clear Graphics","transitions":[{"id":1081,"position":"90,310 90,340","sourceConnector":"bottom","target":{"id":231},"targetConnector":"top"}]},{"action":"gcx:wf:core::CreateValue","description":"This is a variable name that needs to apply to all graphics handled by the Shapefile conversion. Set here once so we can add it as an expression later instead of adding it everywhere.","id":1144,"inputs":{"expression":"TemporaryShapefileLayer"},"name":"valueTemporaryShapefileLayerName","position":"-30,-70","title":"Create Value","transitions":[{"id":1146,"position":"90,120 90,150","sourceConnector":"bottom","target":{"id":1079},"targetConnector":"top"}]},{"action":"gcx:wf:core::Annotation","description":"This is a component for VertiGIS studio. It functions as a way to select a Shapefile (.zip) file from user's location and convert it into a web feature to display.\n\nIt currently will only properly symbolize polygons and only grabs the geometry, but should serve as a great starting point to build logic to accept any geometry type and include attributes with some more in-depth work.","id":1155,"inputs":{},"position":"240,-160","title":"Shapefile uploader"}]},{"id":321,"steps":[{"id":322,"inputs":{},"position":"0,-100","purpose":"start","title":"Event","transitions":[{"id":1135,"position":"90,-40 90,-10","sourceConnector":"bottom","target":{"id":1132},"targetConnector":"top"}]},{"action":"gcx:wf:app::RunOperation","description":"This is the magical step to change from a file/blob type to a web-features type. It has specific syntax that will work with the filePicker.","id":344,"inputs":{"operationName":"results.from-shapefile","operationParameter":{"accessors":["$formShapefileUploader"],"annotations":[{"count":22,"index":10,"kind":"idref"}],"code":"{\n    blobs: $formShapefileUploader.state.filePickerShapefile.value.files\n}","source":"{\n  blobs:$formShapefileUploader.state.filePickerShapefile.value.files\n}"}},"name":"runOperationShapefileToFeatures","position":"-200,430","title":"Run Operation","transitions":[{"id":1133,"position":"-80,600 -80,630","sourceConnector":"bottom","target":{"id":1103},"targetConnector":"top"}]},{"action":"gcx:wf:arcgis::ClearGraphicsLayer","description":"Clear graphics since this should only happen when the users removes all of their uploads. We avoid the non-blocking error and clear the map as would be expected.","id":427,"inputs":{"layerId":{"accessors":["$valueTemporaryShapefileLayerName"],"annotations":[{"count":33,"index":0,"kind":"idref"}],"code":"$valueTemporaryShapefileLayerName.result","source":"$valueTemporaryShapefileLayerName.result"}},"position":"120,430","title":"Clear Graphics"},{"action":"gcx:wf:core::If","description":"If no files are uploaded (happens when a user removes all the uploads) we don't want an error to occur since its an empty object. We just make sure that if the object is undefined we clear the graphics.","id":439,"inputs":{"condition":{"accessors":["$formShapefileUploader"],"annotations":[{"count":22,"index":0,"kind":"idref"}],"code":"$formShapefileUploader.state.filePickerShapefile.value != undefined","source":"$formShapefileUploader.state.filePickerShapefile.value != undefined"}},"position":"-30,170","title":"If Files","transitions":[{"branch":"true","id":441,"inputs":{},"position":"-30,285 -80,285 -80,430","sourceConnector":"left","target":{"id":344},"targetConnector":"top"},{"branch":"false","id":442,"inputs":{},"position":"210,285 240,285 240,430","sourceConnector":"right","target":{"id":427},"targetConnector":"top"}]},{"action":"gcx:wf:arcgis::AddGraphicsLayerFeatures","description":"Because the user could add or remove an item, we need to reset the graphics layer before we remake the necessary changes otherwise old features will stay if removed from the FilePicker","id":1103,"inputs":{"features":{"accessors":[],"annotations":[],"code":"[]","source":"[]"},"layerId":{"accessors":["$valueTemporaryShapefileLayerName"],"annotations":[{"count":33,"index":0,"kind":"idref"}],"code":"$valueTemporaryShapefileLayerName.result","source":"$valueTemporaryShapefileLayerName.result"},"removeAllFeatures":true},"name":"addGraphicsShapefile","position":"-200,630","title":"Add Graphics","transitions":[{"id":1117,"inputs":{},"position":"-80,840 -80,870","sourceConnector":"bottom","target":{"id":1105},"targetConnector":"top"}]},{"action":"gcx:wf:core:loop:ForEach","description":"Add each feature of each Shapefile upload since Shapefiles can have multiple features and the user could upload multiple files. We also go ahead and symbolize.","id":1105,"inputs":{"items":{"accessors":["$runOperationShapefileToFeatures"],"annotations":[{"count":32,"index":0,"kind":"idref"}],"code":"$runOperationShapefileToFeatures.result","source":"$runOperationShapefileToFeatures.result"}},"name":"forEachShapefileFeature","position":"-200,870","title":"For Each","transitions":[{"id":1152,"position":"-80,1120 -80,1150","sourceConnector":"bottom","target":{"id":1109},"targetConnector":"top"}]},{"action":"gcx:wf:arcgis::GetGraphicsLayerFeatures","description":"This Get Graphics is required to get the updated features. Calling old features may not work even if their objects are updated.","id":1109,"inputs":{"layerId":{"accessors":["$valueTemporaryShapefileLayerName"],"annotations":[{"count":33,"index":0,"kind":"idref"}],"code":"$valueTemporaryShapefileLayerName.result","source":"$valueTemporaryShapefileLayerName.result"}},"name":"getGraphicsShapefileExtent","position":"-200,1150","title":"Get Graphics","transitions":[{"id":1153,"position":"-80,1320 -80,1350","sourceConnector":"bottom","target":{"id":1113},"targetConnector":"top"}]},{"action":"gcx:wf:arcgis::SetViewExtent","id":1113,"inputs":{"features":{"accessors":["$getGraphicsShapefileExtent"],"annotations":[{"count":27,"index":0,"kind":"idref"}],"code":"$getGraphicsShapefileExtent.features","source":"$getGraphicsShapefileExtent.features"}},"position":"-200,1350","title":"Set Map Extent"},{"action":"gcx:wf:arcgis::SymbolFromJson","description":"A blue highlight symbol is used here to help visualize polygons. Otherwise they will default to a completely black fill.","id":1132,"inputs":{"json":"{\n  \"type\": \"esriSLS\",\n  \"color\": [123, 252, 234, 255],\n  \"width\": 4.5,\n  \"style\": \"esriSLSSolid\"\n}"},"name":"symbolShapfile","position":"-30,-10","title":"Get Symbol From JSON","transitions":[{"id":1136,"position":"90,140 90,170","sourceConnector":"bottom","target":{"id":439},"targetConnector":"top"}]}],"title":"change-filePickerShapefile"},{"id":1091,"steps":[{"action":"gcx:wf:arcgis::AddGraphicsLayerFeatures","id":1093,"inputs":{"features":{"accessors":["$featureFromShapefile"],"annotations":[{"count":21,"index":0,"kind":"idref"}],"code":"$featureFromShapefile.feature","source":"$featureFromShapefile.feature"},"layerId":{"accessors":["$valueTemporaryShapefileLayerName"],"annotations":[{"count":33,"index":0,"kind":"idref"}],"code":"$valueTemporaryShapefileLayerName.result","source":"$valueTemporaryShapefileLayerName.result"},"removeAllFeatures":false},"position":"-30,470","title":"Add Graphics"},{"action":"gcx:wf:arcgis::CreateGraphic","description":"Here you add the geometry and attributes from the features converted from the Shapefile and symbolize.\n\n**The attributes are not put in here since they are a bit more advanced based on an array mapping at**:\\\n`attributes._emitter.target._originalMap`\\\nhowever this is where you would include them if you needed them later.","id":1095,"inputs":{"geometry":{"accessors":["$forEachShapefileFeature"],"annotations":[{"count":24,"index":0,"kind":"idref"}],"code":"$forEachShapefileFeature.item.geometry","source":"$forEachShapefileFeature.item.geometry"},"symbol":{"accessors":["$symbolShapfile"],"annotations":[{"count":15,"index":0,"kind":"idref"}],"code":"$symbolShapfile.symbol","source":"$symbolShapfile.symbol"}},"name":"featureFromShapefile","position":"-30,90","title":"Create Feature","transitions":[{"id":1099,"inputs":{},"position":"90,440 90,470","sourceConnector":"bottom","target":{"id":1093},"targetConnector":"top"}]},{"id":1097,"inputs":{},"position":"0,0","purpose":"start","title":"For Each","transitions":[{"id":1154,"position":"90,60 90,90","sourceConnector":"bottom","target":{"id":1095},"targetConnector":"top"}]}]}],"deploymentConfig":{"supportedApps":{"GWV":true}},"designerVersion":"5.27.1+8","forms":[{"defaults":{},"elements":{"filePickerShapefile":{"description":{"markdown":"**Shapefiles will only work with `results.from-shapefile` as  `(.zip)` files.**\n\nBelow are the critical file components each zip file must contain to produce a valid output:\n- `.shp` - geometry\n- `.prj` - projection\n- `.dbf` - data table\n- `.shx` - index"},"enabled":true,"fileTypes":".zip","index":0,"prompt":{"markdown":"Add .zip file"},"require":true,"rowIndex":0,"rowNumber":0,"size":20,"title":{"markdown":"Upload File"},"type":"FilePicker","visible":true},"footer":{"enabled":true,"items":{"0":{"index":0,"label":{"markdown":"Close"},"validates":false,"value":"close"}},"section":"footer","type":"ButtonBar"},"header":{"section":"header","title":{"markdown":"Shapefile Uploader"},"type":"Header"}},"id":229}],"start":{"id":3},"steps":[{"id":147,"inputs":{}}],"transitions":[{"branch":"changed$filePickerShapefile","id":323,"inputs":{},"source":{"id":231},"target":{"id":322}},{"branch":"loop","id":1115,"inputs":{},"source":{"id":1105},"target":{"id":1097}}]}
    0
  • Sean McClurkan

    I'm using the example above for the ShapefileUploader.json, but I can't seem to find a syntax for getting the geometry out of the shapefile.

    The example uses the $forEach loop with the RunOperation result as:

    $forEachShapefileFeature.item.geometry

    Where the Loop Items are:

    $runOperationShapefileToFeatures.result

    When I try to use this syntax, the geometry is undefined.  The shapefile I'm using works when I upload it in an HTML5 workflow using a widget, but not in Web.

    I've tried:

    $runOperationShapefileToFeatures.result.geometry

    $runOperationShapefileToFeatures.result.Feature.geometry

    $runOperationShapefileToFeatures.result.feature.geometry

    $runOperationShapefileToFeatures.result[0].geometry

    But all return undefined.  Any help would be appreciated.

    0
  • Alan Clack

    Sean McClurkan 
    I assume you were using my code as an option. Even though that tool is a few versions behind I believe it should still work. Since it sounds like its working for Widgets but not other web components I would double check to make sure that your upload blob is being processed correctly.

    • The upload should be a .zip Shapefile that contains the four required components (.shp, .prj, .dbf, .shx). A blob without these is still a “valid” blob, but will hit errors when processing the Shapefile. I can't think of a huge difference between web and widget where things may be assumed, but just a sanity check.
       
    • The output of the $runOperationShapefileToFeatures.result is a @vertigis.arcgis-extensions.data.FeatureSet.FeatureSet which is not the same as something like @arcgis.core.rest.support.FeatureSet or @arcgis.core.Graphic which a lot of VertiGIS users may be more used to working with. These are both geometry-style objects with geometry, but they have very different organization for their objects and you may be expecting the geometry to be an attribute in the wrong location hence why its showing up as undefined. Hopefully you can log the output as a whole with .result as opposed to going specifically for the geometry to try and find it and map it out correctly. See VertiGIS Commands for results.to-graphics and/or results.from-graphics to convert between the objects you would prefer to work with.
       
    • The last thing I can think of is that depending on your workflow you may need to ensure you're passing along everything with an appropriate scope. A lot of tools like this I have seen are built through multiple forms or steps. Scope is very likely a factor in that your Shapefile blob output is being lost along the way somewhere since it works on a widget and not web. If the Shapefile blob is not stored in an appropriate scope the next part of the workflow, tool, or form will not have any idea it exists and will not be a valid output to pull from later. Sadly, I cannot check your link since I'd need to log in, but hopefully one of these options makes sense and helps you identify the problem.
    0

Du måste logga in om du vill lämna en kommentar.