Commit db772fd3 authored by Jan Čermák's avatar Jan Čermák

refactoring of config.py - add another level of abstraction (mixin) as in...

refactoring of config.py - add another level of abstraction (mixin) as in wizard; custom page for wifi config - closes #2915
parent c2c01c1b
......@@ -12,85 +12,110 @@ logger = logging.getLogger("admin")
app = Bottle()
# names of handlers used in their URL
# use dash-separated names, underscores in URL are ugly
class ConfigPageMixin(object):
template = "config/main"
def default_template(self, **kwargs):
return template(self.template, **kwargs)
def render(self, **kwargs):
# same premise as in wizard form - we are handling single-section ForisForm
form = self.form
first_section = form.sections[0]
title = first_section.title
description = first_section.description
return self.default_template(form=form, title=title, description=description, **kwargs)
class PasswordConfigPage(ConfigPageMixin, PasswordHandler):
pass
class WanConfigPage(ConfigPageMixin, WanHandler):
pass
class LanConfigPage(ConfigPageMixin, LanHandler):
pass
class HandlerMapItems(OrderedDict):
class WifiConfigPage(ConfigPageMixin, WifiHandler):
template = "config/wifi"
class SystemPasswordConfigPage(ConfigPageMixin, SystemPasswordHandler):
pass
class ConfigPageMapItems(OrderedDict):
def display_names(self):
return [{'slug': k, 'name': self[k].userfriendly_title} for k in self.keys()]
handler_map = HandlerMapItems((
('password', PasswordHandler),
('wan', WanHandler),
('lan', LanHandler),
('wifi', WifiHandler),
('system-password', SystemPasswordHandler),
# names of handlers used in their URL
# use dash-separated names, underscores in URL are ugly
config_page_map = ConfigPageMapItems((
('password', PasswordConfigPage),
('wan', WanConfigPage),
('lan', LanConfigPage),
('wifi', WifiConfigPage),
('system-password', SystemPasswordConfigPage),
))
def get_handler(handler_name):
Handler = handler_map.get(handler_name)
if Handler is None:
def get_config_page(page_name):
ConfigPage = config_page_map.get(page_name)
if ConfigPage is None:
raise bottle.HTTPError(404, "Unknown configuration page.")
return Handler
def render(form, **kwargs):
# same premise as in wizard form - we are handling single-section ForisForm
first_section = form.sections[0]
title = first_section.title
description = first_section.description
return template("config/main", form=form, title=title, description=description,
handlers=handler_map.display_names(), **kwargs)
return ConfigPage
@app.route("/", name="config_index")
@login_required
def index():
return template("config/index", handlers=handler_map.display_names())
return template("config/index", config_pages=config_page_map.display_names())
@app.route("/<handler_name:re:.+>/", name="config_handler")
@app.route("/<page_name:re:.+>/", name="config_page")
@login_required
def handler_get(handler_name):
Handler = get_handler(handler_name)
handler = Handler()
return render(handler.form, active_handler_key=handler_name)
def config_page_get(page_name):
ConfigPage = get_config_page(page_name)
config_page = ConfigPage()
return config_page.render(config_pages=config_page_map.display_names(),
active_config_page_key=page_name)
@app.route("/<handler_name:re:.+>/", method="POST")
@app.route("/<page_name:re:.+>/", method="POST")
@login_required
def handler_post(handler_name):
Handler = get_handler(handler_name)
handler = Handler(request.POST)
def config_page_post(page_name):
ConfigPage = get_config_page(page_name)
config_page = ConfigPage(request.POST)
if request.is_xhr:
# only update is allowed
logger.debug("ajax request")
request.POST.pop("update", None)
return dict(html=render(handler.form, is_xhr=True))
return dict(html=config_page.render(is_xhr=True))
try:
if handler.save():
if config_page.save():
bottle.redirect(request.fullpath)
except TypeError:
# raised by Validator - could happen when the form is posted with wrong fields
pass
return render(handler.form, active_handler_key=handler_name)
return config_page.render(active_handler_key=page_name)
@app.route("/<handler_name:re:.+>/ajax")
@app.route("/<page_name:re:.+>/ajax")
@login_required
def config_ajax(handler_name):
def config_ajax(page_name):
action = request.GET.get("action")
if not action:
raise bottle.HTTPError(404, "AJAX action not specified.")
Handler = get_handler(handler_name)
handler = Handler()
ConfigPage = get_config_page(page_name)
config_page = ConfigPage()
try:
result = handler.call_action(action)
result = config_page.call_action(action)
return result
except ValueError:
raise bottle.HTTPError(404, "Unknown action.")
\ No newline at end of file
......@@ -10,12 +10,12 @@
<div id="config-content">
<ul class="tabs">
%for handler in handlers:
%for config_page in config_pages:
<li \\
%if defined("active_handler_key") and handler['slug'] == active_handler_key:
%if defined("active_config_page_key") and config_page['slug'] == active_config_page_key:
class="active" \\
%end\\
><a href="{{ url("config_handler", handler_name=handler['slug']) }}">{{ _(handler['name']) }}</a></li>
><a href="{{ url("config_page", page_name=config_page['slug']) }}">{{ _(config_page['name']) }}</a></li>
%end
</ul>
%end
......
%rebase config/base **locals()
<form id="main-form" class="config-form config-form-wifi" action="{{ request.fullpath }}" method="post" autocomplete="off" {{! form.render_html_data() }}>
<p class="config-description">{{! description }}</p>
%for field in form.active_fields:
%if field.hidden:
{{! field.render() }}
%else:
<div>
{{! field.label_tag }}
{{! field.render() }}
%if field.hint:
<img class="field-hint" src="{{ static("img/icon-help.png") }}" title="{{ field.hint }}">
%end
</div>
%end
%end
<div id="wifi-qr">
</div>
<script src="{{ static("js/contrib/jquery.qrcode-0.7.0.min.js") }}"></script>
<script>
$(document).ready(function() {
ForisWizard.initWiFiQR();
});
</script>
<div class="form-buttons">
<a href="{{ request.fullpath }}" type="submit" class="button grayed">{{ _("Discard changes") }}</a>
<button type="submit" name="send" class="button">{{ _("Save changes") }}</button>
</div>
</form>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment