Source code for dtale.dash_application.custom_geojson

import base64
import json
import pandas as pd

import dash_bootstrap_components as dbc
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output, State
from dash.exceptions import PreventUpdate

from dtale.dash_application.layout.utils import build_input, build_option

CUSTOM_GEOJSON = []


[docs]def get_custom_geojson(geojson_id=None): global CUSTOM_GEOJSON if geojson_id is None: return CUSTOM_GEOJSON return next((ct for ct in CUSTOM_GEOJSON if ct["key"] == geojson_id), None)
[docs]def add_custom_geojson(geojson_key, geojson): global CUSTOM_GEOJSON suffix = 0 while get_custom_geojson("{}{}".format(geojson_key, suffix or "")): suffix += 1 geojson_key = "{}{}".format(geojson_key, suffix + 1 if suffix else "") geojson["key"] = geojson_key CUSTOM_GEOJSON.append(geojson) return geojson_key
[docs]def load_geojson(contents, filename): if contents is None and filename is None: return None if not filename.endswith(".json"): raise Exception("geojson files must be JSON!") _, content_string = contents.split(",") decoded = base64.b64decode(content_string) geojson = json.loads(decoded.decode("utf-8")) geojson_key = "".join(filename.split(".")[:-1]) # get properties available to use for featureidkey data = dict( data=geojson, filename=filename, time=pd.Timestamp("now"), type=geojson["type"] ) if data["type"] == "FeatureCollection": data["properties"] = sorted(geojson["features"][0]["properties"].keys()) geojson_key = add_custom_geojson(geojson_key, data) return geojson_key
[docs]def build_geojson_upload(loc_mode, geojson_key=None, featureidkey=None): curr_geojson = get_custom_geojson(geojson_key) featureidkey_options = [] featureidkey_value = featureidkey featureidkey_placeholder = "Select uploaded data" disabled = False if curr_geojson and not isinstance(curr_geojson, list): if curr_geojson.get("type") == "FeatureCollection": featureidkey_options = [ build_option(fik) for fik in curr_geojson["properties"] ] else: featureidkey_value = None disabled = True featureidkey_placeholder = "id" return [ html.Div( [ html.Div( [ dcc.Upload( html.Div( html.Span( html.Span( "Upload File", style=dict(whiteSpace="pre-line") ), className="input-group-addon d-block pt-1 pb-0 pointer", ), className="input-group mr-3", id="upload-geojson-btn", ), id="upload-geojson", ), ], className="col-auto", ), html.Div(id="output-geojson-upload", className="col mt-auto mb-auto"), ], className="row pb-5", ), html.Div( [ build_input( "geojson", dcc.Dropdown( id="geojson-dropdown", options=[build_option(ct["key"]) for ct in CUSTOM_GEOJSON], placeholder="Select uploaded data", style=dict(width="inherit"), value=geojson_key if loc_mode == "geojson-id" else None, ), className="col-md-6", id="geojson-input", ), build_input( "featureidkey", dcc.Dropdown( id="featureidkey-dropdown", options=featureidkey_options, placeholder=featureidkey_placeholder, style=dict(width="inherit"), disabled=disabled, value=featureidkey_value, ), className="col-md-6", id="featureidkey-input", ), ], className="row", ), ]
[docs]def build_modal(map_type, loc_mode): return html.Div( [ html.Div( html.Span( html.Span("GeoJSON Options", style=dict(whiteSpace="pre-line")), className="input-group-addon d-block pt-1 pb-0 pointer", ), className="input-group mr-3", id="open-geojson-modal", ), dbc.Modal( [ dbc.ModalHeader("Custom GeoJSON Options"), dbc.ModalBody(build_geojson_upload(loc_mode)), dbc.ModalFooter( dbc.Button( "Close", id="close-geojson-modal", className="ml-auto" ) ), ], id="geojson-modal", size="lg", centered=True, ), ], className="col-auto", style={} if map_type == "choropleth" and loc_mode == "geojson-id" else {"display": "none"}, id="custom-geojson-input", )
[docs]def init_callbacks(dash_app): @dash_app.callback( [ Output("output-geojson-upload", "children"), Output("geojson-dropdown", "options"), ], [Input("upload-geojson", "contents")], [State("upload-geojson", "filename")], ) def update_geojson(contents, filename): if filename is None: raise PreventUpdate geojson_options = [build_option(ct["key"]) for ct in get_custom_geojson()] try: geojson_key = load_geojson(contents, filename) geojson_options.append(build_option(geojson_key)) return "{} uploaded!".format(geojson_key), geojson_options except BaseException as ex: return str(ex), geojson_options @dash_app.callback( [ Output("featureidkey-dropdown", "options"), Output("featureidkey-dropdown", "disabled"), Output("featureidkey-dropdown", "placeholder"), ], [Input("geojson-dropdown", "value")], ) def update_featureidkey_options(geojson): geojson_data = get_custom_geojson(geojson) placeholder = "Select uploaded data" if geojson_data is None or isinstance(geojson_data, list): return [], False, placeholder disabled = geojson_data["type"] != "FeatureCollection" placeholder = "id" if disabled else placeholder if geojson_data and not disabled: return ( [build_option(p) for p in geojson_data.get("properties", [])], disabled, placeholder, ) return [], disabled, placeholder @dash_app.callback( Output("geojson-modal", "is_open"), [ Input("open-geojson-modal", "n_clicks"), Input("close-geojson-modal", "n_clicks"), ], [State("geojson-modal", "is_open")], ) def toggle_modal(n1, n2, is_open): if n1 or n2: return not is_open return is_open