Skip to content

Commit

Permalink
Added new views and bug fixes to the web-manager. Added fixes for bas…
Browse files Browse the repository at this point in the history
…e.template.
  • Loading branch information
danwos committed Nov 25, 2016
1 parent d9b99a5 commit 978de0b
Show file tree
Hide file tree
Showing 20 changed files with 317 additions and 127 deletions.
Expand Up @@ -61,14 +61,26 @@ def __init__(self, app):
self.flask_admin = None

def register(self, db_clazz, db_session):
"""
Adds a new class-based view to the flask-admin instance.
:param db_clazz: SQLAlchemy class object
:param db_session: session object
:return: Name of the endpoint, which can be used to generate urls for it.
"""
# We must initialise the Flask-Admin class.
# This can not be done during pattern initialisation, because Flask gets loaded and configured during
# activation phase. So during initialisation it is not available.

if self.flask_admin is None:
self.flask_admin = Admin(self.app.web.flask, name=self.app.name, template_mode='bootstrap3')

self.flask_admin.add_view(ModelView(db_clazz, db_session))
self.flask_admin = Admin(self.app.web.flask,
name=self.app.name,
base_template="master.html",
template_mode='bootstrap3')

endpoint = "admin_%s" % db_clazz.__name__.lower()
self.flask_admin.add_view(ModelView(db_clazz, db_session, endpoint=endpoint))
return endpoint

def unregister(self):
pass
Expand Down
3 changes: 2 additions & 1 deletion groundwork_web/patterns/gw_web_pattern/context.py
Expand Up @@ -57,6 +57,7 @@ def __init__(self, name, template_folder, static_folder, url_prefix, description
self.template_folder = template_folder
self.static_folder = static_folder
self.url_prefix = url_prefix
self.static_url_path = "/static"
self.description = description
self.plugin = plugin
self.app = app
Expand All @@ -66,5 +67,5 @@ def __init__(self, name, template_folder, static_folder, url_prefix, description
subdomain=None,
template_folder=template_folder,
static_folder=static_folder,
static_url_path="/static/" + name)
static_url_path=self.static_url_path)
self.app.web.flask.register_blueprint(self.blueprint)
26 changes: 22 additions & 4 deletions groundwork_web/patterns/gw_web_pattern/gw_web_pattern.py
@@ -1,3 +1,4 @@
import os
import logging
from flask import Flask, render_template
from docutils.core import publish_parts
Expand Down Expand Up @@ -50,8 +51,11 @@ def flask(self, value):
def __init_flask(self, plugin, *args, **kwargs):
self.app.web.init_flask()

def render(self, template, **kwargs):
return self.app.web.render(template, **kwargs)
def render(self, template, plugin=None, **kwargs):
if plugin is None:
plugin = self.plugin

return self.app.web.render(template, plugin, **kwargs)


class WebApplication:
Expand All @@ -66,17 +70,31 @@ def __init__(self, app):
self.menus = MenuApplication(app)

def init_flask(self):
"""
Initialises and configures flask, is not already done,.
:return: None
"""
if self.flask is None:
self.flask = Flask(self.app.name)

# Inject send_signal() to jinja templates
# Use it like {{ send_signal("my_signal") }}
self.flask.jinja_env.globals.update(send_signal=self.app.signals.send)

self.flask.jinja_env.globals.update(app=self.app)

self.flask.jinja_env.globals.update(get_menu=self.__get_menu)
self.flask.jinja_env.globals.update(get_config=self.app.config.get)
self.flask.jinja_env.globals.update(rst2html=self.__rst2html)

# Lets set the secret key for flask. This should be set in configuration files, so that
# signed cookies are still valid if the server got restarted.
# If there is no such parameter available, we create a temporary key, which is only
# available during server runtime.
self.flask.secret_key = self.app.config.get("FLASK_SECRET_KEY", os.urandom(24))

self.flask.config["SERVER_NAME"] = self.app.config.get("FLASK_SERVER_NAME", "localhost")

def __get_menu(self, cluster="base"):
return self.menus.get(cluster=cluster)

Expand All @@ -89,7 +107,7 @@ def __rst2html(self, document, part="body"):
return doc_rendered[part]
return document

def render(self, template, **kwargs):
def render(self, template, plugin=None, **kwargs):
"""
Renders a template and returns a strings, which represents the rendered data.
Expand All @@ -100,5 +118,5 @@ def render(self, template, **kwargs):
:return: Rendered template as string
"""

return render_template(template, **kwargs)
return render_template(template, app=self.app, plugin=plugin, **kwargs)

1 change: 0 additions & 1 deletion groundwork_web/plugins/__init__.py
@@ -1,3 +1,2 @@
from .gw_web.gw_web import GwWeb
from .gw_web_flask.gw_web_flask import GwWebFlask
from .gw_web_manager.gw_web_manager import GwWebManager
4 changes: 3 additions & 1 deletion groundwork_web/plugins/gw_web/gw_web.py
Expand Up @@ -58,7 +58,9 @@ def __server_list(self):
echo(" Plugin: %s" % server.plugin.name)

def __start_flask_debug_server(self):
self.web.flask.run()
self.web.flask.run(host=str(self.app.config.get("FLASK_HOST", "0.0.0.0")),
port=int(self.app.config.get("FLASK_PORT", 5000)),
debug=bool(self.app.config.get("FLASK_DEBUG", True)))

def __test_view(self):
return self.web.render("test.html")
Expand Down
28 changes: 23 additions & 5 deletions groundwork_web/plugins/gw_web/templates/base.html
@@ -1,4 +1,4 @@
{#{% import 'macro.html' as macros with context %}#}
{% import 'macros.html' as macros with context %}
<!DOCTYPE html>
<html lang="en">
<head>
Expand All @@ -21,6 +21,8 @@

{% block analystics -%}
{% endblock -%}
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">

</head>
<body>
<!-- Header -->
Expand All @@ -38,7 +40,7 @@
<a class="navbar-brand" href="/">

{% if get_config("APP_LOGO", "") != ""%}
<img src="{{ get_config("APP_LOGO", "") }}" id="logo_menu">
<img src="{{ get_config('APP_LOGO', '') }}" id="logo_menu">
{% endif %}

<div id="logo_text">
Expand All @@ -48,7 +50,8 @@
</div>
<div class="navbar-collapse collapse" id="navbar-1">
<ul class="nav navbar-nav">
{% for name, menu in get_menu().items() %}
{% for name, menu in get_menu()|dictsort %}
{# {% for name, menu in get_menu().items() %}#}
{% if menu.sub_menus|length == 0 %}
<li><a href="{{ menu.link }}">{{ menu.link_text }}</a></li>
{% else %}
Expand All @@ -57,7 +60,7 @@
aria-haspopup="true" aria-expanded="false">{{ menu.link_text }}
<span class="caret"></span></a>
<ul class="dropdown-menu">
{% for name, menu in menu.sub_menus.items() %}
{% for name, menu in menu.sub_menus|dictsort %}
<li><a href="{{ menu.link }}">{{ menu.link_text }}</a></li>
{% endfor %}
</ul>
Expand All @@ -75,7 +78,22 @@
<div class="container" id="content">
<div class="row">
<div class="col-lg-12">
{% block content %}
{% block messages %}
{{ macros.messages() }}
{% endblock %}
</div>
</div>
<div class="row">
<div class="col-lg-12">
{% block body %}
{% block content %}
{% endblock %}
{% endblock %}
</div>
</div>
<div class="row">
<div class="col-lg-12">
{% block tail %}
{% endblock %}
</div>
</div>
Expand Down
18 changes: 18 additions & 0 deletions groundwork_web/plugins/gw_web/templates/macros.html
@@ -0,0 +1,18 @@
{% macro messages() %}
{% with messages = get_flashed_messages(with_categories=True) %}
{% if messages %}
{% for category, m in messages %}
{% if category %}
{# alert-error changed to alert-danger in bootstrap 3, mapping is for backwards compatibility #}
{% set mapping = {'message': 'info', 'error': 'danger'} %}
<div class="alert alert-{{ mapping.get(category, category) }} alert-dismissable">
{% else %}
<div class="alert alert-dismissable">
{% endif %}
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>
{{ m }}
</div>
{% endfor %}
{% endif %}
{% endwith %}
{% endmacro %}
Empty file.
10 changes: 0 additions & 10 deletions groundwork_web/plugins/gw_web_db_manager/gw_web_db_mamanger.py

This file was deleted.

64 changes: 44 additions & 20 deletions groundwork_web/plugins/gw_web_manager/gw_web_manager.py
@@ -1,5 +1,5 @@
import os
from flask import request
from flask import request, url_for

from groundwork_web.patterns import GwWebPattern

Expand All @@ -11,6 +11,7 @@ class GwWebManager(GwWebPattern):
"""
def __init__(self, *args, **kwargs):
self.name = kwargs.get("name", self.__class__.__name__)
self.needed_plugins = ["GwWeb"]
super().__init__(*args, **kwargs)

def activate(self):
Expand All @@ -22,6 +23,8 @@ def activate(self):
url_prefix="/webmanager",
description="context for web manager urls")

# Pure groundwork objects

self.web.routes.register("/", ["GET"], self.__manager_view, context="webmanager",
name="manager_view", description="Entry-Page for the webmanager")

Expand All @@ -35,10 +38,21 @@ def activate(self):
context="webmanager",
name="plugin_class_details", description="Shows details of a plugin class")

self.web.routes.register("/plugin/instance/<plugin>", ["GET", "POST"], self.__plugin_detail_view,
self.web.routes.register("/plugin/instance/<plugin_name>", ["GET", "POST"], self.__plugin_detail_view,
context="webmanager",
name="plugin_details", description="Shows details of a plugin instance")

self.web.routes.register("/signal", ["GET"], self.__signal_view, context="webmanager",
name="signal_list", description="Lists all registered signals")

self.web.routes.register("/receiver", ["GET"], self.__receiver_view, context="webmanager",
name="receiver_list", description="Lists all registered receivers")

self.web.routes.register("/document", ["GET"], self.__document_view, context="webmanager",
name="document_list", description="Lists all registered documents")

# WEB objects

self.web.routes.register("/route", ["GET"], self.__route_view, context="webmanager",
name="route_list", description="Lists all registered routes")

Expand All @@ -48,20 +62,21 @@ def activate(self):
self.web.routes.register("/context", ["GET"], self.__context_view, context="webmanager",
name="context_list", description="Lists all registered contexts")

self.web.routes.register("/provider", ["GET"], self.__provider_view, context="webmanager",
name="provider_list", description="Lists all registered providers")

self.web.routes.register("/server", ["GET"], self.__server_view, context="webmanager",
name="server_list", description="Lists all registered servers")

webmanager_menu = self.web.menus.register("WebManager", "/webmanager")
self.web.menus.register("Commands", "/webmanager/command", menu=webmanager_menu)
self.web.menus.register("Plugins", "/webmanager/plugin", menu=webmanager_menu)
self.web.menus.register("Routes", "/webmanager/route", menu=webmanager_menu)
self.web.menus.register("Menu entries", "/webmanager/menu", menu=webmanager_menu)
self.web.menus.register("Contexts", "/webmanager/context", menu=webmanager_menu)
self.web.menus.register("Providers", "/webmanager/provider", menu=webmanager_menu)
self.web.menus.register("Servers", "/webmanager/server", menu=webmanager_menu)
with self.app.web.flask.app_context():
webmanager_menu = self.web.menus.register("WebManager", "/webmanager")
webmanager_menu.register("Overview", "/webmanager")
webmanager_menu.register("Commands", url_for("webmanager.__command_view"))
webmanager_menu.register("Signals", url_for("webmanager.__signal_view"))
webmanager_menu.register("Receivers", url_for("webmanager.__receiver_view"))
webmanager_menu.register("Plugins", url_for("webmanager.__plugin_view"))
webmanager_menu.register("Routes", url_for("webmanager.__route_view"))
webmanager_menu.register("Menu entries", url_for("webmanager.__menu_view"))
webmanager_menu.register("Contexts", url_for("webmanager.__context_view"))
webmanager_menu.register("Servers", url_for("webmanager.__server_view"))
webmanager_menu.register("Documents", url_for("webmanager.__document_view"))

def deactivate(self):
pass
Expand All @@ -70,13 +85,22 @@ def __manager_view(self):
return self.web.render("manager.html")

def __command_view(self):
return self.web.render("commands.html", app=self.app)
return self.web.render("commands.html")

def __document_view(self):
return self.web.render("documents.html")

def __signal_view(self):
return self.web.render("signals.html")

def __receiver_view(self):
return self.web.render("receivers.html")

def __plugin_view(self):
return self.web.render("plugins.html", app=self.app)
return self.web.render("plugins.html")

def __plugin_detail_view(self, plugin):
plugin_instance = self.app.plugins.get(plugin)
def __plugin_detail_view(self, plugin_name):
plugin_instance = self.app.plugins.get(plugin_name)
if plugin_instance is None:
return "404"

Expand All @@ -86,7 +110,7 @@ def __plugin_detail_view(self, plugin):
else:
plugin_instance.activate()

return self.web.render("plugin_detail.html", app=self.app, plugin=plugin_instance)
return self.web.render("plugin_detail.html", plugin_instance=plugin_instance)

def __plugin_class_view(self, clazz):
clazz_obj = self.app.plugins.classes.get(clazz)
Expand All @@ -98,11 +122,11 @@ def __plugin_class_view(self, clazz):
name = request.form["name"] or clazz
plugin_instance = self.app.plugins.initialise(plugin_class.clazz, name)

return self.web.render("plugin_class_detail.html", app=self.app, clazz=clazz_obj)
return self.web.render("plugin_class_detail.html", clazz=clazz_obj)

def __route_view(self):
routes = self.app.web.routes.get()
return self.web.render("routes.html", routes=routes, app=self.app)
return self.web.render("routes.html", routes=routes)

def __context_view(self):
contexts = self.app.web.contexts.get()
Expand Down
Expand Up @@ -11,6 +11,7 @@ <h2>{{ context.name }}</h2>
template folder: {{ context.template_folder}} <br>
static folder: {{ context.static_folder}} <br>
url prefix: {{ context.url_prefix}} <br>
static url path: {{ context.static_url_path }}<br>
plugin: {{ context.plugin.name }}

{% endfor %}
Expand Down
26 changes: 26 additions & 0 deletions groundwork_web/plugins/gw_web_manager/templates/documents.html
@@ -0,0 +1,26 @@
{% extends "master.html" %}

{% block content %}

<h1>Documents list</h1>

<table class="table table-striped">
<thead>
<tr>
<th>Name</th>
<th>Description</th>
<th>Plugin</th>
</tr>
</thead>
<tbody>
{% for name, document in app.documents.get().items() %}
<tr>
<td>{{document.name}}</td>
<td>{{document.description}}</td>
<td>{{document.plugin.name}}</td>
</tr>
{% endfor %}
</tbody>
</table>

{% endblock %}

0 comments on commit 978de0b

Please sign in to comment.