Working on base GUI components loader using a depth-three layout: Category->Panel->Section.

Added some fancy error/success messages.
This commit is contained in:
Felipe Martín 2013-11-26 18:11:09 +01:00
parent f65e477241
commit f084b77405
5 changed files with 120 additions and 18 deletions

View File

@ -1,4 +1,4 @@
from flask import Flask, session, render_template, redirect, url_for
from flask import Flask, session, render_template, redirect, url_for, flash
from iosfu.plugin.library import Library
from iosfu.gui.core import GUIController
@ -23,11 +23,25 @@ backup_manager = BackupManager()
backup_manager.lookup()
#
# CONTEXT
#
@server.context_processor
def backup_list():
return dict(backups=backup_manager.backups)
@server.context_processor
def category_list():
return dict(categories=controller._categories)
@server.context_processor
def current_section():
# Empty so jinja can stop yelling at me
return dict(current=dict())
#
# ROUTES
#
@ -39,23 +53,43 @@ def main():
return render_template('main.jinja')
@server.route("/<panel_id>")
def panel(panel_id=None):
@server.route("/<category>/")
def category(category):
"""
Category
"""
# ctx = {'current': {'category': category}}
panels = controller._categories[category]
if len(panels) == 1:
go = redirect(url_for('panel', category=category, panel_id=panels[0]))
else:
# TODO: List Panels? Send to main?
go = 'TODO'
return go
@server.route("/<category>/<panel_id>/")
def panel(category, panel_id):
"""
Panel
"""
panel = controller.load_panel(panel_id)
return "{}".format(panel().__slug__)
ctx = {'current': {'category': category, 'panel': panel}}
template, context = panel.render(ctx)
return render_template(template, **ctx)
@server.route("/<panel_id>.<section_id>")
def section(panel_id=None, section_id=None):
@server.route("/<category>/<panel_id>/<section_id>/")
def section(category, panel_id, section_id):
"""
Section
"""
panel = controller.load_panel(panel_id)
section = panel.get_section(section_id)
return "{}.{}".format(panel.__slug__, section.__slug__)
ctx = {'current': {
'category': category, 'panel': panel, 'section': section}}
template, context = section.render(ctx)
return render_template(template, **ctx)
@server.route("/backup/<backup_id>/")
@ -67,12 +101,17 @@ def select_backup(backup_id):
backup = backup_manager.backups[backup_id]
if backup.valid:
session['backup'] = backup_id
flash('Changed to backup {}'.format(backup_id), 'success')
else:
del session['backup']
flash('The backup you selected is invalid.', 'danger')
# Delete current selected backup -if any
if 'backup' in session:
del session['backup']
except:
# Backup is not loaded / do not exist
# session['backup'] does not exist
# Delete current selected backup -if any
if 'backup' in session:
del session['backup']
flash('The backup you selected was not found.', 'danger')
return redirect(url_for('main'))

View File

@ -39,6 +39,12 @@ class GUIPanel(GUIComponent):
if section_id in self._section_map:
return self.sections[self._section_map[section_id]]()
def render(self, *args, **kwargs):
"""
Main render method
"""
return 'Base GUIPanel'
#
# Privates
#
@ -74,6 +80,12 @@ class GUISection(GUIComponent):
if not self.id and self.name:
self.id = "{}".format(slugify(self.name))
def render(self, *args, **kwargs):
"""
Base rendering method
"""
return "Base GUIComponent"
@property
def __slug__(self):
return self.id

View File

@ -1,5 +1,6 @@
from importlib import import_module
from iosfu.utils import slugify
from .components.base import GUIPanel
@ -10,16 +11,29 @@ class GUIController(object):
_panels = {}
_sections = {}
_categories = {}
def register_panel(self, panel_component):
"""
Decorator to register GUIPanels
Decorator to register GUIPanels.
"""
ins = panel_component()
assert isinstance(ins, GUIPanel)
self._panels[ins.__slug__] = panel_component
slug = ins.__slug__
# Append panel to instance manager
self._panels[slug] = panel_component
# Category handling
category = slugify(ins.category)
if ins.category not in self._categories:
self._categories[category] = []
self._categories[category].append(slug)
def load_from_library(self, library):
"""
Loads all available GUI modules from plugins loaded by the library.
"""
for k, plugin in library.plugins.items():
plugin_module = plugin.__module__
gui_module = "{0}.{1}".format(
@ -33,5 +47,8 @@ class GUIController(object):
print(error)
def load_panel(self, panel_id):
"""
Returns the given GUIPanel instance.
"""
if panel_id in self._panels:
return self._panels[panel_id]()

View File

@ -15,12 +15,15 @@
<nav class="navbar navbar-default navbar-static-top" role="navigation">
<div class="container">
<!-- Left -->
<a class="navbar-brand" href="#">
<a class="navbar-brand" href="/">
iOSFU
</a>
<ul class="nav navbar-nav">
<li class="active"><a href="#">Link 1</a></li>
<li><a href="#">Link 2</a></li>
{% for category in categories %}
<li {% if current.category == category %}class="active"{% endif %}>
<a href="/{{ category }}">{{ category|title }}</a>
</li>
{% endfor %}
</ul>
<!-- Right -->
@ -37,13 +40,13 @@
Change <b class="caret"></b>
</a>
<!-- Backup list -->
<ul class="dropdown-menu">
<ul class="dropdown-menu text-right">
{% for backup_id in backups %}
<li>
{% if backups[backup_id].valid %}
<a href="/backup/{{ backup_id }}/">{{ backup_id }}</a>
{% else %}
<a href="/backup/{{ backup_id }}/" data-toggle="tooltip" title="This backup seems invalid">
<a href="/backup/{{ backup_id }}/" data-toggle="tooltip" title="This backup seems invalid" data-placement="left">
{{ backup_id }}
<span class="glyphicon glyphicon-exclamation-sign text-danger"></span>
</a>
@ -57,15 +60,41 @@
</nav>
<div class="container">
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for category, message in messages %}
<div class="alert alert-{{ category }}">{{ message }}</div>
{% endfor %}
{% endif %}
{% endwith %}
<ol class="breadcrumb">
<li><a href="/">iOSFU</a></li>
<li><a href="#">-- Plugin --</a></li>
<li class="active">-- Section --</li>
{% if current.category %}
<li><a href="/{{ current.category }}/">{{ current.category|title }}</a></li>
{% endif %}
{% if current.panel %}
<li class="active">
<a href="/{{ current.category }}/{{ current.panel.id }}/">{{ current.panel.name }}</a>
</li>
{% endif %}
{% if current.section %}
<li class="active">
<!-- <a href="/{{ current.category }}/{{ current.panel }}/{{ current.section }}"> -->
{{ current.section }}
<!-- </a> -->
</li>
{% endif %}
</ol>
</div>
<!-- JS -->
<script src="https://code.jquery.com/jquery.js"></script>
<script src="/static/bootstrap/js/bootstrap.min.js"></script>
<script type="text/javascript">
// Init tooltips
$(function(){
$('[data-toggle=tooltip]').tooltip()
});
</script>
</body>
</html>

View File

@ -19,7 +19,12 @@ class DeviceInfoPanel(GUIPanel):
name = 'Device info'
category = 'Base'
sections = [
Main,
VersionInfo
]
def render(self, context):
return 'main.jinja', context