Verified Commit 86bc39eb authored by Štěpán Henek's avatar Štěpán Henek 🌩

Merge branch '3.11'

parents cb2f91a2 0b533307
98.11 (2018-09-21)
------------------
* dhcp lease time option added to LAN and guest tabs
98.10 (2018-09-20)
------------------
* config menu refactoring
* added reset guide button to guide
* profile tab added (only for turris-os-version >= 4.0 and mox/omnia only)
* new modal dialogs using js library vex
* new spinner for restarts and reboots
* lan tab splitted to lan and guest tabs
* networks tab added (only for turris-os-version >= 4.0 and mox/omnia only)
* fixing reboot confirms
98.9 (2018-08-29)
-----------------
* mox branding added
98.8 (2018-08-29)
-----------------
* password and administration tab merged
* wifi tab show message fix
98.7 (2018-08-16)
-----------------
* session fix
98.6 (2018-08-16)
-----------------
* python3 compatibility
* jinja2 and ws fix
98.5 (2018-08-09)
-----------------
* version printing
* using console scripts in entry points
98.4 (2018-06-29)
-----------------
* CHANGELOG file added
* new plugin system integrated
# Foris - web administration interface for OpenWrt based on NETCONF
# Copyright (C) 2013 CZ.NIC, z.s.p.o. <http://www.nic.cz>
# Copyright (C) 2018 CZ.NIC, z.s.p.o. <http://www.nic.cz>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
......@@ -20,33 +20,10 @@ COMPILED_CSS = $(wildcard foris/static/css/*)
COMPILED_L10N = $(wildcard foris/locale/*/LC_MESSAGES/*.mo)
JS_FILES = $(filter-out %.min.js $(wildcard foris/static/js/contrib/*),$(wildcard \
foris/static/js/*.js \
foris/static/js/**/*.js \
))
JS_MINIFIED = $(JS_FILES:.js=.min.js)
PRE_TPL_FILES = $(wildcard \
foris/templates/*.pre.tpl \
foris/templates/**/*.pre.tpl \
)
TPL_FILES = $(PRE_TPL_FILES:.pre.tpl=.tpl)
JS_MINIFIER = slimit -m
SASS_COMPILER = compass compile -s compressed -e production
all: branding sass js localization tpl
# target: js - Create minified JS files using slimit JS compressor.
js: $(JS_FILES) $(JS_MINIFIED)
# target: tpl - Do preprocessing of .pre.tpl files.
tpl: $(PRE_TPL_FILES) $(TPL_FILES)
all: branding sass
# target: branding - Copy assets for a specified device to its location.
branding:
......@@ -62,29 +39,17 @@ sass:
$(SASS_COMPILER)
@echo
# target: localization - Create .mo files from .po fiels in locale directory
localization:
@echo "-- Compiling localization files"
@tools/compilemessages.sh foris
@echo "Done."
@echo
%.tpl: %.pre.tpl
@echo '-- Preprocessing template $<'
tools/preprocess_template.sh $< > $@
@echo
%.min.js: %.js
@echo '-- Minifying $<'
$(JS_MINIFIER) $< > $@
@echo
# target: clean - Remove all compiled CSS, JS and localization files.
# target: clean - Remove all compiled CSS and localization files.
clean:
rm -rf $(COMPILED_CSS) $(COMPILED_L10N) $(JS_MINIFIED) $(TPL_FILES)
rm -rf $(COMPILED_CSS) $(COMPILED_L10N) $(TPL_FILES)
# target: help - Show this help.
help:
@egrep "^# target:" Makefile
.PHONY: all branding sass js localization tpl
# target: messages - extract translations from sources
messages:
./setup.py extract_messages --no-location -o foris/locale/foris.pot -F babel.cfg
./setup.py update_catalog -D foris -i foris/locale/foris.pot -d foris/locale/
.PHONY: all branding sass messages
[jinja2: **/templates/**.j2]
encoding = utf-8
[python: **.py]
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
width="100%"
height="100%"
viewBox="0 0 230 76"
id="Layer_1"
xml:space="preserve"
sodipodi:docname="logo-turris.svg"
inkscape:version="0.92.3 (2405546, 2018-03-11)"><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1080"
id="namedview20"
showgrid="false"
inkscape:zoom="1.4521739"
inkscape:cx="-81.257489"
inkscape:cy="65.54491"
inkscape:window-x="1920"
inkscape:window-y="0"
inkscape:window-maximized="0"
inkscape:current-layer="Layer_1" /><metadata
id="metadata3255"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><defs
id="defs3253" /><style
type="text/css"
id="style3217" /><path
d="M 95.7,3 V 13.4 H 92.5 V 3 H 88.8 V 0.3 H 99.3 V 3 h -3.6 z"
id="path3233"
style="fill:#00a2e2;fill-opacity:1" /><path
d="m 112.3,10.6 c -0.3,0.6 -0.6,1.2 -1.1,1.7 -0.5,0.5 -1.1,0.8 -1.8,1.1 -0.7,0.3 -1.5,0.4 -2.3,0.4 -0.9,0 -1.6,-0.1 -2.3,-0.4 -0.7,-0.3 -1.3,-0.6 -1.8,-1.1 -0.5,-0.5 -0.8,-1 -1.1,-1.7 -0.3,-0.6 -0.4,-1.4 -0.4,-2.1 V 0.3 h 3.1 v 7.9 c 0,0.4 0,0.7 0.1,1 0.1,0.3 0.2,0.6 0.4,0.9 0.2,0.3 0.4,0.5 0.8,0.6 0.3,0.1 0.7,0.2 1.1,0.2 0.4,0 0.8,-0.1 1.1,-0.2 0.3,-0.1 0.6,-0.3 0.8,-0.6 0.2,-0.3 0.3,-0.5 0.4,-0.9 0.1,-0.3 0.1,-0.7 0.1,-1 V 0.3 h 3.2 v 8.1 c 0.1,0.8 0,1.6 -0.3,2.2 z"
id="path3235"
style="fill:#00a2e2;fill-opacity:1" /><path
d="m 123.1,13.4 -2.8,-5.2 h -1.1 v 5.2 h -3.1 v -13 h 5 c 0.6,0 1.2,0.1 1.8,0.2 0.6,0.1 1.1,0.3 1.6,0.7 0.5,0.3 0.9,0.7 1.1,1.2 0.3,0.5 0.4,1.1 0.4,1.9 0,0.9 -0.2,1.6 -0.7,2.2 -0.5,0.6 -1.1,1 -2,1.3 l 3.4,5.6 h -3.6 z M 123,4.3 C 123,4 122.9,3.7 122.8,3.6 122.7,3.4 122.5,3.3 122.3,3.2 122.1,3.1 121.9,3 121.6,3 121.3,3 121.1,2.9 120.9,2.9 h -1.7 v 3 h 1.5 c 0.3,0 0.5,0 0.8,-0.1 0.3,0 0.5,-0.1 0.7,-0.2 0.2,-0.1 0.4,-0.3 0.5,-0.5 0.2,-0.2 0.3,-0.4 0.3,-0.8 z"
id="path3237"
style="fill:#00a2e2;fill-opacity:1" /><path
d="m 136.1,13.4 -2.8,-5.2 h -1.1 v 5.2 h -3.1 v -13 h 5 c 0.6,0 1.2,0.1 1.8,0.2 0.6,0.1 1.1,0.3 1.6,0.7 0.5,0.3 0.9,0.7 1.1,1.2 0.2,0.5 0.4,1.1 0.4,1.9 0,0.9 -0.2,1.6 -0.7,2.2 -0.5,0.6 -1.1,1 -2,1.3 l 3.4,5.6 h -3.6 z M 136,4.3 C 136,4 135.9,3.7 135.8,3.6 135.7,3.4 135.5,3.3 135.3,3.2 135.1,3.1 134.9,3 134.6,3 134.3,3 134.1,2.9 133.9,2.9 h -1.7 v 3 h 1.5 c 0.3,0 0.5,0 0.8,-0.1 0.3,0 0.5,-0.1 0.7,-0.2 0.2,-0.1 0.4,-0.3 0.5,-0.5 0.2,-0.2 0.3,-0.4 0.3,-0.8 z"
id="path3239"
style="fill:#00a2e2;fill-opacity:1" /><path
d="m 142.1,13.4 v -13 h 3.2 v 13 h -3.2 z"
id="path3241"
style="fill:#00a2e2;fill-opacity:1" /><path
d="m 155.7,3.7 c -0.3,-0.3 -0.6,-0.6 -1.1,-0.8 -0.4,-0.2 -0.9,-0.3 -1.3,-0.3 -0.2,0 -0.4,0 -0.6,0.1 -0.2,0 -0.4,0.1 -0.6,0.2 -0.2,0.1 -0.3,0.2 -0.4,0.4 -0.1,0.2 -0.2,0.4 -0.2,0.6 0,0.2 0,0.4 0.1,0.6 0.1,0.1 0.2,0.3 0.4,0.4 0.2,0.1 0.4,0.2 0.6,0.3 0.2,0.1 0.5,0.2 0.8,0.3 0.4,0.1 0.9,0.3 1.4,0.5 0.5,0.2 0.9,0.4 1.3,0.7 0.4,0.3 0.7,0.7 1,1.1 0.3,0.4 0.4,1 0.4,1.6 0,0.7 -0.1,1.4 -0.4,1.9 -0.3,0.5 -0.6,1 -1.1,1.4 -0.5,0.4 -1,0.6 -1.6,0.8 -0.6,0.2 -1.2,0.3 -1.9,0.3 -0.9,0 -1.8,-0.2 -2.7,-0.5 -0.9,-0.3 -1.6,-0.8 -2.2,-1.4 l 2.1,-2.1 c 0.3,0.4 0.7,0.7 1.3,1 0.5,0.3 1,0.4 1.6,0.4 0.2,0 0.5,0 0.7,-0.1 0.2,0 0.4,-0.1 0.6,-0.2 0.2,-0.1 0.3,-0.3 0.4,-0.4 0.1,-0.2 0.1,-0.4 0.1,-0.7 0,-0.2 -0.1,-0.5 -0.2,-0.6 -0.1,-0.2 -0.3,-0.3 -0.5,-0.5 -0.2,-0.2 -0.5,-0.3 -0.8,-0.4 -0.3,-0.1 -0.7,-0.2 -1.2,-0.4 -0.4,-0.1 -0.8,-0.3 -1.2,-0.5 -0.4,-0.2 -0.8,-0.4 -1.1,-0.7 -0.3,-0.3 -0.6,-0.6 -0.8,-1 -0.2,-0.4 -0.3,-0.9 -0.3,-1.5 0,-0.7 0.1,-1.3 0.4,-1.9 0.3,-0.5 0.7,-0.9 1.2,-1.3 0.5,-0.3 1,-0.6 1.6,-0.7 0.6,-0.2 1.2,-0.2 1.8,-0.2 0.7,0 1.5,0.1 2.3,0.4 0.8,0.3 1.4,0.7 2,1.2 l -1.9,2 z"
id="path3243"
style="fill:#00a2e2;fill-opacity:1" /><polygon
points="39.9,41.5 39.8,41.5 0,41.5 8,55.3 31.9,55.3 43.9,76 59.8,76 39.9,41.5 "
id="polygon3245"
style="fill:#1d1d1b" /><polygon
points="73.7,17.4 65.7,3.6 45.8,38.1 65.8,72.6 73.7,58.8 61.8,38.1 "
id="polygon3247"
style="fill:#1d1d1b" /><polygon
points="51.8,13.9 59.8,0.1 20,0.1 0,34.6 16,34.6 27.9,13.9 "
id="polygon3249"
style="fill:#00a2e2;fill-opacity:1" /><text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
x="88"
y="42.700001"
id="text948"><tspan
sodipodi:role="line"
id="tspan946"
x="88"
y="78.090622" /></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:bold;font-size:40px;line-height:1.25;font-family:Roboto;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;-inkscape-font-specification:'Roboto Bold';font-stretch:normal;font-variant:normal;"
x="99.850296"
y="48.45509"
id="text3726"><tspan
sodipodi:role="line"
id="tspan3724"
x="99.850296"
y="83.845718" /></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:40px;line-height:1.25;font-family:Roboto;-inkscape-font-specification:Roboto;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
x="88.11377"
y="46.718563"
id="text3730"><tspan
sodipodi:role="line"
id="tspan3728"
x="88.11377"
y="46.718563"
style="font-weight:bold">MOX</tspan></text>
</svg>
\ No newline at end of file
@import url('./fonts.css')
$highlight-color: #00a2e2
$highlight-color-active: lighten(desaturate($highlight-color, 20), 15)
// overwrite variables defined in _variables.sass
$sidebar-active-tab-color: $highlight-color
$button-color: $highlight-color
$button-color-active: $highlight-color-active
$base-font: 'Roboto', Helvetica, Arial, sans-serif
$base-font-size: 16px
$heading-font: $base-font
@font-face
font-family: 'Roboto'
font-style: normal
font-weight: 400
src: local('Roboto'), local('Roboto-Regular'), url('../fonts/Roboto-Regular.woff') format('woff')
@font-face
font-family: 'Roboto'
font-style: normal
font-weight: 700
src: local('Roboto Bold'), local('Roboto-Bold'), url('../fonts/Roboto-Bold.woff') format('woff')
This diff is collapsed.
Foris sample plugin
===================
This is a sample plugin for foris
Requirements
============
* foris
* foris-controller-sample-module
Installation
============
``python setup.py install``
or
``pip install .``
__path__ = __import__('pkgutil').extend_path(__path__, __name__)
import bottle
import os
from foris import fapi, validators
from foris.config import ConfigPageMixin, add_config_page
from foris.config_handlers import BaseConfigHandler
from foris.form import Number
from foris.plugins import ForisPlugin
from foris.state import current_state
from foris.utils.translators import gettext_dummy as gettext, gettext as _
# This represents a main form handler
class SamplePluginConfigHandler(BaseConfigHandler):
# gettext() triggers lazy_translated text
# it is also used for detecting translations during foris_make_messages cmd
userfriendly_title = gettext("Sample")
def get_form(self):
data = current_state.backend.perform("sample", "get_slices")
if self.data:
# Update from post (used when the form is updated via ajax)
data.update(self.data)
form = fapi.ForisForm("sample", data)
section = form.add_section(
name="main_section",
title=self.userfriendly_title,
)
# _() translates the string immediatelly
# it is also used for detecting translations during foris_make_messages cmd
section.add_field(
Number, name="slices", label=_("Number of slices"), required=True,
validators=validators.InRange(2, 15)
)
def form_cb(data):
res = current_state.backend.perform(
"sample", "set_slices", {"slices": int(data["slices"])})
return "save_result", res # store {"result": ...} to be used in SamplePluginPage save() method
form.add_callback(form_cb)
return form
# This represents a plugin page
class SamplePluginPage(ConfigPageMixin, SamplePluginConfigHandler):
slug = "sample" # part of the url of the plugin (.../config/<slug>)
menu_order = 90 # Where it should be placed in the main menu (higher the number the lower)
template = "sample/sample" # template which will be used (.html.js will be auto added)
template_type = "jinja2"
def get_backend_data(self):
res = current_state.backend.perform("sample", "list")
return res["records"]
def save(self, *args, **kwargs):
# Handle form result here
return super(SamplePluginPage, self).save(*args, **kwargs)
def _prepare_render_args(self, args):
args['PLUGIN_NAME'] = SamplePlugin.PLUGIN_NAME
args['PLUGIN_STYLES'] = SamplePlugin.PLUGIN_STYLES
args['PLUGIN_STATIC_SCRIPTS'] = SamplePlugin.PLUGIN_STATIC_SCRIPTS
args['PLUGIN_DYNAMIC_SCRIPTS'] = SamplePlugin.PLUGIN_DYNAMIC_SCRIPTS
args['records'] = self.get_backend_data()
def render(self, **kwargs):
self._prepare_render_args(kwargs)
return super(SamplePluginPage, self).render(**kwargs)
def _action_get_records(self):
# obtain and render the data and render a partial template (for ajax)
records = self.get_backend_data()
return bottle.template(
"sample/_records.html.j2",
records=records,
template_adapter=bottle.Jinja2Template,
)
def call_ajax_action(self, action):
if action == "get_records":
return self._action_get_records()
raise ValueError("Unknown AJAX action.")
# plugin definition
class SamplePlugin(ForisPlugin):
PLUGIN_NAME = "sample" # also shown in the url
DIRNAME = os.path.dirname(os.path.abspath(__file__))
PLUGIN_STYLES = [
"css/sample.css", # path to css script generated using sass/sample.sass
]
PLUGIN_STATIC_SCRIPTS = [
"js/contrib/Chart.bundle.min.js", # 3rd party static js
"js/sample.js", # static js file
]
PLUGIN_DYNAMIC_SCRIPTS = [
"sample.js", # dynamic js file (a template which will be rendered to javascript)
]
def __init__(self, app):
super(SamplePlugin, self).__init__(app)
add_config_page(SamplePluginPage)
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 48.2 (47327) - http://www.bohemiancoding.com/sketch -->
<title>icon / turris / dark</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Assets" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="icon-/-turris-/-dark" fill="#595959">
<polygon id="Path" points="6.33888735 0 0 11 5.06435376 11 8.87106423 4.39428334 16.4675949 4.39428334 19 0"></polygon>
<polygon id="Path" points="14 11.9925632 20.4310855 23 23 18.6028832 19.1380606 11.9925632 22.9914323 5.39711679 20.4222863 1"></polygon>
<polygon id="Path" points="12.6666667 13 12.6497839 13 0 13 2.53105187 17.3998626 10.1413184 17.3998626 13.9378963 24 19 24 12.6723703 13"></polygon>
</g>
</g>
</svg>
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
// Render a chart based on table data
var make_chart = function() {
var graph_config = {
data: {
datasets: [
{
lineTension: 0,
label: Foris.sampleMessages.chartLabel, // transaltions are defined within dynamic js
data: graph_data,
},
],
fill: true,
},
options: {
responsive: true,
title: {
display: true,
text: Foris.sampleMessages.chartTitle // transaltions are defined within dynamic js
},
tooltips: {
mode: 'index',
intersect: false,
},
hover: {
mode: 'nearest',
intersect: true
},
scales: {
xAxes: [{
display: false,
scaleLabel: {
display: true,
labelString: Foris.sampleMessages.chartTimeAxis // transaltions are defined within dynamic js
}
}],
yAxes: [{
display: true,
ticks: {
suggestedMin: 0,
suggestedMax: 100,
},
scaleLabel: {
display: true,
labelString: Foris.sampleMessages.chartValueAxis // transaltions are defined within dynamic js
}
}],
},
},
};
var graph_ctx = document.getElementById("canvas").getContext("2d");
graph_config.options.scales.xAxes[0].ticks = {
min: graph_config.data.datasets[0].data[0].x,
max: graph_config.data.datasets[0].data[graph_config.data.datasets[0].data.length - 1].x,
};
Foris.lineChart = new Chart.Scatter(graph_ctx, graph_config);
Foris.lineChartData = graph_config.data;
Foris.lineChartOptions = graph_config.options;
}
// Global chart data
var graph_data;
// Functions which updates the chart
Foris.update_sample_chart = function() {
// Clear current chart
$("#canvas-container").empty();
$("#canvas-container").append('<canvas id="canvas"></canvas>');
// Set data
graph_data = [];
var idx = 0;
$("#records-table td.table-index").each(function(idx, item) {
graph_data[idx] = {x: parseInt($(item).text())};
idx++;
});
idx = 0;
$("#records-table td.table-value").each(function(idx, item) {
graph_data[idx]["y"] = parseInt($(item).text());
idx++;
});
// render chart
make_chart();
}
// Update chart after page is rendred
$(document).ready(function() {
Foris.update_sample_chart();
});
/* a simple sass example */
#records
td, th
padding: 0.3em 0.8em
border-bottom: 1px solid #fff
tr:first-child td
padding-top: 0.5em
tbody tr
&:nth-child(2n) td
background: #f2f2f2
&:hover td
border-bottom: 1px solid #00a2e2
th
font-weight: bold
border-bottom: 1px solid #ddd
margin-bottom: 2px
tbody td
&:nth-child(2), &:nth-child(3), &:nth-child(4)
text-align: right
// Translation has to be handeled dynamically in jinja2 template here
Foris.sampleMessages = {
chartLabel: "{% trans %}Chart Data{% endtrans %}",
chartTitle: "{% trans %}Example chart{% endtrans %}",
chartTimeAxis: "{% trans %}Time axis{% endtrans %}",
chartValueAxis: "{% trans %}Value axis{% endtrans %}"
}
// Register on websockets events (just reload chart is used
Foris.WS["sample"] = function(msg) {
switch(msg.action) {
case "reload_chart":
$.get('{{ url("config_ajax", page_name="sample") }}', {action: "get_records"})
.done((response) => {
$("#records-table").replaceWith(response);
Foris.update_sample_chart();
})
break;
}
}
<table id="records-table">
<thead><th>#</th><th>{% trans %}Value{% endtrans %}</th></thead>
<tbody>
{% for idx, value in records %}
<tr><td class="table-index">{{ idx }}</td><td class="table-value">{{ value }}</td></tr>
{% endfor %}
</tbody>
</table>
{% extends 'config/base.html.j2' %}
{# this block will be inserted into the main layout #}
{% block config_base %}
{# The the main form can be rendered using ajax. And it might be necessary to skip some parts for that #}
{% if is_xhr is not defined %}
<div id="page-sample-plugin" class="config-page">
{% endif %}
{# Just for fun render some images #}
{% for _ in range(20) %}
<img src="{{ static('plugins/sample/img/logo-dark.svg') }}"/>
{% endfor %}
{# Render messages that config store operation passed/failed #}
{% include '_messages.html.j2' %}
<p>{% trans %}Some generic description what this plugin does.{% endtrans %}</p>
<form action="{{ request.fullpath }}" method="post" class="config-form">
<input type="hidden" name="csrf_token" value="{{ get_csrf_token() }}">
{# For the most cases this is how the forms are rendered #}
{% for field in form.active_fields %}
{% include '_field.html.j2' %}
{% endfor %}
<button type="submit" name="send">{% trans %}Update configuration{% endtrans %}</button>
</form>
<h3>{% trans %}Records{% endtrans %}</h3>
<div id="records">
{# Example to render some data #}
{% include 'sample/_records.html.j2' %}
</div>
<h3>{% trans %}Chart{% endtrans %}</h3>
<p>{% trans %}To redraw the chart using websockets just run the following command:{% endtrans %}</p>
<pre>foris-notify-wrapper -n -m sample -a reload_chart '{}'</pre>
<br />
{# Example chart in Chart.js #}
<div id="canvas-container"><canvas id="canvas"></canvas></div>
{% if is_xhr is not defined %}
</div>
{% endif %}
{% endblock %}
#!/usr/bin/env python
import copy
from setuptools import setup
from setuptools.command.build_py import build_py
class BuildCmd(build_py):
def run(self):
# build foris plugin files
from foris_plugins_distutils import build
cmd = build(copy.copy(self.distribution))
cmd.ensure_finalized()
cmd.run()
# build package
build_py.run(self)
setup(
name="Foris Sample Plugin",
version="0",
description="Sample plugin for foris web interface",
author="CZ.NIC, z. s. p. o.",
author_email="stepan.henek@nic.cz",
url="https://gitlab.labs.nic.cz/turris/foris-sample-plugin/",
license="GPL-3.0",
requires=[
"foris",
],
setup_requires=[
'babel',
'jinja2',
'libsass',
'foris_plugins_distutils',
],
provides=[
"foris_plugins.sample",
],