Merge pull request #397 from mterzo/offline_fix
Add offline mode for Semantic UI.
This commit is contained in:
@@ -15,6 +15,7 @@ from flask import (
|
|||||||
Response, stream_with_context, redirect,
|
Response, stream_with_context, redirect,
|
||||||
request, session, jsonify
|
request, session, jsonify
|
||||||
)
|
)
|
||||||
|
from jinja2.utils import contextfunction
|
||||||
|
|
||||||
from pypuppetdb.QueryBuilder import *
|
from pypuppetdb.QueryBuilder import *
|
||||||
|
|
||||||
@@ -1091,3 +1092,15 @@ def daily_reports_chart(env):
|
|||||||
certname=certname,
|
certname=certname,
|
||||||
)
|
)
|
||||||
return jsonify(result=result)
|
return jsonify(result=result)
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/offline/<path:filename>')
|
||||||
|
def offline_static(filename):
|
||||||
|
mimetype = 'text/html'
|
||||||
|
if filename.endswith('.css'):
|
||||||
|
mimetype = 'text/css'
|
||||||
|
elif filename.endswith('.js'):
|
||||||
|
mimetype = 'text/javascript'
|
||||||
|
|
||||||
|
return Response(response=render_template('static/%s' % filename),
|
||||||
|
status=200, mimetype=mimetype)
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ from flask import Flask
|
|||||||
|
|
||||||
from pypuppetdb import connect
|
from pypuppetdb import connect
|
||||||
from puppetboard.utils import (jsonprint, prettyprint, url_for_field,
|
from puppetboard.utils import (jsonprint, prettyprint, url_for_field,
|
||||||
get_or_abort)
|
url_static_offline, get_or_abort)
|
||||||
|
|
||||||
from . import __version__
|
from . import __version__
|
||||||
|
|
||||||
@@ -31,6 +31,7 @@ def get_app():
|
|||||||
app.jinja_env.filters['jsonprint'] = jsonprint
|
app.jinja_env.filters['jsonprint'] = jsonprint
|
||||||
app.jinja_env.filters['prettyprint'] = prettyprint
|
app.jinja_env.filters['prettyprint'] = prettyprint
|
||||||
app.jinja_env.globals['url_for_field'] = url_for_field
|
app.jinja_env.globals['url_for_field'] = url_for_field
|
||||||
|
app.jinja_env.globals['url_static_offline'] = url_static_offline
|
||||||
APP = app
|
APP = app
|
||||||
|
|
||||||
return APP
|
return APP
|
||||||
|
|||||||
BIN
puppetboard/static/fonts/lato-italic-400.ttf
Normal file
BIN
puppetboard/static/fonts/lato-italic-400.ttf
Normal file
Binary file not shown.
BIN
puppetboard/static/fonts/lato-italic-700.ttf
Normal file
BIN
puppetboard/static/fonts/lato-italic-700.ttf
Normal file
Binary file not shown.
BIN
puppetboard/static/fonts/lato-normal-400.ttf
Normal file
BIN
puppetboard/static/fonts/lato-normal-400.ttf
Normal file
Binary file not shown.
BIN
puppetboard/static/fonts/lato-normal-700.ttf
Normal file
BIN
puppetboard/static/fonts/lato-normal-700.ttf
Normal file
Binary file not shown.
@@ -13,11 +13,12 @@
|
|||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<link href='{{ url_for('static', filename='jquery-datatables-1.10.13/dataTables.semanticui.min.css') }}' rel='stylesheet' type='text/css'>
|
<link href='{{ url_for('static', filename='jquery-datatables-1.10.13/dataTables.semanticui.min.css') }}' rel='stylesheet' type='text/css'>
|
||||||
|
<link href="{{ url_for('offline_static', filename='Semantic-UI-2.1.8/semantic.min.css') }}" rel="stylesheet" />
|
||||||
{% else %}
|
{% else %}
|
||||||
<link href='//fonts.googleapis.com/css?family=Open+Sans' rel='stylesheet' type='text/css' />
|
<link href='//fonts.googleapis.com/css?family=Open+Sans' rel='stylesheet' type='text/css' />
|
||||||
|
<link href="{{ url_for('static', filename='Semantic-UI-2.1.8/semantic.min.css') }}" rel="stylesheet" />
|
||||||
<link href='//cdnjs.cloudflare.com/ajax/libs/datatables/1.10.13/css/dataTables.semanticui.min.css' rel='stylesheet' type='text/css'>
|
<link href='//cdnjs.cloudflare.com/ajax/libs/datatables/1.10.13/css/dataTables.semanticui.min.css' rel='stylesheet' type='text/css'>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<link href="{{ url_for('static', filename='Semantic-UI-2.1.8/semantic.min.css') }}" rel="stylesheet" />
|
|
||||||
<link href="{{ url_for('static', filename='css/puppetboard.css') }}" rel="stylesheet" />
|
<link href="{{ url_for('static', filename='css/puppetboard.css') }}" rel="stylesheet" />
|
||||||
|
|
||||||
{% if config.OFFLINE_MODE %}
|
{% if config.OFFLINE_MODE %}
|
||||||
|
|||||||
11
puppetboard/templates/static/Semantic-UI-2.1.8/semantic.min.css
vendored
Normal file
11
puppetboard/templates/static/Semantic-UI-2.1.8/semantic.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
24
puppetboard/templates/static/css/google_fonts.css
Normal file
24
puppetboard/templates/static/css/google_fonts.css
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
@font-face {
|
||||||
|
font-family: 'Lato';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
src: local('Lato Regular'), local('Lato-Regular'), url({{ url_for('static', filename='fonts/lato-normal-400.ttf') }}) format('truetype');
|
||||||
|
}
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Lato';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 700;
|
||||||
|
src: local('Lato Bold'), local('Lato-Bold'), url({{ url_for('static', filename='fonts/lato-normal-700.ttf') }}) format('truetype');
|
||||||
|
}
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Lato';
|
||||||
|
font-style: italic;
|
||||||
|
font-weight: 400;
|
||||||
|
src: local('Lato Italic'), local('Lato-Italic'), url({{ url_for('static', filename='fonts/lato-italic-400.ttf') }}) format('truetype');
|
||||||
|
}
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Lato';
|
||||||
|
font-style: italic;
|
||||||
|
font-weight: 700;
|
||||||
|
src: local('Lato Bold Italic'), local('Lato-BoldItalic'), url({{ url_for('static', filename='fonts/lato-italic-700.ttf') }}) format('truetype');
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import os.path
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
@@ -9,6 +10,7 @@ from requests.exceptions import HTTPError, ConnectionError
|
|||||||
from pypuppetdb.errors import EmptyResponseError
|
from pypuppetdb.errors import EmptyResponseError
|
||||||
|
|
||||||
from flask import abort, request, url_for
|
from flask import abort, request, url_for
|
||||||
|
from jinja2.utils import contextfunction
|
||||||
|
|
||||||
# Python 3 compatibility
|
# Python 3 compatibility
|
||||||
try:
|
try:
|
||||||
@@ -19,6 +21,14 @@ except NameError:
|
|||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@contextfunction
|
||||||
|
def url_static_offline(context, value):
|
||||||
|
request_parts = os.path.split(os.path.dirname(context.name))
|
||||||
|
static_path = '/'.join(request_parts[1:])
|
||||||
|
|
||||||
|
return url_for('static', filename="%s/%s" % (static_path, value))
|
||||||
|
|
||||||
|
|
||||||
def url_for_field(field, value):
|
def url_for_field(field, value):
|
||||||
args = request.view_args.copy()
|
args = request.view_args.copy()
|
||||||
args.update(request.args.copy())
|
args.update(request.args.copy())
|
||||||
|
|||||||
@@ -266,6 +266,9 @@ def test_offline_mode(client, mocker):
|
|||||||
assert soup.title.contents[0] == 'Puppetboard'
|
assert soup.title.contents[0] == 'Puppetboard'
|
||||||
for link in soup.find_all('link'):
|
for link in soup.find_all('link'):
|
||||||
assert "//" not in link['href']
|
assert "//" not in link['href']
|
||||||
|
if 'offline' in link['href']:
|
||||||
|
static_rv = client.get(link['href'])
|
||||||
|
assert rv.status_code == 200
|
||||||
|
|
||||||
for script in soup.find_all('script'):
|
for script in soup.find_all('script'):
|
||||||
if "src" in script.attrs:
|
if "src" in script.attrs:
|
||||||
@@ -821,3 +824,16 @@ def test_node_facts_json(client, mocker,
|
|||||||
assert len(line) == 2
|
assert len(line) == 2
|
||||||
|
|
||||||
assert 'chart' not in result_json
|
assert 'chart' not in result_json
|
||||||
|
|
||||||
|
|
||||||
|
def test_offline_static(client):
|
||||||
|
rv = client.get('/offline/css/google_fonts.css')
|
||||||
|
|
||||||
|
assert 'Content-Type' in rv.headers
|
||||||
|
assert 'text/css' in rv.headers['Content-Type']
|
||||||
|
assert rv.status_code == 200
|
||||||
|
|
||||||
|
rv = client.get('/offline/Semantic-UI-2.1.8/semantic.min.css')
|
||||||
|
assert 'Content-Type' in rv.headers
|
||||||
|
assert 'text/css' in rv.headers['Content-Type']
|
||||||
|
assert rv.status_code == 200
|
||||||
|
|||||||
Reference in New Issue
Block a user