Skip to content
Snippets Groups Projects
Commit 79569ac6 authored by Alice Heaton's avatar Alice Heaton :speech_balloon:
Browse files

Merge branch 'assets' into text_and_table_widgets

parents db417a77 9460c268
No related branches found
No related tags found
No related merge requests found
Showing
with 713 additions and 68 deletions
......@@ -49,10 +49,15 @@ django-tables2==1.0.4
#django-debug-toolbar
## ---------CSS and assets
#django-assets
# django-assets==0.10
# We need the version of django_assets that contains the following fix:
# https://github.com/miracle2k/django-assets/issues/52
git+git://github.com/miracle2k/django-assets.git@97005b92d092827cfebe798e48e00dba25f83597
#webassets
#pyScss
#cssmin
cssmin==0.2.0
jsmin==2.1.2
django-bootstrap3
# vi: filetype=conf
......@@ -3,12 +3,6 @@
{% load bootstrap3 %}
{% load render_widget %}
{% block bootstrap3_extra_head %}
{% for stylesheet in css %}
<link href='{{STATIC_URL}}{{stylesheet}}' rel='stylesheet' />
{% endfor %}
{% endblock %}
{% block maincontent %}
<h1 class="page-header"><span class="fa fa-dashboard fa-fw"></span>{% trans "Dashboard" %}</h1>
{# Actual widgets #}
......@@ -155,9 +149,3 @@
</div>
{% endblock maincontent %}
{% block lastjs %}
{{ block.super }}
{% for library in javascript %}
<script src='{{STATIC_URL}}{{ library }}'></script>
{% endfor %}
{% endblock %}
from mock import patch
from django.test import TestCase
from dashboard.models import Dashboard
from dashboard.views import DashboardView
from dashboard.widget_pool import register_widget
from hid.assets import use_assets
class TestWidget(object):
......@@ -62,16 +65,15 @@ class TestDashboardView(TestCase):
dashboard_view = DashboardView()
view_args = {'name': 'dashboard1'}
dashboard_view.kwargs = view_args
return dashboard_view.get_context_data(**view_args)
def test_remove_duplicates(self):
""" Ensure duplicates are removed and the order is kept"""
dashboard_view = DashboardView()
test_array = [1, 2, 5, 1, 3, 2, 5, 3, 1, 4]
self.assertEqual(
dashboard_view._remove_duplicates(test_array),
[1, 2, 5, 3, 4]
)
assets = [
'file.js', 'app/file.js', 'file.css',
'app/file.css', 'some.js', 'app2/file.js',
'some.css', 'app2/file.css',
'dashboard/dashboard.css'
]
with use_assets(*assets):
context_data = dashboard_view.get_context_data(**view_args)
return context_data
def test_context_data_includes_dashboard_name(self):
self.setup_dashboard('dashboard1')
......@@ -142,7 +144,7 @@ class TestDashboardView(TestCase):
['test-widget-4', 'test-widget-2']
])
def test_context_data_includes_javascript(self):
def test_context_data_requires_assets(self):
self.setup_dashboard('dashboard1', [
{
'widget_type': 'test-widget-1',
......@@ -155,28 +157,15 @@ class TestDashboardView(TestCase):
'column': 1
}
])
context = self.get_dashboard_view_context('dashboard1')
self.assertEqual(context['javascript'], [
required_assets = []
with patch('dashboard.views.require_assets') as mock:
self.get_dashboard_view_context('dashboard1')
for call_args in mock.call_args_list:
required_assets += call_args[0]
self.assertEqual(set([
'file.js', 'app/file.js',
'some.js', 'app2/file.js'
])
def test_context_data_includes_css(self):
self.setup_dashboard('dashboard1', [
{
'widget_type': 'test-widget-1',
'row': 0,
'column': 0
},
{
'widget_type': 'test-widget-2',
'row': 0,
'column': 1
}
])
context = self.get_dashboard_view_context('dashboard1')
self.assertEqual(context['css'], [
'dashboard/dashboard.css',
'some.js', 'app2/file.js',
'file.css', 'app/file.css',
'some.css', 'app2/file.css'
])
'some.css', 'app2/file.css',
'dashboard/dashboard.css'
]), set(required_assets))
from django.views.generic import TemplateView
from hid.assets import require_assets
from dashboard.models import Dashboard
from dashboard.widget_pool import get_widget
......@@ -38,25 +40,14 @@ class DashboardView(TemplateView):
if len(current_row) > 0:
context['rows'].append(current_row)
# Get all the javascript & css dependencies
context['javascript'] = []
context['css'] = ['dashboard/dashboard.css']
# Ensure we have all the javascript & css dependencies
require_assets('dashboard/dashboard.css')
for widget in widgets:
widget_type = get_widget(widget.widget_type)
if hasattr(widget_type, 'javascript'):
context['javascript'] += widget_type.javascript
require_assets(*widget_type.javascript)
if hasattr(widget_type, 'css'):
context['css'] += widget_type.css
context['javascript'] = self._remove_duplicates(context['javascript'])
context['css'] = self._remove_duplicates(context['css'])
require_assets(*widget_type.css)
# Return the context
return context
def _remove_duplicates(self, the_list):
""" Remove duplicates whilst preseving order """
out = []
for e in the_list:
if e not in out:
out.append(e)
return out
""" Handle the assets for the project so we can compile all
javascript and css in a single file, which is the optimum
way of building the resources for high latency and low
bandwidth setups.
The list of assets is not dynamic - to be build for production
the list of assets in _assets must be defined in this file.
Asset type is determined by file extension:
.js: Javascript file
.css: Css file
.less: Less file
To ensure dependencies are included, and to clearly express
which components require certain css or javascript files,
views may call 'require_assets' which will raise an
AssetMissing exception if the given asset is not included
statically here.
"""
from contextlib import contextmanager
from django_assets import Bundle, register
_assets = [
# Stylesheets
'fonts/font-awesome-4.3.0/css/font-awesome.css',
'less/internews-bootstrap.less',
'dashboard/dashboard.css',
# Javascript librairies
'js/jquery.min.js',
'bootstrap/js/bootstrap.min.js',
'js/underscore.js',
'js/backbone.js',
'flot/jquery.flot.js',
'flot/jquery.flot.resize.js',
'hid/widgets/chart.js'
]
class AssetMissing(Exception):
""" Exception raised when an asset is missing """
pass
def require_assets(*assets):
""" Ensure the given assets are included in the page's assets
Args:
assets: List of assets
Raises:
AssetMissing: If any of the asset is missing
"""
global _assets
for asset in assets:
if asset not in _assets:
raise AssetMissing("Missing asset: {}".format(asset))
@contextmanager
def use_assets(*assets):
""" Context manager to temporarily override the asset list.
This is used for testing purposes only - assets not defined
statically here will not be included in production
environment.
"""
global _assets
old_assets = _assets
try:
_assets = assets
yield
finally:
_assets = old_assets
register('javascript_assets', Bundle(
*[a for a in _assets if a.endswith('.js')],
filters='jsmin', output='js/javascript_assets.js'
))
register('css_assets', Bundle(
*[a for a in _assets if a.endswith('.css') or a.endswith('.less')],
filters='less, cssmin', output='css/css_assets.css',
depends=['less/*.less']
))
from django.test import TestCase
from hid.assets import require_assets, use_assets, AssetMissing
class TestAssets(TestCase):
def test_requiring_existing_assets_does_not_raise(self):
with use_assets('a.css', 'b.css', 'c.js'):
try:
require_assets('a.css', 'c.js')
except AssetMissing:
raise
self.fail('AssetMissing raised unexpectedly')
def test_requiring_missing_assets_does_raise(self):
with use_assets('a.css', 'b.css', 'c.js'):
with self.assertRaises(AssetMissing):
require_assets('a.css', 'missing.js')
File added
File added
Source diff could not be displayed: it is too large. Options to address this: view the blob.
File added
File added
File added
......@@ -106,6 +106,7 @@ STATICFILES_DIRS = (
STATICFILES_FINDERS = (
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
'django_assets.finders.AssetsFinder'
)
########## END STATIC FILE CONFIGURATION
......@@ -134,7 +135,8 @@ THIRD_PARTY_APPS = (
'bootstrap3',
'rest_framework',
'django_tables2',
'djangojs'
'djangojs',
'django_assets'
)
LOCAL_APPS = (
......
<!doctype html>
{% load assets %}
{% load bootstrap3 %}
{% load i18n %}
<html>
......@@ -16,8 +17,9 @@
<script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
<![endif]-->
{% block bootstrap3_extra_head %}{% endblock %}
<link href="{{ STATIC_URL }}css/styles.css" media="all" rel="stylesheet" />
<link href="{{ STATIC_URL }}fonts/font-awesome-4.3.0/css/font-awesome.min.css" media="all" rel="stylesheet" />
{% assets "css_assets" %}
<link href="{{ ASSET_URL }}" medial="all" rel="stylesheet" />
{% endassets %}
<link rel="shortcut icon" href="{{STATIC_URL}}images/favicon.ico?v=1"/>
</head>
......@@ -37,9 +39,9 @@
{% endblock content %}
{% block bootstrap3_extra_js %}
{% bootstrap_javascript jquery=True %}
<script src="{{ STATIC_URL }}js/underscore.js"></script>
<script src="{{ STATIC_URL }}js/backbone.js"></script>
{% assets "javascript_assets" %}
<script type="text/javascript" src="{{ ASSET_URL }}"></script>
{% endassets %}
{% endblock %}
{% block lastjs %}
{% endblock %}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment