Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ venv
*.sublime*
.vscode/
.tox
.DS_Store
13 changes: 13 additions & 0 deletions examples/dash/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Dash embedded in FAB
-----------------------

Example of Dash embedded under flask-appbuilder

thanks to @jimmybow (https://github.com/jimmybow/Flask_template_auth_with_Dash) for the inspiration


Run it::

$ export FLASK_APP=app/__init__.py
$ flask fab create-admin
$ flask run
28 changes: 28 additions & 0 deletions examples/dash/app/Dashboard/Dash_App1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# -*- coding: utf-8 -*-
"""
Created on Sun Jul 8 10:39:33 2018

@author: jimmybow
"""
from dash import Dash
from dash.dependencies import Input, State, Output
from .Dash_fun import apply_layout_with_auth, load_object, save_object
import dash_core_components as dcc
import dash_html_components as html

url_base = "/dash/app1/"

layout = html.Div(
[html.Div("This is dash app1"), html.Br(), dcc.Input(id="input_text"), html.Br(), html.Br(), html.Div(id="target")]
)


def Add_Dash(server, appbuilder):
app = Dash(server=server, url_base_pathname=url_base)
apply_layout_with_auth(app, layout, appbuilder)

@app.callback(Output("target", "children"), [Input("input_text", "value")])
def callback_fun(value):
return "your input is {}".format(value)

return app.server
41 changes: 41 additions & 0 deletions examples/dash/app/Dashboard/Dash_App2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
from datetime import datetime as dt

from dash import Dash

import dash_core_components as dcc
import dash_html_components as html
import pandas_datareader as pdr
from dash.dependencies import Input
from dash.dependencies import Output
from .Dash_fun import apply_layout_with_auth, load_object, save_object

url_base = "/dash/app2/"

layout = html.Div(
[
html.H1("Stock Tickers"),
dcc.Dropdown(
id="my-dropdown",
options=[
{"label": "Coke", "value": "COKE"},
{"label": "Tesla", "value": "TSLA"},
{"label": "Apple", "value": "AAPL"},
],
value="COKE",
),
dcc.Graph(id="my-graph"),
],
style={"width": "500"},
)


def Add_Dash(server, appbuilder):
app = Dash(server=server, url_base_pathname=url_base)
apply_layout_with_auth(app, layout, appbuilder)

@app.callback(Output("my-graph", "figure"), [Input("my-dropdown", "value")])
def update_graph(selected_dropdown_value):
df = pdr.get_data_yahoo(selected_dropdown_value, start=dt(2017, 1, 1), end=dt.now())
return {"data": [{"x": df.index, "y": df.Close}], "layout": {"margin": {"l": 40, "r": 0, "t": 20, "b": 30}}}

return app.server
52 changes: 52 additions & 0 deletions examples/dash/app/Dashboard/Dash_fun.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# -*- coding: utf-8 -*-
"""
Created on Fri Jan 25 22:34:51 2019

@author: jimmybow
"""

from datetime import datetime, timedelta
from flask_login import current_user
from flask import redirect, has_app_context
import dash_html_components as html
import dash_core_components as dcc
import pandas as pd
import uuid
import os
import pickle


def save_object(obj, session_id, name):
os.makedirs("Dir_Store", exist_ok=True)
file = "Dir_Store/{}_{}".format(session_id, name)
pickle.dump(obj, open(file, "wb"))


def load_object(session_id, name):
file = "Dir_Store/{}_{}".format(session_id, name)
obj = pickle.load(open(file, "rb"))
os.remove(file)
return obj


def clean_Dir_Store():
if os.path.isdir("Dir_Store"):
file_list = pd.Series("Dir_Store/" + i for i in os.listdir("Dir_Store"))
mt = file_list.apply(lambda x: datetime.fromtimestamp(os.path.getmtime(x))).astype(str)
for i in file_list[mt < str(datetime.now() - timedelta(hours=3))]:
os.remove(i)


def apply_layout_with_auth(app, layout, appbuilder):
def serve_layout():
if current_user and current_user.is_authenticated:
session_id = str(uuid.uuid4())
clean_Dir_Store()
return html.Div([html.Div(session_id, id="session_id", style={"display": "none"}), layout])
loginurl = None
if has_app_context():
return dcc.Location(pathname=appbuilder.get_url_for_login, id="")
return None

app.config.suppress_callback_exceptions = True
app.layout = serve_layout
Empty file.
21 changes: 21 additions & 0 deletions examples/dash/app/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import logging

from flask import Flask
from flask_appbuilder import AppBuilder, SQLA
from .Dashboard import Dash_App1, Dash_App2

"""
Logging configuration
"""
logging.basicConfig(format="%(asctime)s:%(levelname)s:%(name)s:%(message)s")
logging.getLogger().setLevel(logging.DEBUG)


app = Flask(__name__)
app.config.from_object("config")
db = SQLA(app)
appbuilder = AppBuilder(app, db.session)
app = Dash_App1.Add_Dash(app, appbuilder)
app = Dash_App2.Add_Dash(app, appbuilder)

from . import views # noqa
22 changes: 22 additions & 0 deletions examples/dash/app/templates/dash.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{% extends "appbuilder/baselayout.html" %}
{% block head_css %}
{{ super() }}

{% endblock %}
{% block content %}
<div class="right_col" role="main">
<div class="row">
<div class="col-md-12 col-sm-12 col-xs-12">
<div class="dashboard_graph">
<div style="width: 100%; min-height:800px;">
<iframe noresize='noresize'
style='position: absolute; background: transparent; width: 95%; height:100%;' src={{ dash_url }}
frameborder="0">
</iframe>
</div>
<div class="clearfix"></div>
</div>
</div>
</div>
</div>
{% endblock %}
36 changes: 36 additions & 0 deletions examples/dash/app/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
from flask_appbuilder.baseviews import BaseView
from flask_appbuilder import expose, has_access
from .Dashboard import Dash_App1, Dash_App2

from . import appbuilder


class MyDashAppCallBack(BaseView):
route_base = "/"

@has_access
@expose("/dashboard_callback/")
def methoddash(self):
print("dash")
return self.render_template("dash.html", dash_url=Dash_App1.url_base, appbuilder=appbuilder)


appbuilder.add_view_no_menu(MyDashAppCallBack())
appbuilder.add_link(
"Dashboard Callback", href="/dashboard_callback/", icon="fa-list", category="Dash Demo", category_icon="fa-list"
)


class MyDashAppGraph(BaseView):
route_base = "/"

@has_access
@expose("/dashboard_graph/")
def methoddash(self):
return self.render_template("dash.html", dash_url=Dash_App2.url_base, appbuilder=appbuilder)


appbuilder.add_view_no_menu(MyDashAppGraph())
appbuilder.add_link(
"Dashboard Graph", href="/dashboard_graph/", icon="fa-list", category="Dash Demo", category_icon="fa-list"
)
3 changes: 3 additions & 0 deletions examples/dash/babel/babel.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[python: **.py]
[jinja2: **/templates/**.html]
encoding = utf-8
1 change: 1 addition & 0 deletions examples/dash/babel/messages.pot
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

57 changes: 57 additions & 0 deletions examples/dash/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import os

basedir = os.path.abspath(os.path.dirname(__file__))

CSRF_ENABLED = True
SECRET_KEY = "\2\1thisismyscretkey\1\2\e\y\y\h"

OPENID_PROVIDERS = [
{"name": "Google", "url": "https://www.google.com/accounts/o8/id"},
{"name": "Yahoo", "url": "https://me.yahoo.com"},
{"name": "AOL", "url": "http://openid.aol.com/<username>"},
{"name": "Flickr", "url": "http://www.flickr.com/<username>"},
{"name": "MyOpenID", "url": "https://www.myopenid.com"},
]

SQLALCHEMY_DATABASE_URI = "sqlite:///" + os.path.join(basedir, "app.db")
# SQLALCHEMY_DATABASE_URI = 'mysql://myapp@localhost/myapp'
# SQLALCHEMY_DATABASE_URI = 'postgresql://root:password@localhost/myapp'
BABEL_DEFAULT_LOCALE = "en"


# ------------------------------
# GLOBALS FOR APP Builder
# ------------------------------
BABEL_DEFAULT_LOCALE = "en"
BABEL_DEFAULT_FOLDER = "translations"
LANGUAGES = {
"en": {"flag": "gb", "name": "English"},
"pt": {"flag": "pt", "name": "Portuguese"},
"es": {"flag": "es", "name": "Spanish"},
"de": {"flag": "de", "name": "German"},
"zh": {"flag": "cn", "name": "Chinese"},
"ru": {"flag": "ru", "name": "Russian"},
}


UPLOAD_FOLDER = basedir + "/app/static/uploads/"
IMG_UPLOAD_FOLDER = basedir + "/app/static/uploads/"
IMG_UPLOAD_URL = "/static/uploads/"
AUTH_TYPE = 1
AUTH_ROLE_ADMIN = "Admin"
AUTH_ROLE_PUBLIC = "Public"
# APP_NAME = "My App Name"
# APP_ICON = "static/img/logo.jpg"
APP_THEME = "" # default
# APP_THEME = "cerulean.css"
# APP_THEME = "amelia.css"
# APP_THEME = "cosmo.css"
# APP_THEME = "cyborg.css"
# APP_THEME = "flatly.css"
# APP_THEME = "journal.css"
# APP_THEME = "readable.css"
# APP_THEME = "simplex.css"
# APP_THEME = "slate.css"
# APP_THEME = "spacelab.css"
# APP_THEME = "united.css"
# APP_THEME = "yeti.css"
3 changes: 3 additions & 0 deletions examples/dash/run.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from app import app

app.run(host="0.0.0.0", port=8080, debug=True)
Loading