diff --git a/configure/public/toolConfigs.json b/configure/public/toolConfigs.json index f12dd1390..8bd51a45b 100644 --- a/configure/public/toolConfigs.json +++ b/configure/public/toolConfigs.json @@ -1 +1 @@ -{"Identifier":{"defaultIcon":"map-marker","description":"Mouse over the map for a by-pixel legend of a raster.","descriptionFull":{"title":"Mouse over to query underlying datasets. This will read the raw values from a geo-referenced dataset, which can be any bit-depth (8,16,32). You can set up multiple file to return values from.","example":{"[Layer_Name]":{"url":"(str) path_to_data/data.tif","bands":"(int) how many bands to query from","sigfigs":"(int) how many digits after the decimal","unit":"(str) whatever string unit","timeFormat":"(str) for formatting injected '{starttime}' and '{endtime}' in url. See syntax in https://d3js.org/d3-time-format#locale_format"},"...":{}}},"hasVars":true,"name":"Identifier","toolbarPriority":1,"separatedTool":true,"paths":{"IdentifierTool":"essence/Tools/Identifier/IdentifierTool"},"config":{"rows":[{"components":[{"field":"separatedTool","name":"Separated Tool","description":"If true, this tool will live outside the left-hand toolbar and be independently accessible.","type":"checkbox","width":3,"defaultChecked":true},{"field":"variables.justification","name":"Justification","description":"The legend will display on the right side of the screen if set to right, otherwise default to the left side","type":"dropdown","width":2,"options":["left","right"]}]},{"components":[{"field":"variables.layers","name":"Layers","description":"Only show DEM if associated layer is on.","type":"objectarray","width":12,"object":[{"field":"name","name":"Layer Name or UUID","description":"This is the layer name exactly as it appears in the Layers section in the configuration.","type":"text","width":4},{"field":"url","name":"URL to .tif","description":"This can be a relative path to a file under the Mission name or a full url path. The former is preferred is the file is large. Can use '{starttime}' and '{endtime}' if the layer is time enabled. If this field is left empty, the Identifier Tool will try to best-match the hovered-over pixel color with this layer's legend (if any).","type":"text","width":8},{"field":"bands","name":"Bands","description":"Number of bands from which to query.","type":"number","min":0,"step":1,"width":2},{"field":"sigfigs","name":"SigFigs","description":"Number of significant figures to use after the decimal of returned values.","type":"number","min":0,"step":1,"width":2},{"field":"unit","name":"Unit","description":"A string that is appended to your returned value. e.g. ' m' would be appended on a raw value ('41') and show '41 m'. If it was 'm', it would return '41m', without a space.","type":"text","width":2},{"field":"scalefactor","name":"Scale Factor","description":"A number for which to multiply the raw value by for display purposes only. Useful, for instance, if the underlying dataset is in units that are off by factor's of 10 from what's desired to be shown to users.","type":"number","width":2},{"field":"timeFormat","name":"Time Format","description":"A string for formatting the injected '{starttime}' and '{endtime}' in the url. See syntax in https://d3js.org/d3-time-format#locale_format","type":"text","width":4}]}]}]}},"Layers":{"defaultIcon":"layers","description":"Hierarchically toggle layers on and off and alter their opacities.","descriptionFull":{"title":"Allows users to toggle on and off layers, download them, filter their features and change some parameters such as opacity.","example":{"expanded":"(bool) is initial state expanded [default false]"}},"hasVars":true,"name":"Layers","toolbarPriority":1,"paths":{"LayersTool":"essence/Tools/Layers/LayersTool"},"expandable":true,"config":{"rows":[{"components":[{"field":"variables.expanded","name":"Expanded","description":"Whether all layer groupings default to being expanded (as opposed to being collapsed).","type":"checkbox","width":3,"defaultChecked":false}]}]}},"Legend":{"defaultIcon":"map-legend","description":"Show a chart legend that maps colors and symbols to meaning.","descriptionFull":{"title":"A layer can be configured with a legend by pointing its Legend field to a .csv file or by including a JSON legend array into the layer's Raw Variables. The Legend Tool renders symbologies and gradient scales for any properly configured on layer.","example":{"displayOnStart":true,"justification":"right"}},"hasVars":true,"name":"Legend","toolbarPriority":2,"separatedTool":true,"paths":{"LegendTool":"essence/Tools/Legend/LegendTool"},"config":{"rows":[{"components":[{"field":"separatedTool","name":"Separated Tool","description":"If true, this tool will live outside the left-hand toolbar and be independently accessible.","type":"checkbox","width":3,"defaultChecked":true},{"field":"variables.displayOnStart","name":"Display on Start","description":"Whether the expanded legend should automatically be displayed on start.","type":"checkbox","width":3,"defaultChecked":false},{"field":"variables.justification","name":"Justification","description":"The legend will display on the right side of the screen if set to right, otherwise default to the left side","type":"dropdown","width":2,"options":["left","right"]}]}]}},"Info":{"defaultIcon":"information-variant","description":"Display the geojson properties field of a clicked feature.","descriptionFull":{"title":"Lists out the geojson properties of any clicked feature. Any clicked feature will open the Info tool and display the data in JSON formatting. Some layer 'kinds' disable opening the Info tool and displaying data automatically, like the 'Waypoints' kind layer.","example":{"sortAlphabetically":true}},"hasVars":true,"name":"Info","toolbarPriority":3,"paths":{"InfoTool":"essence/Tools/Info/InfoTool"},"expandable":true,"config":{"rows":[{"components":[{"field":"variables.sortAlphabetically","name":"Sort Alphabetically","description":"Whether to sort the feature's fields alphabetically instead of listing them in their native order.","type":"checkbox","width":3,"defaultChecked":false}]}]}},"Sites":{"defaultIcon":"pin","description":"A button bar to navigate between various map locations.","descriptionFull":{"title":"A button bar to quickly navigate between preset map locations.","example":{"sites":[{"name":"(str) Name of site","code":"(str) Unique identifier. Can match header layer to toggle it's sublayers","view":["(num) Latitude","(num) Longitude","(num) Zoom level"]},{"...":"..."}]}},"hasVars":true,"name":"Sites","toolbarPriority":4,"paths":{"SitesTool":"essence/Tools/Sites/SitesTool"},"config":{"rows":[{"components":[{"field":"variables.sites","name":"Sites","description":"","type":"objectarray","width":12,"object":[{"field":"name","name":"Name","description":"Name of site. Required.","type":"text","width":4},{"field":"code","name":"Code","description":"Unique identifier. Can match header layer to toggle its sublayers. Required.","type":"text","width":2},{"field":"lat","name":"Latitude","description":"","type":"number","width":2},{"field":"lng","name":"Longitude","description":"","type":"number","width":2},{"field":"zoom","name":"Zoom Level","description":"","type":"number","min":0,"step":1,"width":2}]}]}]}},"Isochrone":{"defaultIcon":"circle-double","description":"Find the range of locations accessible to an explorer within a given time.","descriptionFull":{"title":"Given a user-defined starting point, render a shaded region where colors indicate minimum travel time or resource expenditure to reach a given location. Hover over the region to view the least costly path from the start to the cursor. Costs are calculated based on selectable and configurable models, which may each require multiple different tilesets as input.","example":{"data":{"DEM":[{"name":"Unique Name 1","tileurl":"Layers/Example/{z}/{x}/{y}.png","minZoom":8,"maxNativeZoom":18,"resolution":256,"interpolateSeams":true},{"...":"..."}],"slope":[{"...":"..."}],"cost":[{"...":"..."}]},"interpolateSeams":false,"models":["Traverse Time","Isodistance","..."]}},"hasVars":true,"name":"Isochrone","toolbarPriority":10,"paths":{"IsochroneTool":"essence/Tools/Isochrone/IsochroneTool"},"config":{"rows":[{"name":"Data Sources","components":[{"field":"variables.data.DEM","name":"Elevation (DEM)","description":"Configure DEM data tilesets to be used by the specified models for computations.","type":"objectarray","width":12,"object":[{"field":"name","name":"Name","description":"A unique name.","type":"text","width":4},{"field":"tileurl","name":"DEM Tile URL","description":"","type":"text","width":8},{"field":"minZoom","name":"Minimum Zoom","description":"Minimum zoom of the specified tileset.","type":"number","min":0,"step":1,"width":2},{"field":"maxNativeZoom","name":"Max Native Zoom","description":"Maximum (native) zoom of the specified tileset.","type":"number","min":0,"step":1,"max":40,"width":2},{"field":"resolution","name":"Resolution","description":"Pixel dimension of the side of the tiles in the tileset. Generally a power of 2 between 32 and 256.","type":"number","min":0,"step":1,"width":2},{"field":"interpolateSeams","name":"Interpolate Seams","description":"Because '1bto4b' (the DEM tiling script) generates tiles with matching edges, data loaded and passed to models may have “seams,” or regularly-spaced pairs of identical rows and columns. Depending on the data type and model, these seams may or may not cause inaccurate results. The default behavior of the tool is therefore to attempt to correct these seams.","type":"checkbox","width":3,"defaultChecked":false}]}]},{"components":[{"field":"variables.data.slope","name":"Slope","description":"Configure Slope data tilesets to be used by the specified models for computations.","type":"objectarray","width":12,"object":[{"field":"name","name":"Name","description":"A unique name.","type":"text","width":4},{"field":"tileurl","name":"DEM Tile URL","description":"","type":"text","width":8},{"field":"minZoom","name":"Minimum Zoom","description":"Minimum zoom of the specified tileset.","type":"number","min":0,"step":1,"width":2},{"field":"maxNativeZoom","name":"Max Native Zoom","description":"Maximum (native) zoom of the specified tileset.","type":"number","min":0,"step":1,"max":40,"width":2},{"field":"resolution","name":"Resolution","description":"Pixel dimension of the side of the tiles in the tileset. Generally a power of 2 between 32 and 256.","type":"number","min":0,"step":1,"width":2},{"field":"interpolateSeams","name":"Interpolate Seams","description":"Because '1bto4b' (the DEM tiling script) generates tiles with matching edges, data loaded and passed to models may have “seams,” or regularly-spaced pairs of identical rows and columns. Depending on the data type and model, these seams may or may not cause inaccurate results. The default behavior of the tool is therefore to attempt to correct these seams.","type":"checkbox","width":3,"defaultChecked":false}]}]},{"components":[{"field":"variables.data.obstacle","name":"Obstacle","description":"Configure Obstacle map data tilesets to be used by the specified models for computations.","type":"objectarray","width":12,"object":[{"field":"name","name":"Name","description":"A unique name.","type":"text","width":4},{"field":"tileurl","name":"DEM Tile URL","description":"","type":"text","width":8},{"field":"minZoom","name":"Minimum Zoom","description":"Minimum zoom of the specified tileset.","type":"number","min":0,"step":1,"width":2},{"field":"maxNativeZoom","name":"Max Native Zoom","description":"Maximum (native) zoom of the specified tileset.","type":"number","min":0,"step":1,"max":40,"width":2},{"field":"resolution","name":"Resolution","description":"Pixel dimension of the side of the tiles in the tileset. Generally a power of 2 between 32 and 256.","type":"number","min":0,"step":1,"width":2},{"field":"interpolateSeams","name":"Interpolate Seams","description":"Because '1bto4b' (the DEM tiling script) generates tiles with matching edges, data loaded and passed to models may have “seams,” or regularly-spaced pairs of identical rows and columns. Depending on the data type and model, these seams may or may not cause inaccurate results. The default behavior of the tool is therefore to attempt to correct these seams.","type":"checkbox","width":3,"defaultChecked":false}]}]},{"components":[{"field":"variables.data.cost","name":"Cost","description":"Configure Cost data tilesets to be used by the specified models for computations.","type":"objectarray","width":12,"object":[{"field":"name","name":"Name","description":"A unique name.","type":"text","width":4},{"field":"tileurl","name":"DEM Tile URL","description":"","type":"text","width":8},{"field":"minZoom","name":"Minimum Zoom","description":"Minimum zoom of the specified tileset.","type":"number","min":0,"step":1,"width":2},{"field":"maxNativeZoom","name":"Max Native Zoom","description":"Maximum (native) zoom of the specified tileset.","type":"number","min":0,"step":1,"max":40,"width":2},{"field":"resolution","name":"Resolution","description":"Pixel dimension of the side of the tiles in the tileset. Generally a power of 2 between 32 and 256.","type":"number","min":0,"step":1,"width":2},{"field":"interpolateSeams","name":"Interpolate Seams","description":"Because '1bto4b' (the DEM tiling script) generates tiles with matching edges, data loaded and passed to models may have “seams,” or regularly-spaced pairs of identical rows and columns. Depending on the data type and model, these seams may or may not cause inaccurate results. The default behavior of the tool is therefore to attempt to correct these seams.","type":"checkbox","width":3,"defaultChecked":false}]}]},{"components":[{"field":"variables.data.shade","name":"Shade","description":"Configure Shade data tilesets to be used by the specified models for computations.","type":"objectarray","width":12,"object":[{"field":"name","name":"Name","description":"A unique name.","type":"text","width":4},{"field":"tileurl","name":"DEM Tile URL","description":"","type":"text","width":8},{"field":"minZoom","name":"Minimum Zoom","description":"Minimum zoom of the specified tileset.","type":"number","min":0,"step":1,"width":2},{"field":"maxNativeZoom","name":"Max Native Zoom","description":"Maximum (native) zoom of the specified tileset.","type":"number","min":0,"step":1,"max":40,"width":2},{"field":"resolution","name":"Resolution","description":"Pixel dimension of the side of the tiles in the tileset. Generally a power of 2 between 32 and 256.","type":"number","min":0,"step":1,"width":2},{"field":"interpolateSeams","name":"Interpolate Seams","description":"Because '1bto4b' (the DEM tiling script) generates tiles with matching edges, data loaded and passed to models may have “seams,” or regularly-spaced pairs of identical rows and columns. Depending on the data type and model, these seams may or may not cause inaccurate results. The default behavior of the tool is therefore to attempt to correct these seams.","type":"checkbox","width":3,"defaultChecked":false}]}]},{"name":"Models","components":[{"field":"variables.models","name":"Enabled Models","description":"Comma-separated list of isochrone models to enable. Possible values are: 'Traverse Time', 'Isodistance', 'Example' ","type":"textarray","width":12}]},{"name":"Settings","components":[{"field":"variables.interpolateSeams","name":"Interpolate Seams (Global)","description":"Because '1bto4b' (the DEM tiling script) generates tiles with matching edges, data loaded and passed to models may have “seams,” or regularly-spaced pairs of identical rows and columns. Depending on the data type and model, these seams may or may not cause inaccurate results. The default behavior of the tool is therefore to attempt to correct these seams. Set this property to false to disable this behavior for all sources that do not explicitly set their own 'interpolateSeams' property to true.","type":"checkbox","width":3,"defaultChecked":false}]}]}},"Viewshed":{"defaultIcon":"wifi-strength-2","description":"Realtime user generated viewsheds.","descriptionFull":{"title":"Renders dynamic tilesets based on line-of-sight visibilities from user defined source points. DEM tiles are used to generate these. At least one DEM tileset must be configured. curvature is optional and can be set to false to disable using the Major Radius to account for curvature during generations. cameraPresets are optional and the objects within only require the name field.","example":{"data":[{"name":"Unique Name 1","demtileurl":"Layers/Example/demtileset/{z}/{x}/{y}.png","minZoom":8,"maxNativeZoom":18},{"...":"..."}],"curvature":false,"cameraPresets":[{"name":"CAM A","height":2,"azCenter":0,"azFOV":70,"elCenter":-10,"elFOV":30},{"...":"..."}],"defaultObserverHeight":2,"defaultTargetHeight":0}},"hasVars":true,"name":"Viewshed","toolbarPriority":101,"paths":{"ViewshedTool":"essence/Tools/Viewshed/ViewshedTool","ViewshedTool_Manager":"essence/Tools/Viewshed/ViewshedTool_Manager","ViewshedTool_Algorithm":"essence/Tools/Viewshed/ViewshedTool_Algorithm"},"config":{"rows":[{"components":[{"field":"variables.data","name":"Layer specific DEMs","description":"Only show DEM if associated layer is on.","type":"objectarray","width":12,"object":[{"field":"name","name":"Name","description":"User-friendly name for DEM","type":"text","width":2},{"field":"demtileurl","name":"DEM Path","description":"","type":"text","width":8},{"field":"minZoom","name":"Minimum Zoom","description":"","type":"number","min":0,"step":1,"width":1},{"field":"maxNativeZoom","name":"Maximum Native Zoom","description":"","type":"number","min":0,"step":1,"width":1}]}]},{"components":[{"field":"variables.cameraPresets","name":"Camera Presets","description":"Only show DEM if associated layer is on.","type":"objectarray","width":12,"object":[{"field":"name","name":"Name","description":"Camera Name","type":"text","width":10},{"field":"height","name":"Height","description":"Height in meters","type":"number","min":0,"width":2},{"field":"azCenter","name":"Azimuth Center","description":"","type":"number","width":3},{"field":"azFOV","name":"Azimuth FOV","description":"","type":"number","width":3},{"field":"elCenter","name":"Elevation Center","description":"","type":"number","width":3},{"field":"elFOV","name":"Elevation FOV","description":"","type":"number","width":3}]}]},{"components":[{"field":"variables.curvature","name":"Curvature","description":"Whether to account for planetary curvature while computing viewsheds.","type":"checkbox","width":3,"defaultChecked":false}]}]}},"Shade":{"defaultIcon":"sun-angle-outline","description":"Realtime user generated sun and orbiter masks.","descriptionFull":{"title":"Shades the ground when line-of-sights to an orbiting target are occluded.","example":{"dem":"Data/missionDEM.tif","data":[{"name":"User-friendly name for DEM","demtileurl":"pathToDEMTiles/{z}/{x}/{y}.png","minZoom":8,"maxNativeZoom":18}],"sources":[{"name":"User-friendly name for orbiter or body that 'casts shadows'","value":"NAIF SPICE Spacecraft name or ID"},{"name":"...","value":"..."}],"observers":[{"name":"User-friendly name for observer for spacecraft time computations. Set to null to turn off time converting.","value":"SPICE Spacecraft name or ID","frame":"SPICE reference frame. i.e. IAU_MARS","body":"SPICE planet body. i.e. MARS"}],"defaultHeight":0,"observerTimePlaceholder":null,"utcTimeFormat":null}},"hasVars":true,"name":"Shade","toolbarPriority":102,"paths":{"ShadeTool":"essence/Tools/Shade/ShadeTool","ShadeTool_Manager":"essence/Tools/Shade/ShadeTool_Algorithm","ShadeTool_Algorithm":"essence/Tools/Shade/ShadeTool_Algorithm"},"config":{"rows":[{"components":[{"field":"variables.dem","name":"DEM path","description":"A path to a DEM.tif. This is used to get the current center elevation. This can/should be the same file used for the Measure Tool and the Coordinate's elevation.","type":"text","width":12}]},{"components":[{"field":"variables.data","name":"Layer specific DEMs","description":"At minimum, the Shade tool requires at least one 'data' source. A data source describes a DEM tileset (see /auxiliary/gdal2customtiles or /auxiliary/1bto4b) and allows users to select it by name to generate shade maps over.","type":"objectarray","width":12,"object":[{"field":"name","name":"Name","description":"User-friendly name for DEM","type":"text","width":2},{"field":"demtileurl","name":"DEM Path","description":"","type":"text","width":8},{"field":"minZoom","name":"Minimum Zoom","description":"","type":"number","min":0,"step":1,"width":1},{"field":"maxNativeZoom","name":"Maximum Native Zoom","description":"","type":"number","min":0,"step":1,"width":1}]}]},{"components":[{"field":"variables.sources","name":"Sources","description":"An array of objects with the properties 'name' and 'value'. 'name' is the display name for the Source Entity dropdown. 'value' is the SPICE spacecraft ID that gets passed to the backend ll2aerll.py script. Ensure the right kernels for the configured source entities/targets exist in /private/api/spice/kernels.","type":"objectarray","width":12,"object":[{"field":"name","name":"Name","description":"User-friendly name for orbiter or body that 'casts light'","type":"text","width":4},{"field":"value","name":"Value","description":"NAIF SPICE Spacecraft name or ID","type":"text","width":4}]}]},{"components":[{"field":"variables.observers","name":"Observers","description":"An array of objects with the properties 'name' and 'value'. 'name' is the display name for the Source Entity dropdown. 'value' is the SPICE spacecraft ID that gets passed to the backend chronos.py scripts. Ensure the right kernels for the configured observers exist in /private/api/spice/kernels and that there is a proper chronos setup file for each observer's value private/api/spice/chronosSetups/chronos-{lowercased_observer_value}.setup.","type":"objectarray","width":12,"object":[{"field":"name","name":"Name","description":"User-friendly name for observer for spacecraft time computations","type":"text","width":3},{"field":"value","name":"Value","description":"NAIF SPICE Spacecraft name or ID","type":"text","width":3},{"field":"frame","name":"Frame","description":"SPICE reference frame. i.e. 'IAU_MARS'","type":"text","width":3},{"field":"body","name":"Body","description":"SPICE planet body. i.e. 'MARS'","type":"text","width":3}]}]},{"components":[{"field":"variables.defaultHeight","name":"Default Height","description":"Sets a default for the 'Height' parameter. Height in meters above the surface to use when calculating line-of-sight shading. For instance, a point on the surface (0m) may not be visible to a 'Source Entity', say the Mars Reconnaissance Orbiter (MRO), but 2m above that point may be. This value does not only apply to the center longitude and latitude but to all points on the visible terrain. Gradually increasing this value shows the shade map n-meters above the surface. The regular default is 0 meters.","type":"number","min":0,"width":4},{"field":"variables.observerTimePlaceholder","name":"Observer Time Placeholder","description":"Sets the placeholder information for when the observer time's input box is cleared. Useful for denoting the expected time format to be inputted. For example “SOL DDDD HH:MM:SS”. Default null.","type":"text","width":4},{"field":"variables.utcTimeFormat","name":"UTC Time Format","description":"Sets the placeholder information for when the observer time's input box is cleared. Useful for denoting the expected time format to be inputted. Uses d3 time syntax (https://d3js.org/d3-time-format#locale_format). Example for day-of-year: '%Y-%j %H:%M:%S'. Defaults to times like so: 2023 SEP 06 19:27:05.","type":"text","width":4}]}]}},"Chemistry":{"defaultIcon":"flask","description":"Display chemistry percentages via graphs of a clicked point.","descriptionFull":{},"hasVars":false,"name":"Chemistry","paths":{"ChemistryTool":"essence/Tools/Chemistry/ChemistryTool"}},"Curtain":{"defaultIcon":"waves","description":"Curtain views of Ground Penetrating Radar data.","descriptionFull":{"title":"Vertical imagery aligned under terrain for visualizing data from ground penetrating radar.","example":{"withCredentials":false}},"hasVars":true,"name":"Curtain","paths":{"CurtainTool":"essence/Tools/Curtain/CurtainTool"},"config":{"rows":[{"components":[{"field":"variables.withCredentials","name":"With Credentials","description":"","type":"checkbox","width":3,"defaultChecked":false}]}]}},"Kinds":{"defaultIcon":"palette-swatch","description":"Not a real tool but plugin to configure different layer interactions.","descriptionFull":{},"hasVars":false,"name":"Kinds","kinds":["info","waypoint","chemistry_tool","draw_tool"],"paths":{"Kinds":"essence/Tools/Kinds/Kinds"}},"Measure":{"defaultIcon":"tape-measure","description":"Measure distances and generates elevation profiles.","descriptionFull":{"title":"Specify a path to a Digital Elevation Model (dem) .tif. Measure distances and generates elevation profiles. Can also query specific bands at specific points of images and generate profiles of them. If multiple dems are specified, a dropdown will be present for users to toggle between them.","example":{"dem":"(str) path to Data/defaultDEM.tif","layerDems":{"[layer_name]":"(str) path/to/layers/dem.tif"},"onlyShowDemIfLayerOn":true,"defaultMode":"segment || continuous || continuous_color"}},"hasVars":true,"name":"Measure","paths":{"MeasureTool":"essence/Tools/Measure/MeasureTool"},"config":{"rows":[{"components":[{"field":"variables.dem","name":"DEM path","description":"Path to a primary DEM (such as Data/defaultDEM.tif). Required if Layer Specific DEMs is unset.","type":"text","width":12}]},{"components":[{"field":"variables.layerDems","name":"Layer Specific DEMs","description":"Object of layer names and the paths to their DEMs. Users may switch between DEMs to profile via a dropdown. The dropdown only renders if there is more than one DEM configured overall.","type":"objectarray","width":12,"object":[{"field":"layer","name":"Layer Name","description":"","type":"text","width":4},{"field":"dem","name":"DEM Path","description":"","type":"text","width":8}]}]},{"components":[{"field":"variables.onlyShowDemIfLayerOn","name":"Only Show DEM If On","description":"If true, hides the configured Layer Specific DEMs of off layers from the tool's DEM selection dropdown. If false, all Layer Specific DEMs, even with invalid layer names, always show in the dropdown.","type":"checkbox","width":2,"defaultChecked":false}]},{"components":[{"field":"variables.defaultMode","name":"Default Mode","description":"Which measurement mode to default to. Options are 'segment', 'continuous' and 'continuous_color'","type":"dropdown","width":2,"options":["segment","continuous","continuous_color"]}]}]}},"Draw":{"defaultIcon":"pencil","description":"Advanced and collaborative map drawing.","descriptionFull":{"title":"The Draw tool is an advanced vector data creation and editing tool supporting a multi-user environment. Users can create and manage their own files which can have points, lines, and polygons as well as arrows and text to support annotation. Files can be viewed between users and features copied from one file to another.","example":{"intents":["Polygon_1_Alias","Polygon_2_Alias","Polygon_3_Alias","Line_Alias","Point_Alias","All_Alias"],"defaultDrawClipping":"over || under || off","defaultPublicFilter":false,"defaultYoursOnlyFilter":true,"defaultOnFilter":false,"leadsCanEditFileInfo":false,"hoverLengthOnLines":false,"templates":{"myTemplate":[{"type":"slider","field":"a","min":0,"max":100,"step":1,"default":0},{"type":"number","field":"b","min":0,"max":100,"step":1,"required":true,"default":3},{"type":"text","field":"c","minLength":2,"maxLength":4,"required":true,"regex":null,"default":null},{"type":"textarea","field":"d","maxLength":10,"required":true,"default":"hi"},{"type":"checkbox","field":"e","default":true},{"type":"dropdown","field":"f","items":["Yes","No","Maybe"],"default":"No"},{"type":"incrementer","field":"g","default":"ID-#"},{"type":"date","field":"h","format":"HH:mm:ss","default":"now"}]}}},"hasVars":true,"name":"Draw","toolbarPriority":1001,"paths":{"DrawTool":"essence/Tools/Draw/DrawTool"},"tests":{"DrawToolTest":"essence/Tools/Draw/DrawTool.test"},"expandable":true,"config":{"rows":[{"name":"Intent Aliases","description":"There are five files that are group editable with the correct permission. The group authentication is set an environment variable in the .env file during startup. These files are meant as collaborative layers that a only a few people will manage and contribute to do to the potential of race conditions on who did the last edit.","components":[{"field":"variables.intents.0","name":"Polygon 1 Alias","description":"","type":"text","width":2},{"field":"variables.intents.1","name":"Polygon 2 Alias","description":"","type":"text","width":2},{"field":"variables.intents.2","name":"Polygon 3 Alias","description":"","type":"text","width":2},{"field":"variables.intents.3","name":"Line Alias","description":"","type":"text","width":2},{"field":"variables.intents.4","name":"Point Alias","description":"","type":"text","width":2},{"field":"variables.intents.5","name":"All Alias","description":"","type":"text","width":2}]},{"components":[{"field":"variables.defaultDrawClipping","name":"Default Draw Clipping","description":"Default clipping mode for drawing. Drawing a polygon Over another would clip away that other polygon. Drawing a polygon Under another would have that polygon clip away the newly drawn one. When the clipping mode is Off, no clipping occurs. Users may freely change the clipping mode.","type":"dropdown","width":3,"options":["over","under","off"]},{"field":"variables.leadsCanEditFileInfo","name":"Leads Can Edit File Info","description":"If true, lead roles can edit the file info, (name, description, tags, folder, make private) of any user's public file.","type":"checkbox","width":3,"defaultChecked":false},{"field":"variables.hoverLengthOnLines","name":"Hover Length On Lines","description":"If true, the hover text for line features will include the total length of the line in meters.","type":"checkbox","width":3,"defaultChecked":false}]},{"components":[{"field":"variables.defaultPublicFilter","name":"Default Public Filter","description":"When the DrawTool first opens, filter the file list down to only public files or not.","type":"checkbox","width":4,"defaultChecked":false},{"field":"variables.defaultYoursOnlyFilter","name":"Default Yours Only Filter","description":"When the DrawTool first opens, filter the file list down to only files you own or not.","type":"checkbox","width":4,"defaultChecked":true},{"field":"variables.defaultOnFilter","name":"Default On Filter","description":"When the DrawTool first opens, filter the file list down to only files that are on or not. ","type":"checkbox","width":4,"defaultChecked":false}]},{"components":[{"field":"variables.templates","name":"Default File Property Templates","description":"Templates create forms for feature properties. For instance, all features in a given draw file could, in the feature's edit panel, have the field “Reviewed” be togglable via a checkbox. Users may make their own templates too but the ones configured here are promoted and cannot be delete.","type":"objectarray","width":12,"object":[{"field":"name","name":"Template Name","description":"","type":"text","width":4},{"field":"name","name":"Property Field Name","description":"","type":"text","width":4},{"field":"type","name":"Component","description":"","type":"dropdown","width":2,"options":["slider","number","text","textarea","checkbox","dropdown","incrementer","date"]},{"field":"required","name":"Required","description":"Field requires entry.","type":"checkbox","width":2,"defaultChecked":false},{"field":"min","name":"Min Value","description":"For Slider and Number","type":"number","width":4},{"field":"max","name":"Max Value","description":"For Slider and Number","type":"number","width":4},{"field":"step","name":"Step Size","description":"For Slider and Number","type":"number","width":4},{"field":"minLength","name":"Min Length","description":"For Text and Textarea","type":"number","width":4},{"field":"maxLength","name":"Max Length","description":"For Text and Textarea","type":"number","width":4},{"field":"regex","name":"Regex","description":"For Text and Textarea","type":"text","width":3},{"field":"items","name":"Dropdown Items","description":"Comma-separated. For dropdown","type":"text","width":6},{"field":"format","name":"Date Format","description":"For date","type":"text","width":3},{"field":"default","name":"Default Value","description":"For all types","type":"text","width":3},{"field":"intersectedGeodataset","name":"Intersect GeoDataset","description":"Templated fields can be auto-populated based on whether the drawn feature's shape intersecting feature's from an underlying GeoDataset.","type":"text","width":4},{"field":"intersectedProp","name":"Intersected Property Name","description":"The properties field/path whose value should be used when auto-populating this template field.","type":"text","width":4},{"field":"intersectedConflict","name":"Intersection Conflict","description":"In case the drawn shape intersects no features or multiple features, what to do: Default to 'Default Value'? Set the field's value to 'null'? Use the properties of the first intersected GeoDataset feature? Use the properties of the last intersected GeoDataset feature? If possible, set the field to a comma-separated string of the values from each intersected feature.","type":"dropdown","width":4,"options":["default","null","first","last","array"]}]}]}]}}} \ No newline at end of file +{"Identifier":{"defaultIcon":"map-marker","description":"Mouse over the map for a by-pixel legend of a raster.","descriptionFull":{"title":"Mouse over to query underlying datasets. This will read the raw values from a geo-referenced dataset, which can be any bit-depth (8,16,32). You can set up multiple file to return values from.","example":{"[Layer_Name]":{"url":"(str) path_to_data/data.tif","bands":"(int) how many bands to query from","sigfigs":"(int) how many digits after the decimal","unit":"(str) whatever string unit","timeFormat":"(str) for formatting injected '{starttime}' and '{endtime}' in url. See syntax in https://d3js.org/d3-time-format#locale_format"},"...":{}}},"hasVars":true,"name":"Identifier","toolbarPriority":1,"separatedTool":true,"paths":{"IdentifierTool":"essence/Tools/Identifier/IdentifierTool"},"config":{"rows":[{"components":[{"field":"separatedTool","name":"Separated Tool","description":"If true, this tool will live outside the left-hand toolbar and be independently accessible.","type":"checkbox","width":3,"defaultChecked":true},{"field":"variables.justification","name":"Justification","description":"The legend will display on the right side of the screen if set to right, otherwise default to the left side","type":"dropdown","width":2,"options":["left","right"]}]},{"components":[{"field":"variables.layers","name":"Layers","description":"Only show DEM if associated layer is on.","type":"objectarray","width":12,"object":[{"field":"name","name":"Layer Name or UUID","description":"This is the layer name exactly as it appears in the Layers section in the configuration.","type":"text","width":4},{"field":"url","name":"URL to .tif","description":"This can be a relative path to a file under the Mission name or a full url path. The former is preferred is the file is large. Can use '{starttime}' and '{endtime}' if the layer is time enabled. If this field is left empty, the Identifier Tool will try to best-match the hovered-over pixel color with this layer's legend (if any).","type":"text","width":8},{"field":"bands","name":"Bands","description":"Number of bands from which to query.","type":"number","min":0,"step":1,"width":2},{"field":"sigfigs","name":"SigFigs","description":"Number of significant figures to use after the decimal of returned values.","type":"number","min":0,"step":1,"width":2},{"field":"unit","name":"Unit","description":"A string that is appended to your returned value. e.g. ' m' would be appended on a raw value ('41') and show '41 m'. If it was 'm', it would return '41m', without a space.","type":"text","width":2},{"field":"scalefactor","name":"Scale Factor","description":"A number for which to multiply the raw value by for display purposes only. Useful, for instance, if the underlying dataset is in units that are off by factor's of 10 from what's desired to be shown to users.","type":"number","width":2},{"field":"timeFormat","name":"Time Format","description":"A string for formatting the injected '{starttime}' and '{endtime}' in the url. See syntax in https://d3js.org/d3-time-format#locale_format","type":"text","width":4}]}]}]}},"Layers":{"defaultIcon":"layers","description":"Hierarchically toggle layers on and off and alter their opacities.","descriptionFull":{"title":"Allows users to toggle on and off layers, download them, filter their features and change some parameters such as opacity.","example":{"expanded":"(bool) is initial state expanded [default false]"}},"hasVars":true,"name":"Layers","toolbarPriority":1,"paths":{"LayersTool":"essence/Tools/Layers/LayersTool"},"expandable":true,"config":{"rows":[{"components":[{"field":"variables.expanded","name":"Expanded","description":"Whether all layer groupings default to being expanded (as opposed to being collapsed).","type":"checkbox","width":3,"defaultChecked":false}]}]}},"Legend":{"defaultIcon":"map-legend","description":"Show a chart legend that maps colors and symbols to meaning.","descriptionFull":{"title":"A layer can be configured with a legend by pointing its Legend field to a .csv file or by including a JSON legend array into the layer's Raw Variables. The Legend Tool renders symbologies and gradient scales for any properly configured on layer.","example":{"displayOnStart":true,"justification":"right"}},"hasVars":true,"name":"Legend","toolbarPriority":2,"separatedTool":true,"paths":{"LegendTool":"essence/Tools/Legend/LegendTool"},"config":{"rows":[{"components":[{"field":"separatedTool","name":"Separated Tool","description":"If true, this tool will live outside the left-hand toolbar and be independently accessible.","type":"checkbox","width":3,"defaultChecked":true},{"field":"variables.displayOnStart","name":"Display on Start","description":"Whether the expanded legend should automatically be displayed on start.","type":"checkbox","width":3,"defaultChecked":false},{"field":"variables.justification","name":"Justification","description":"The legend will display on the right side of the screen if set to right, otherwise default to the left side","type":"dropdown","width":2,"options":["left","right"]},{"field":"variables.showHeadersInLegend","name":"Show Headers in Legend","description":"If true, the legend will display the name of Header layer types.","type":"checkbox","width":3,"defaultChecked":false}]}]}},"Info":{"defaultIcon":"information-variant","description":"Display the geojson properties field of a clicked feature.","descriptionFull":{"title":"Lists out the geojson properties of any clicked feature. Any clicked feature will open the Info tool and display the data in JSON formatting. Some layer 'kinds' disable opening the Info tool and displaying data automatically, like the 'Waypoints' kind layer.","example":{"sortAlphabetically":true}},"hasVars":true,"name":"Info","toolbarPriority":3,"paths":{"InfoTool":"essence/Tools/Info/InfoTool"},"expandable":true,"config":{"rows":[{"components":[{"field":"variables.sortAlphabetically","name":"Sort Alphabetically","description":"Whether to sort the feature's fields alphabetically instead of listing them in their native order.","type":"checkbox","width":3,"defaultChecked":false}]}]}},"Sites":{"defaultIcon":"pin","description":"A button bar to navigate between various map locations.","descriptionFull":{"title":"A button bar to quickly navigate between preset map locations.","example":{"sites":[{"name":"(str) Name of site","code":"(str) Unique identifier. Can match header layer to toggle it's sublayers","view":["(num) Latitude","(num) Longitude","(num) Zoom level"]},{"...":"..."}]}},"hasVars":true,"name":"Sites","toolbarPriority":4,"paths":{"SitesTool":"essence/Tools/Sites/SitesTool"},"config":{"rows":[{"components":[{"field":"variables.sites","name":"Sites","description":"","type":"objectarray","width":12,"object":[{"field":"name","name":"Name","description":"Name of site. Required.","type":"text","width":4},{"field":"code","name":"Code","description":"Unique identifier. Can match header layer to toggle its sublayers. Required.","type":"text","width":2},{"field":"lat","name":"Latitude","description":"","type":"number","width":2},{"field":"lng","name":"Longitude","description":"","type":"number","width":2},{"field":"zoom","name":"Zoom Level","description":"","type":"number","min":0,"step":1,"width":2}]}]}]}},"Isochrone":{"defaultIcon":"circle-double","description":"Find the range of locations accessible to an explorer within a given time.","descriptionFull":{"title":"Given a user-defined starting point, render a shaded region where colors indicate minimum travel time or resource expenditure to reach a given location. Hover over the region to view the least costly path from the start to the cursor. Costs are calculated based on selectable and configurable models, which may each require multiple different tilesets as input.","example":{"data":{"DEM":[{"name":"Unique Name 1","tileurl":"Layers/Example/{z}/{x}/{y}.png","minZoom":8,"maxNativeZoom":18,"resolution":256,"interpolateSeams":true},{"...":"..."}],"slope":[{"...":"..."}],"cost":[{"...":"..."}]},"interpolateSeams":false,"models":["Traverse Time","Isodistance","..."]}},"hasVars":true,"name":"Isochrone","toolbarPriority":10,"paths":{"IsochroneTool":"essence/Tools/Isochrone/IsochroneTool"},"config":{"rows":[{"name":"Data Sources","components":[{"field":"variables.data.DEM","name":"Elevation (DEM)","description":"Configure DEM data tilesets to be used by the specified models for computations.","type":"objectarray","width":12,"object":[{"field":"name","name":"Name","description":"A unique name.","type":"text","width":4},{"field":"tileurl","name":"DEM Tile URL","description":"","type":"text","width":8},{"field":"minZoom","name":"Minimum Zoom","description":"Minimum zoom of the specified tileset.","type":"number","min":0,"step":1,"width":2},{"field":"maxNativeZoom","name":"Max Native Zoom","description":"Maximum (native) zoom of the specified tileset.","type":"number","min":0,"step":1,"max":40,"width":2},{"field":"resolution","name":"Resolution","description":"Pixel dimension of the side of the tiles in the tileset. Generally a power of 2 between 32 and 256.","type":"number","min":0,"step":1,"width":2},{"field":"interpolateSeams","name":"Interpolate Seams","description":"Because '1bto4b' (the DEM tiling script) generates tiles with matching edges, data loaded and passed to models may have “seams,” or regularly-spaced pairs of identical rows and columns. Depending on the data type and model, these seams may or may not cause inaccurate results. The default behavior of the tool is therefore to attempt to correct these seams.","type":"checkbox","width":3,"defaultChecked":false}]}]},{"components":[{"field":"variables.data.slope","name":"Slope","description":"Configure Slope data tilesets to be used by the specified models for computations.","type":"objectarray","width":12,"object":[{"field":"name","name":"Name","description":"A unique name.","type":"text","width":4},{"field":"tileurl","name":"DEM Tile URL","description":"","type":"text","width":8},{"field":"minZoom","name":"Minimum Zoom","description":"Minimum zoom of the specified tileset.","type":"number","min":0,"step":1,"width":2},{"field":"maxNativeZoom","name":"Max Native Zoom","description":"Maximum (native) zoom of the specified tileset.","type":"number","min":0,"step":1,"max":40,"width":2},{"field":"resolution","name":"Resolution","description":"Pixel dimension of the side of the tiles in the tileset. Generally a power of 2 between 32 and 256.","type":"number","min":0,"step":1,"width":2},{"field":"interpolateSeams","name":"Interpolate Seams","description":"Because '1bto4b' (the DEM tiling script) generates tiles with matching edges, data loaded and passed to models may have “seams,” or regularly-spaced pairs of identical rows and columns. Depending on the data type and model, these seams may or may not cause inaccurate results. The default behavior of the tool is therefore to attempt to correct these seams.","type":"checkbox","width":3,"defaultChecked":false}]}]},{"components":[{"field":"variables.data.obstacle","name":"Obstacle","description":"Configure Obstacle map data tilesets to be used by the specified models for computations.","type":"objectarray","width":12,"object":[{"field":"name","name":"Name","description":"A unique name.","type":"text","width":4},{"field":"tileurl","name":"DEM Tile URL","description":"","type":"text","width":8},{"field":"minZoom","name":"Minimum Zoom","description":"Minimum zoom of the specified tileset.","type":"number","min":0,"step":1,"width":2},{"field":"maxNativeZoom","name":"Max Native Zoom","description":"Maximum (native) zoom of the specified tileset.","type":"number","min":0,"step":1,"max":40,"width":2},{"field":"resolution","name":"Resolution","description":"Pixel dimension of the side of the tiles in the tileset. Generally a power of 2 between 32 and 256.","type":"number","min":0,"step":1,"width":2},{"field":"interpolateSeams","name":"Interpolate Seams","description":"Because '1bto4b' (the DEM tiling script) generates tiles with matching edges, data loaded and passed to models may have “seams,” or regularly-spaced pairs of identical rows and columns. Depending on the data type and model, these seams may or may not cause inaccurate results. The default behavior of the tool is therefore to attempt to correct these seams.","type":"checkbox","width":3,"defaultChecked":false}]}]},{"components":[{"field":"variables.data.cost","name":"Cost","description":"Configure Cost data tilesets to be used by the specified models for computations.","type":"objectarray","width":12,"object":[{"field":"name","name":"Name","description":"A unique name.","type":"text","width":4},{"field":"tileurl","name":"DEM Tile URL","description":"","type":"text","width":8},{"field":"minZoom","name":"Minimum Zoom","description":"Minimum zoom of the specified tileset.","type":"number","min":0,"step":1,"width":2},{"field":"maxNativeZoom","name":"Max Native Zoom","description":"Maximum (native) zoom of the specified tileset.","type":"number","min":0,"step":1,"max":40,"width":2},{"field":"resolution","name":"Resolution","description":"Pixel dimension of the side of the tiles in the tileset. Generally a power of 2 between 32 and 256.","type":"number","min":0,"step":1,"width":2},{"field":"interpolateSeams","name":"Interpolate Seams","description":"Because '1bto4b' (the DEM tiling script) generates tiles with matching edges, data loaded and passed to models may have “seams,” or regularly-spaced pairs of identical rows and columns. Depending on the data type and model, these seams may or may not cause inaccurate results. The default behavior of the tool is therefore to attempt to correct these seams.","type":"checkbox","width":3,"defaultChecked":false}]}]},{"components":[{"field":"variables.data.shade","name":"Shade","description":"Configure Shade data tilesets to be used by the specified models for computations.","type":"objectarray","width":12,"object":[{"field":"name","name":"Name","description":"A unique name.","type":"text","width":4},{"field":"tileurl","name":"DEM Tile URL","description":"","type":"text","width":8},{"field":"minZoom","name":"Minimum Zoom","description":"Minimum zoom of the specified tileset.","type":"number","min":0,"step":1,"width":2},{"field":"maxNativeZoom","name":"Max Native Zoom","description":"Maximum (native) zoom of the specified tileset.","type":"number","min":0,"step":1,"max":40,"width":2},{"field":"resolution","name":"Resolution","description":"Pixel dimension of the side of the tiles in the tileset. Generally a power of 2 between 32 and 256.","type":"number","min":0,"step":1,"width":2},{"field":"interpolateSeams","name":"Interpolate Seams","description":"Because '1bto4b' (the DEM tiling script) generates tiles with matching edges, data loaded and passed to models may have “seams,” or regularly-spaced pairs of identical rows and columns. Depending on the data type and model, these seams may or may not cause inaccurate results. The default behavior of the tool is therefore to attempt to correct these seams.","type":"checkbox","width":3,"defaultChecked":false}]}]},{"name":"Models","components":[{"field":"variables.models","name":"Enabled Models","description":"Comma-separated list of isochrone models to enable. Possible values are: 'Traverse Time', 'Isodistance', 'Example' ","type":"textarray","width":12}]},{"name":"Settings","components":[{"field":"variables.interpolateSeams","name":"Interpolate Seams (Global)","description":"Because '1bto4b' (the DEM tiling script) generates tiles with matching edges, data loaded and passed to models may have “seams,” or regularly-spaced pairs of identical rows and columns. Depending on the data type and model, these seams may or may not cause inaccurate results. The default behavior of the tool is therefore to attempt to correct these seams. Set this property to false to disable this behavior for all sources that do not explicitly set their own 'interpolateSeams' property to true.","type":"checkbox","width":3,"defaultChecked":false}]}]}},"Viewshed":{"defaultIcon":"wifi-strength-2","description":"Realtime user generated viewsheds.","descriptionFull":{"title":"Renders dynamic tilesets based on line-of-sight visibilities from user defined source points. DEM tiles are used to generate these. At least one DEM tileset must be configured. curvature is optional and can be set to false to disable using the Major Radius to account for curvature during generations. cameraPresets are optional and the objects within only require the name field.","example":{"data":[{"name":"Unique Name 1","demtileurl":"Layers/Example/demtileset/{z}/{x}/{y}.png","minZoom":8,"maxNativeZoom":18},{"...":"..."}],"curvature":false,"cameraPresets":[{"name":"CAM A","height":2,"azCenter":0,"azFOV":70,"elCenter":-10,"elFOV":30},{"...":"..."}],"defaultObserverHeight":2,"defaultTargetHeight":0}},"hasVars":true,"name":"Viewshed","toolbarPriority":101,"paths":{"ViewshedTool":"essence/Tools/Viewshed/ViewshedTool","ViewshedTool_Manager":"essence/Tools/Viewshed/ViewshedTool_Manager","ViewshedTool_Algorithm":"essence/Tools/Viewshed/ViewshedTool_Algorithm"},"config":{"rows":[{"components":[{"field":"variables.data","name":"Layer specific DEMs","description":"Only show DEM if associated layer is on.","type":"objectarray","width":12,"object":[{"field":"name","name":"Name","description":"User-friendly name for DEM","type":"text","width":2},{"field":"demtileurl","name":"DEM Path","description":"","type":"text","width":8},{"field":"minZoom","name":"Minimum Zoom","description":"","type":"number","min":0,"step":1,"width":1},{"field":"maxNativeZoom","name":"Maximum Native Zoom","description":"","type":"number","min":0,"step":1,"width":1}]}]},{"components":[{"field":"variables.cameraPresets","name":"Camera Presets","description":"Only show DEM if associated layer is on.","type":"objectarray","width":12,"object":[{"field":"name","name":"Name","description":"Camera Name","type":"text","width":10},{"field":"height","name":"Height","description":"Height in meters","type":"number","min":0,"width":2},{"field":"azCenter","name":"Azimuth Center","description":"","type":"number","width":3},{"field":"azFOV","name":"Azimuth FOV","description":"","type":"number","width":3},{"field":"elCenter","name":"Elevation Center","description":"","type":"number","width":3},{"field":"elFOV","name":"Elevation FOV","description":"","type":"number","width":3}]}]},{"components":[{"field":"variables.curvature","name":"Curvature","description":"Whether to account for planetary curvature while computing viewsheds.","type":"checkbox","width":3,"defaultChecked":false}]}]}},"Shade":{"defaultIcon":"sun-angle-outline","description":"Realtime user generated sun and orbiter masks.","descriptionFull":{"title":"Shades the ground when line-of-sights to an orbiting target are occluded.","example":{"dem":"Data/missionDEM.tif","data":[{"name":"User-friendly name for DEM","demtileurl":"pathToDEMTiles/{z}/{x}/{y}.png","minZoom":8,"maxNativeZoom":18}],"sources":[{"name":"User-friendly name for orbiter or body that 'casts shadows'","value":"NAIF SPICE Spacecraft name or ID"},{"name":"...","value":"..."}],"observers":[{"name":"User-friendly name for observer for spacecraft time computations. Set to null to turn off time converting.","value":"SPICE Spacecraft name or ID","frame":"SPICE reference frame. i.e. IAU_MARS","body":"SPICE planet body. i.e. MARS"}],"defaultHeight":0,"observerTimePlaceholder":null,"utcTimeFormat":null}},"hasVars":true,"name":"Shade","toolbarPriority":102,"paths":{"ShadeTool":"essence/Tools/Shade/ShadeTool","ShadeTool_Manager":"essence/Tools/Shade/ShadeTool_Algorithm","ShadeTool_Algorithm":"essence/Tools/Shade/ShadeTool_Algorithm"},"config":{"rows":[{"components":[{"field":"variables.dem","name":"DEM path","description":"A path to a DEM.tif. This is used to get the current center elevation. This can/should be the same file used for the Measure Tool and the Coordinate's elevation.","type":"text","width":12}]},{"components":[{"field":"variables.data","name":"Layer specific DEMs","description":"At minimum, the Shade tool requires at least one 'data' source. A data source describes a DEM tileset (see /auxiliary/gdal2customtiles or /auxiliary/1bto4b) and allows users to select it by name to generate shade maps over.","type":"objectarray","width":12,"object":[{"field":"name","name":"Name","description":"User-friendly name for DEM","type":"text","width":2},{"field":"demtileurl","name":"DEM Path","description":"","type":"text","width":8},{"field":"minZoom","name":"Minimum Zoom","description":"","type":"number","min":0,"step":1,"width":1},{"field":"maxNativeZoom","name":"Maximum Native Zoom","description":"","type":"number","min":0,"step":1,"width":1}]}]},{"components":[{"field":"variables.sources","name":"Sources","description":"An array of objects with the properties 'name' and 'value'. 'name' is the display name for the Source Entity dropdown. 'value' is the SPICE spacecraft ID that gets passed to the backend ll2aerll.py script. Ensure the right kernels for the configured source entities/targets exist in /private/api/spice/kernels.","type":"objectarray","width":12,"object":[{"field":"name","name":"Name","description":"User-friendly name for orbiter or body that 'casts light'","type":"text","width":4},{"field":"value","name":"Value","description":"NAIF SPICE Spacecraft name or ID","type":"text","width":4}]}]},{"components":[{"field":"variables.observers","name":"Observers","description":"An array of objects with the properties 'name' and 'value'. 'name' is the display name for the Source Entity dropdown. 'value' is the SPICE spacecraft ID that gets passed to the backend chronos.py scripts. Ensure the right kernels for the configured observers exist in /private/api/spice/kernels and that there is a proper chronos setup file for each observer's value private/api/spice/chronosSetups/chronos-{lowercased_observer_value}.setup.","type":"objectarray","width":12,"object":[{"field":"name","name":"Name","description":"User-friendly name for observer for spacecraft time computations","type":"text","width":3},{"field":"value","name":"Value","description":"NAIF SPICE Spacecraft name or ID","type":"text","width":3},{"field":"frame","name":"Frame","description":"SPICE reference frame. i.e. 'IAU_MARS'","type":"text","width":3},{"field":"body","name":"Body","description":"SPICE planet body. i.e. 'MARS'","type":"text","width":3}]}]},{"components":[{"field":"variables.defaultHeight","name":"Default Height","description":"Sets a default for the 'Height' parameter. Height in meters above the surface to use when calculating line-of-sight shading. For instance, a point on the surface (0m) may not be visible to a 'Source Entity', say the Mars Reconnaissance Orbiter (MRO), but 2m above that point may be. This value does not only apply to the center longitude and latitude but to all points on the visible terrain. Gradually increasing this value shows the shade map n-meters above the surface. The regular default is 0 meters.","type":"number","min":0,"width":4},{"field":"variables.observerTimePlaceholder","name":"Observer Time Placeholder","description":"Sets the placeholder information for when the observer time's input box is cleared. Useful for denoting the expected time format to be inputted. For example “SOL DDDD HH:MM:SS”. Default null.","type":"text","width":4},{"field":"variables.utcTimeFormat","name":"UTC Time Format","description":"Sets the placeholder information for when the observer time's input box is cleared. Useful for denoting the expected time format to be inputted. Uses d3 time syntax (https://d3js.org/d3-time-format#locale_format). Example for day-of-year: '%Y-%j %H:%M:%S'. Defaults to times like so: 2023 SEP 06 19:27:05.","type":"text","width":4}]}]}},"Chemistry":{"defaultIcon":"flask","description":"Display chemistry percentages via graphs of a clicked point.","descriptionFull":{},"hasVars":false,"name":"Chemistry","paths":{"ChemistryTool":"essence/Tools/Chemistry/ChemistryTool"}},"Curtain":{"defaultIcon":"waves","description":"Curtain views of Ground Penetrating Radar data.","descriptionFull":{"title":"Vertical imagery aligned under terrain for visualizing data from ground penetrating radar.","example":{"withCredentials":false}},"hasVars":true,"name":"Curtain","paths":{"CurtainTool":"essence/Tools/Curtain/CurtainTool"},"config":{"rows":[{"components":[{"field":"variables.withCredentials","name":"With Credentials","description":"","type":"checkbox","width":3,"defaultChecked":false}]}]}},"Kinds":{"defaultIcon":"palette-swatch","description":"Not a real tool but plugin to configure different layer interactions.","descriptionFull":{},"hasVars":false,"name":"Kinds","kinds":["info","waypoint","chemistry_tool","draw_tool"],"paths":{"Kinds":"essence/Tools/Kinds/Kinds"}},"Measure":{"defaultIcon":"tape-measure","description":"Measure distances and generates elevation profiles.","descriptionFull":{"title":"Specify a path to a Digital Elevation Model (dem) .tif. Measure distances and generates elevation profiles. Can also query specific bands at specific points of images and generate profiles of them. If multiple dems are specified, a dropdown will be present for users to toggle between them.","example":{"dem":"(str) path to Data/defaultDEM.tif","layerDems":{"[layer_name]":"(str) path/to/layers/dem.tif"},"onlyShowDemIfLayerOn":true,"defaultMode":"segment || continuous || continuous_color"}},"hasVars":true,"name":"Measure","paths":{"MeasureTool":"essence/Tools/Measure/MeasureTool"},"config":{"rows":[{"components":[{"field":"variables.dem","name":"DEM path","description":"Path to a primary DEM (such as Data/defaultDEM.tif). Required if Layer Specific DEMs is unset.","type":"text","width":12}]},{"components":[{"field":"variables.layerDems","name":"Layer Specific DEMs","description":"Object of layer names and the paths to their DEMs. Users may switch between DEMs to profile via a dropdown. The dropdown only renders if there is more than one DEM configured overall.","type":"objectarray","width":12,"object":[{"field":"layer","name":"Layer Name","description":"","type":"text","width":4},{"field":"dem","name":"DEM Path","description":"","type":"text","width":8}]}]},{"components":[{"field":"variables.onlyShowDemIfLayerOn","name":"Only Show DEM If On","description":"If true, hides the configured Layer Specific DEMs of off layers from the tool's DEM selection dropdown. If false, all Layer Specific DEMs, even with invalid layer names, always show in the dropdown.","type":"checkbox","width":2,"defaultChecked":false}]},{"components":[{"field":"variables.defaultMode","name":"Default Mode","description":"Which measurement mode to default to. Options are 'segment', 'continuous' and 'continuous_color'","type":"dropdown","width":2,"options":["segment","continuous","continuous_color"]}]}]}},"Draw":{"defaultIcon":"pencil","description":"Advanced and collaborative map drawing.","descriptionFull":{"title":"The Draw tool is an advanced vector data creation and editing tool supporting a multi-user environment. Users can create and manage their own files which can have points, lines, and polygons as well as arrows and text to support annotation. Files can be viewed between users and features copied from one file to another.","example":{"intents":["Polygon_1_Alias","Polygon_2_Alias","Polygon_3_Alias","Line_Alias","Point_Alias","All_Alias"],"defaultDrawClipping":"over || under || off","defaultPublicFilter":false,"defaultYoursOnlyFilter":true,"defaultOnFilter":false,"leadsCanEditFileInfo":false,"hoverLengthOnLines":false,"templates":{"myTemplate":[{"type":"slider","field":"a","min":0,"max":100,"step":1,"default":0},{"type":"number","field":"b","min":0,"max":100,"step":1,"required":true,"default":3},{"type":"text","field":"c","minLength":2,"maxLength":4,"required":true,"regex":null,"default":null},{"type":"textarea","field":"d","maxLength":10,"required":true,"default":"hi"},{"type":"checkbox","field":"e","default":true},{"type":"dropdown","field":"f","items":["Yes","No","Maybe"],"default":"No"},{"type":"incrementer","field":"g","default":"ID-#"},{"type":"date","field":"h","format":"HH:mm:ss","default":"now"}]}}},"hasVars":true,"name":"Draw","toolbarPriority":1001,"paths":{"DrawTool":"essence/Tools/Draw/DrawTool"},"tests":{"DrawToolTest":"essence/Tools/Draw/DrawTool.test"},"expandable":true,"config":{"rows":[{"name":"Intent Aliases","description":"There are five files that are group editable with the correct permission. The group authentication is set an environment variable in the .env file during startup. These files are meant as collaborative layers that a only a few people will manage and contribute to do to the potential of race conditions on who did the last edit.","components":[{"field":"variables.intents.0","name":"Polygon 1 Alias","description":"","type":"text","width":2},{"field":"variables.intents.1","name":"Polygon 2 Alias","description":"","type":"text","width":2},{"field":"variables.intents.2","name":"Polygon 3 Alias","description":"","type":"text","width":2},{"field":"variables.intents.3","name":"Line Alias","description":"","type":"text","width":2},{"field":"variables.intents.4","name":"Point Alias","description":"","type":"text","width":2},{"field":"variables.intents.5","name":"All Alias","description":"","type":"text","width":2}]},{"components":[{"field":"variables.defaultDrawClipping","name":"Default Draw Clipping","description":"Default clipping mode for drawing. Drawing a polygon Over another would clip away that other polygon. Drawing a polygon Under another would have that polygon clip away the newly drawn one. When the clipping mode is Off, no clipping occurs. Users may freely change the clipping mode.","type":"dropdown","width":3,"options":["over","under","off"]},{"field":"variables.leadsCanEditFileInfo","name":"Leads Can Edit File Info","description":"If true, lead roles can edit the file info, (name, description, tags, folder, make private) of any user's public file.","type":"checkbox","width":3,"defaultChecked":false},{"field":"variables.hoverLengthOnLines","name":"Hover Length On Lines","description":"If true, the hover text for line features will include the total length of the line in meters.","type":"checkbox","width":3,"defaultChecked":false}]},{"components":[{"field":"variables.defaultPublicFilter","name":"Default Public Filter","description":"When the DrawTool first opens, filter the file list down to only public files or not.","type":"checkbox","width":4,"defaultChecked":false},{"field":"variables.defaultYoursOnlyFilter","name":"Default Yours Only Filter","description":"When the DrawTool first opens, filter the file list down to only files you own or not.","type":"checkbox","width":4,"defaultChecked":true},{"field":"variables.defaultOnFilter","name":"Default On Filter","description":"When the DrawTool first opens, filter the file list down to only files that are on or not. ","type":"checkbox","width":4,"defaultChecked":false}]},{"components":[{"field":"variables.templates","name":"Default File Property Templates","description":"Templates create forms for feature properties. For instance, all features in a given draw file could, in the feature's edit panel, have the field “Reviewed” be togglable via a checkbox. Users may make their own templates too but the ones configured here are promoted and cannot be delete.","type":"objectarray","width":12,"object":[{"field":"name","name":"Template Name","description":"","type":"text","width":4},{"field":"name","name":"Property Field Name","description":"","type":"text","width":4},{"field":"type","name":"Component","description":"","type":"dropdown","width":2,"options":["slider","number","text","textarea","checkbox","dropdown","incrementer","date"]},{"field":"required","name":"Required","description":"Field requires entry.","type":"checkbox","width":2,"defaultChecked":false},{"field":"min","name":"Min Value","description":"For Slider and Number","type":"number","width":4},{"field":"max","name":"Max Value","description":"For Slider and Number","type":"number","width":4},{"field":"step","name":"Step Size","description":"For Slider and Number","type":"number","width":4},{"field":"minLength","name":"Min Length","description":"For Text and Textarea","type":"number","width":4},{"field":"maxLength","name":"Max Length","description":"For Text and Textarea","type":"number","width":4},{"field":"regex","name":"Regex","description":"For Text and Textarea","type":"text","width":3},{"field":"items","name":"Dropdown Items","description":"Comma-separated. For dropdown","type":"text","width":6},{"field":"format","name":"Date Format","description":"For date","type":"text","width":3},{"field":"default","name":"Default Value","description":"For all types","type":"text","width":3},{"field":"intersectedGeodataset","name":"Intersect GeoDataset","description":"Templated fields can be auto-populated based on whether the drawn feature's shape intersecting feature's from an underlying GeoDataset.","type":"text","width":4},{"field":"intersectedProp","name":"Intersected Property Name","description":"The properties field/path whose value should be used when auto-populating this template field.","type":"text","width":4},{"field":"intersectedConflict","name":"Intersection Conflict","description":"In case the drawn shape intersects no features or multiple features, what to do: Default to 'Default Value'? Set the field's value to 'null'? Use the properties of the first intersected GeoDataset feature? Use the properties of the last intersected GeoDataset feature? If possible, set the field to a comma-separated string of the values from each intersected feature.","type":"dropdown","width":4,"options":["default","null","first","last","array"]}]}]}]}}} \ No newline at end of file diff --git a/configure/src/metaconfigs/layer-image-config.json b/configure/src/metaconfigs/layer-image-config.json index 7e52fc760..7003832ad 100644 --- a/configure/src/metaconfigs/layer-image-config.json +++ b/configure/src/metaconfigs/layer-image-config.json @@ -192,7 +192,15 @@ "name": "Legend From URL", "description": "A URL to a static image or .csv with the following header: 'color,strokecolor,shape,value'. If the path is relative, it will be relative to the mission's directory. This legend is overridden if a legend is also configured below.", "type": "text", - "width": 12 + "width": 10 + }, + { + "new": true, + "field": "variables.hideLegendLayerName", + "name": "Hide layer name", + "description": "Hide layer name in the legend.", + "type": "checkbox", + "width": 2 } ] }, diff --git a/configure/src/metaconfigs/layer-model-config.json b/configure/src/metaconfigs/layer-model-config.json index 85f1ea889..64cf18e99 100644 --- a/configure/src/metaconfigs/layer-model-config.json +++ b/configure/src/metaconfigs/layer-model-config.json @@ -425,7 +425,15 @@ "name": "Legend From URL", "description": "A URL to a static image or .csv with the following header: 'color,strokecolor,shape,value'. If the path is relative, it will be relative to the mission's directory. This legend is overridden if a legend is also configured below.", "type": "text", - "width": 12 + "width": 10 + }, + { + "new": true, + "field": "variables.hideLegendLayerName", + "name": "Hide layer name", + "description": "Hide layer name in the legend.", + "type": "checkbox", + "width": 2 } ] }, diff --git a/configure/src/metaconfigs/layer-query-config.json b/configure/src/metaconfigs/layer-query-config.json index e204a8e0a..5c4430582 100644 --- a/configure/src/metaconfigs/layer-query-config.json +++ b/configure/src/metaconfigs/layer-query-config.json @@ -548,7 +548,15 @@ "name": "Legend From URL", "description": "A URL to a static image or .csv with the following header: 'color,strokecolor,shape,value'. If the path is relative, it will be relative to the mission's directory. This legend is overridden if a legend is also configured below.", "type": "text", - "width": 12 + "width": 10 + }, + { + "new": true, + "field": "variables.hideLegendLayerName", + "name": "Hide layer name", + "description": "Hide layer name in the legend.", + "type": "checkbox", + "width": 2 } ] }, diff --git a/configure/src/metaconfigs/layer-tile-config.json b/configure/src/metaconfigs/layer-tile-config.json index 23611cec0..3c9f065bc 100644 --- a/configure/src/metaconfigs/layer-tile-config.json +++ b/configure/src/metaconfigs/layer-tile-config.json @@ -398,7 +398,15 @@ "name": "Legend From URL", "description": "A URL to a static image or .csv with the following header: 'color,strokecolor,shape,value'. If the path is relative, it will be relative to the mission's directory. This legend is overridden if a legend is also configured below.", "type": "text", - "width": 12 + "width": 10 + }, + { + "new": true, + "field": "variables.hideLegendLayerName", + "name": "Hide layer name", + "description": "Hide layer name in the legend.", + "type": "checkbox", + "width": 2 } ] }, diff --git a/configure/src/metaconfigs/layer-vector-config.json b/configure/src/metaconfigs/layer-vector-config.json index 57fe72cf5..8b91cbd2d 100644 --- a/configure/src/metaconfigs/layer-vector-config.json +++ b/configure/src/metaconfigs/layer-vector-config.json @@ -486,7 +486,15 @@ "name": "Legend From URL", "description": "A URL to a static image or .csv with the following header: 'color,strokecolor,shape,value'. If the path is relative, it will be relative to the mission's directory. This legend is overridden if a legend is also configured below.", "type": "text", - "width": 12 + "width": 10 + }, + { + "new": true, + "field": "variables.hideLegendLayerName", + "name": "Hide layer name", + "description": "Hide layer name in the legend.", + "type": "checkbox", + "width": 2 } ] }, diff --git a/configure/src/metaconfigs/layer-vectortile-config.json b/configure/src/metaconfigs/layer-vectortile-config.json index 71015d632..34b71611f 100644 --- a/configure/src/metaconfigs/layer-vectortile-config.json +++ b/configure/src/metaconfigs/layer-vectortile-config.json @@ -442,7 +442,15 @@ "name": "Legend From URL", "description": "A URL to a static image or .csv with the following header: 'color,strokecolor,shape,value'. If the path is relative, it will be relative to the mission's directory. This legend is overridden if a legend is also configured below.", "type": "text", - "width": 12 + "width": 10 + }, + { + "new": true, + "field": "variables.hideLegendLayerName", + "name": "Hide layer name", + "description": "Hide layer name in the legend.", + "type": "checkbox", + "width": 2 } ] }, diff --git a/configure/src/metaconfigs/layer-velocity-config.json b/configure/src/metaconfigs/layer-velocity-config.json index 3bc04e0d4..eef793007 100644 --- a/configure/src/metaconfigs/layer-velocity-config.json +++ b/configure/src/metaconfigs/layer-velocity-config.json @@ -372,7 +372,15 @@ "name": "Legend From URL", "description": "A URL to a static image or .csv with the following header: 'color,strokecolor,shape,value'. If the path is relative, it will be relative to the mission's directory. This legend is overridden if a legend is also configured below.", "type": "text", - "width": 12 + "width": 10 + }, + { + "new": true, + "field": "variables.hideLegendLayerName", + "name": "Hide layer name", + "description": "Hide layer name in the legend.", + "type": "checkbox", + "width": 2 } ] }, diff --git a/src/essence/Tools/Legend/LegendTool.js b/src/essence/Tools/Legend/LegendTool.js index ca8d36a5b..b86776943 100644 --- a/src/essence/Tools/Legend/LegendTool.js +++ b/src/essence/Tools/Legend/LegendTool.js @@ -20,6 +20,7 @@ var LegendTool = { //Get tool variables this.displayOnStart = L_.getToolVars('legend')['displayOnStart'] this.justification = L_.getToolVars('legend')['justification'] + this.showHeadersInLegend = L_.getToolVars('legend')['showHeadersInLegend'] if (this.justification == 'right') { const toolController = d3.select('#toolcontroller_sepdiv') const toolContent = d3.select('#toolContentSeparated_Legend') @@ -99,78 +100,109 @@ function interfaceWithMMWebGIS() { function refreshLegends() { $('#LegendTool').empty() - for (let l in L_.layers.on) { - if (L_.layers.on[l] == true) { - if (L_.layers.data[l].type != 'header') { - if (L_.layers.data[l]?._legend === undefined - && ((['image', 'tile'].includes(L_.layers.data[l].type) && L_.layers.data[l].cogTransform) - || L_.layers.data[l].type === 'velocity')) { - const layersTool = ToolController_.getTool('LayersTool') - layersTool.populateCogScale(L_.layers.data[l].name) - } + function _refreshLegends(node, parent, depth) { + let shift = LegendTool.showHeadersInLegend === true ? depth : 0 + for (let i in node) { + let l = node[i].name + if (L_.layers.on[l] == true) { + if (L_.layers.data[l].type != 'header') { + if (L_.layers.data[l]?._legend === undefined + && ((['image', 'tile'].includes(L_.layers.data[l].type) && L_.layers.data[l].cogTransform) + || L_.layers.data[l].type === 'velocity')) { + const layersTool = ToolController_.getTool('LayersTool') + layersTool.populateCogScale(L_.layers.data[l].name) + } - // Check if there's a legend URL that points to an image - const legendURL = L_.layers.data[l]?.legend - if (legendURL && typeof legendURL === 'string') { - let isImageUrl = false - - // First check for file extensions - const fileExtension = legendURL.toLowerCase().split('.').pop().split('?')[0] // Remove query params - const imageExtensions = ['png', 'jpg', 'jpeg', 'gif', 'svg', 'webp', 'tiff', 'tif', 'bmp', 'ico', 'avif'] - - if (imageExtensions.includes(fileExtension)) { - isImageUrl = true - } else if (['csv'].includes(fileExtension)) { - isImageUrl = false - } else { - // If no file extension and not a csv, check for image MIME types in URL parameters (e.g., WMS GetLegendGraphic) - try { - const url = new URL(legendURL) - const formatParam = url.searchParams.get('FORMAT') || url.searchParams.get('format') - - if (formatParam) { - const imageMimeTypes = [ - 'image/png', 'image/jpeg', 'image/jpg', 'image/gif', - 'image/svg+xml', 'image/webp', 'image/tiff', - 'image/bmp', 'image/ico', 'image/avif' - ] - - const decodedFormat = decodeURIComponent(formatParam).toLowerCase() - if (imageMimeTypes.includes(decodedFormat)) { - isImageUrl = true + // Check if there's a legend URL that points to an image + const legendURL = L_.layers.data[l]?.legend + if (legendURL && typeof legendURL === 'string') { + let isImageUrl = false + + // First check for file extensions + const fileExtension = legendURL.toLowerCase().split('.').pop().split('?')[0] // Remove query params + const imageExtensions = ['png', 'jpg', 'jpeg', 'gif', 'svg', 'webp', 'tiff', 'tif', 'bmp', 'ico', 'avif'] + + if (imageExtensions.includes(fileExtension)) { + isImageUrl = true + } else if (['csv'].includes(fileExtension)) { + isImageUrl = false + } else { + // If no file extension and not a csv, check for image MIME types in URL parameters (e.g., WMS GetLegendGraphic) + try { + const url = new URL(legendURL) + const formatParam = url.searchParams.get('FORMAT') || url.searchParams.get('format') + + if (formatParam) { + const imageMimeTypes = [ + 'image/png', 'image/jpeg', 'image/jpg', 'image/gif', + 'image/svg+xml', 'image/webp', 'image/tiff', + 'image/bmp', 'image/ico', 'image/avif' + ] + + const decodedFormat = decodeURIComponent(formatParam).toLowerCase() + if (imageMimeTypes.includes(decodedFormat)) { + isImageUrl = true + } } + } catch (e) { + // URL parsing failed, treat as non-image + console.warn('Failed to parse legend URL:', legendURL) } - } catch (e) { - // URL parsing failed, treat as non-image - console.warn('Failed to parse legend URL:', legendURL) + } + + if (isImageUrl) { + // Handle image legend directly + drawLegends( + LegendTool.tools, + legendURL, // Pass the URL string directly + l, + L_.layers.data[l].display_name, + L_.layers.opacity[l], + shift + ) + continue; // Skip the CSV processing below } } - if (isImageUrl) { - // Handle image legend directly + if (L_.layers.data[l]?._legend != undefined) { drawLegends( LegendTool.tools, - legendURL, // Pass the URL string directly + L_.layers.data[l]?._legend, l, L_.layers.data[l].display_name, - L_.layers.opacity[l] + L_.layers.opacity[l], + shift ) - continue; // Skip the CSV processing below } - } - - if (L_.layers.data[l]?._legend != undefined) { - drawLegends( - LegendTool.tools, - L_.layers.data[l]?._legend, - l, - L_.layers.data[l].display_name, - L_.layers.opacity[l] - ) - } + } else if (LegendTool.showHeadersInLegend === true) { + const haveLegends = L_.layers.data[l].sublayers + .map(i => i.name) + .filter(i => { + return ((L_.layers.data[i]._legend?.length > 0 + || (L_.layers.data[i]?._legend === undefined + && ((['image', 'tile'].includes(L_.layers.data[i].type) && L_.layers.data[i].cogTransform) + || L_.layers.data[i].type === 'velocity'))) && L_.layers.on[i]) + }) + + if (haveLegends.length > 0) { + drawLegends( + LegendTool.tools, + L_.layers.data[l]?._legend, + l, + L_.layers.data[l].display_name, + L_.layers.opacity[l], + shift + ) + } + } } + + if (node[i].sublayers) + _refreshLegends(node[i].sublayers, node[i], depth + 1) } } + + _refreshLegends(L_.configData.layers, {}, 0) } // The legends parameter should be an array of objects, where each object must contain @@ -244,8 +276,16 @@ function drawLegendHeader() { return tools } -function drawLegends(tools, _legend, layerUUID, display_name, opacity) { +function drawLegends(tools, _legend, layerUUID, display_name, opacity, shift) { if (tools == null) return + + const layerConfig = L_.layers.data[layerUUID] + + const isHeader = layerConfig.type === 'header' + + // If option to hide layer name in legend is checked in the configuration + const hideLegendLayerName = layerConfig.variables?.hideLegendLayerName || false; + var c = tools .append('div') .attr('class', 'mmgisScrollbar') @@ -253,16 +293,20 @@ function drawLegends(tools, _legend, layerUUID, display_name, opacity) { .style('display', 'inline-block') .style('padding-top', '5px') .style('padding-right', '12px') - .style('border-bottom', '1px solid var(--color-i)') + .style('padding-left', shift > 0 ? `${shift * 16}px` : '') + .style('border-bottom', isHeader ? '' : '1px solid var(--color-i)') c.append('div') .attr('class', 'row') .append('p') .style('font-size', '13px') .style('color', 'var(--color-f)') - .style('margin-bottom', '5px') + .style('margin-bottom', isHeader ? '' : '5px') .style('padding-left', '8px') - .text(display_name) + .style('font-weight', isHeader ? 'bold' : '') + .text(hideLegendLayerName ? '' : display_name) + + if (isHeader) return let lastContinues = [] let lastShape = '' diff --git a/src/essence/Tools/Legend/config.json b/src/essence/Tools/Legend/config.json index 11136fa62..f22e5b6d5 100644 --- a/src/essence/Tools/Legend/config.json +++ b/src/essence/Tools/Legend/config.json @@ -42,6 +42,14 @@ "type": "dropdown", "width": 2, "options": ["left", "right"] + }, + { + "field": "variables.showHeadersInLegend", + "name": "Show Headers in Legend", + "description": "If true, the legend will display the name of Header layer types.", + "type": "checkbox", + "width": 3, + "defaultChecked": false } ] }