From b285358a96d950ab6817bf94547129567152faf3 Mon Sep 17 00:00:00 2001 From: Rob Cresswell Date: Wed, 5 Aug 2015 19:00:00 +0100 Subject: [PATCH] Add Developer Dashboard + Bootstrap Theme Preview Themers need an easy way to see how customizations in the new themeing mechanism will affect known bootstrap elements. While DEBUG is True, the developer dashboard will be present in the Horizon nav sidebar. This currently displays the Bootstrap Theme Preview page, and will also be used for Angular widget demos etc in the future. Documentation on SCSS and the preview page are being provided in a separate patch to coordinate with the theming work (https://bugs.launchpad.net/horizon/+bug/1514869) Note: The SECRET_KEY block in settings.py is moved before the enabled files setup, so that importing settings in the enabled file doesn't cause errors. Co-Authored-By: Diana Whitten Implements: blueprint bootstrap-theme-preview Change-Id: I44bc52d4dcfbbdc60a27879e638d78c4b508b2e9 --- .../contrib/developer/__init__.py | 0 .../contrib/developer/dashboard.py | 26 + .../dashboard/developer/developer.module.js | 45 + .../developer/developer.module.spec.js | 42 + .../static/dashboard/developer/developer.scss | 2 + .../theme-preview/theme-preview.directive.js | 101 ++ .../theme-preview/theme-preview.html | 1157 +++++++++++++++++ .../theme-preview/theme-preview.module.js | 28 + .../theme-preview.module.spec.js | 25 + .../theme-preview/theme-preview.scss | 53 + .../contrib/developer/tests.py | 27 + .../developer/theme_preview/__init__.py | 0 .../contrib/developer/theme_preview/panel.py | 22 + .../templates/theme_preview/index.html | 14 + .../contrib/developer/theme_preview/tests.py | 45 + .../contrib/developer/theme_preview/urls.py | 24 + .../contrib/developer/theme_preview/views.py | 34 + .../enabled/_9001_developer.py | 36 + openstack_dashboard/enabled/_9010_preview.py | 21 + openstack_dashboard/settings.py | 24 +- openstack_dashboard/test/settings.py | 2 + ...tstrap-theme-preview-65da171c9b943646.yaml | 8 + 22 files changed, 1724 insertions(+), 12 deletions(-) create mode 100644 openstack_dashboard/contrib/developer/__init__.py create mode 100644 openstack_dashboard/contrib/developer/dashboard.py create mode 100644 openstack_dashboard/contrib/developer/static/dashboard/developer/developer.module.js create mode 100644 openstack_dashboard/contrib/developer/static/dashboard/developer/developer.module.spec.js create mode 100644 openstack_dashboard/contrib/developer/static/dashboard/developer/developer.scss create mode 100644 openstack_dashboard/contrib/developer/static/dashboard/developer/theme-preview/theme-preview.directive.js create mode 100644 openstack_dashboard/contrib/developer/static/dashboard/developer/theme-preview/theme-preview.html create mode 100644 openstack_dashboard/contrib/developer/static/dashboard/developer/theme-preview/theme-preview.module.js create mode 100644 openstack_dashboard/contrib/developer/static/dashboard/developer/theme-preview/theme-preview.module.spec.js create mode 100644 openstack_dashboard/contrib/developer/static/dashboard/developer/theme-preview/theme-preview.scss create mode 100644 openstack_dashboard/contrib/developer/tests.py create mode 100644 openstack_dashboard/contrib/developer/theme_preview/__init__.py create mode 100644 openstack_dashboard/contrib/developer/theme_preview/panel.py create mode 100644 openstack_dashboard/contrib/developer/theme_preview/templates/theme_preview/index.html create mode 100644 openstack_dashboard/contrib/developer/theme_preview/tests.py create mode 100644 openstack_dashboard/contrib/developer/theme_preview/urls.py create mode 100644 openstack_dashboard/contrib/developer/theme_preview/views.py create mode 100644 openstack_dashboard/enabled/_9001_developer.py create mode 100644 openstack_dashboard/enabled/_9010_preview.py create mode 100644 releasenotes/notes/bp-bootstrap-theme-preview-65da171c9b943646.yaml diff --git a/openstack_dashboard/contrib/developer/__init__.py b/openstack_dashboard/contrib/developer/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/openstack_dashboard/contrib/developer/dashboard.py b/openstack_dashboard/contrib/developer/dashboard.py new file mode 100644 index 000000000..bf1219cbc --- /dev/null +++ b/openstack_dashboard/contrib/developer/dashboard.py @@ -0,0 +1,26 @@ +# Copyright 2015 Cisco Systems, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from django.utils.translation import ugettext_lazy as _ + +import horizon + + +class Developer(horizon.Dashboard): + name = _("Developer") + slug = "developer" + default_panel = "theme_preview" + + +horizon.register(Developer) diff --git a/openstack_dashboard/contrib/developer/static/dashboard/developer/developer.module.js b/openstack_dashboard/contrib/developer/static/dashboard/developer/developer.module.js new file mode 100644 index 000000000..70f532874 --- /dev/null +++ b/openstack_dashboard/contrib/developer/static/dashboard/developer/developer.module.js @@ -0,0 +1,45 @@ +/* + * (c) Copyright 2015 Cisco Systems, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +(function () { + 'use strict'; + + /** + * @ngdoc module + * @ngname horizon.dashboard.developer + * @description + * Dashboard module to host developer panels. + */ + angular + .module('horizon.dashboard.developer', [ + 'horizon.dashboard.developer.theme-preview' + ]) + .config(config); + + config.$inject = [ + '$provide', + '$windowProvider' + ]; + + /** + * @name horizon.dashboard.developer.basePath + * @description Base path for the developer dashboard + */ + function config($provide, $windowProvider) { + var path = $windowProvider.$get().STATIC_URL + 'dashboard/developer/'; + $provide.constant('horizon.dashboard.developer.basePath', path); + } +})(); diff --git a/openstack_dashboard/contrib/developer/static/dashboard/developer/developer.module.spec.js b/openstack_dashboard/contrib/developer/static/dashboard/developer/developer.module.spec.js new file mode 100644 index 000000000..b5b9492ac --- /dev/null +++ b/openstack_dashboard/contrib/developer/static/dashboard/developer/developer.module.spec.js @@ -0,0 +1,42 @@ +/* + * (c) Copyright 2015 Cisco Systems, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +(function () { + 'use strict'; + + describe('horizon.dashboard.developer', function () { + it('should be defined', function () { + expect(angular.module('horizon.dashboard.developer')).toBeDefined(); + }); + }); + + describe('horizon.dashboard.developer.basePath constant', function () { + var developerBasePath, staticUrl; + + beforeEach(module('horizon.dashboard.developer')); + beforeEach(inject(function ($injector) { + developerBasePath = $injector.get('horizon.dashboard.developer.basePath'); + staticUrl = $injector.get('$window').STATIC_URL; + })); + + it('should be defined', function () { + expect(developerBasePath).toBeDefined(); + }); + + it('should equal to "/static/dashboard/developer/"', function () { + expect(developerBasePath).toEqual(staticUrl + 'dashboard/developer/'); + }); + }); +})(); diff --git a/openstack_dashboard/contrib/developer/static/dashboard/developer/developer.scss b/openstack_dashboard/contrib/developer/static/dashboard/developer/developer.scss new file mode 100644 index 000000000..4ad9a92e7 --- /dev/null +++ b/openstack_dashboard/contrib/developer/static/dashboard/developer/developer.scss @@ -0,0 +1,2 @@ +// Top level file for Developer dashboard SCSS +@import "theme-preview/theme-preview"; diff --git a/openstack_dashboard/contrib/developer/static/dashboard/developer/theme-preview/theme-preview.directive.js b/openstack_dashboard/contrib/developer/static/dashboard/developer/theme-preview/theme-preview.directive.js new file mode 100644 index 000000000..926da4afb --- /dev/null +++ b/openstack_dashboard/contrib/developer/static/dashboard/developer/theme-preview/theme-preview.directive.js @@ -0,0 +1,101 @@ +/* + * (c) Copyright 2015 Cisco Systems, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +(function() { + 'use strict'; + + angular + .module('horizon.dashboard.developer.theme-preview') + .directive('themepreview', themePreview); + + themePreview.$inject = ['horizon.dashboard.developer.basePath']; + + /** + * @ngdoc directive + * @name themepreview + * @description + * Wraps the JS code for displaying the theme preview page. Shouldnt be used elsewhere. + */ + + function themePreview(path) { + var directive = { + restrict: 'E', + templateUrl: path + 'theme-preview/theme-preview.html', + link: link + }; + + return directive; + } + + function link(scope, element) { + + //TODO(tqtran) Use angular, not jquery + $('a[href="#"]').click(function(e) { + e.preventDefault(); + }); + + var $modal = $('#source-modal'); + var $pre = $modal.find('pre'); + + var $button = $('
') + .click(function(){ + var $fragment = stripAngular($(this).parent().clone()); + var html = cleanSource($fragment.html()); + $pre.text(html); + $modal.modal(); + }); + + var $component = $('.bs-component'); + $component.find('[data-toggle="popover"]').popover(); + $component.find('[data-toggle="tooltip"]').tooltip(); + + $component.hover(function() { + $(this).append($button); + $button.show(); + }); + } + + // Utility function to clean up the source code before displaying + function stripAngular($frag) { + var $translated = $frag.find('[translate]') + .removeAttr('translate'); + $translated.html($translated.find('> span').html()); + $frag.find('.ng-scope').removeClass('ng-scope'); + $frag.find('.ng-pristine').removeClass('ng-pristine'); + $frag.find('.ng-valid').removeClass('ng-valid'); + $frag.find('input').removeAttr('style'); + return $frag; + } + + // Utility function to clean up the source code before displaying + function cleanSource(html) { + var lines = html.split(/\n/); + lines.shift(); + lines.splice(-1, 1); + var indentSize = lines[0].length - lines[0].trim().length; + var re = new RegExp(' {' + indentSize + '}'); + lines = lines.map(function(line) { + if (line.match(re)) { + line = line.substring(indentSize); + } + return line; + }); + lines = lines.join('\n'); + + return lines; + } +})(); + diff --git a/openstack_dashboard/contrib/developer/static/dashboard/developer/theme-preview/theme-preview.html b/openstack_dashboard/contrib/developer/static/dashboard/developer/theme-preview/theme-preview.html new file mode 100644 index 000000000..8523acde4 --- /dev/null +++ b/openstack_dashboard/contrib/developer/static/dashboard/developer/theme-preview/theme-preview.html @@ -0,0 +1,1157 @@ +

+ To view source code, hover over a section, then click the button in the top right of that section. +

+ + + + +
+
+
+ + +
+ +
+ +
+ +
+
+
+
+ + +
+ + +
+
+

+ + + + + + + +

+ +

+ + + + + + + +

+ +
+
+ + + + + + + + + +
+
+ +

+ + + + +

+
+
+ +

+ +

+ +
+
+ Left + Middle + Right +
+
+ +
+
+
+ + + + +
+ +
+ + + +
+ +
+ +
+ + +
+
+
+
+ +
+
+ + + + +
+
+
+
+
+ + +
+
+
+ +
+
+ + + +
+
+
+

Heading 1

+

Heading 2

+

Heading 3

+

Heading 4

+
Heading 5
+
Heading 6
+

Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor.

+
+
+
+
+

Example body text

+

Maecenas faucibus mollis interdum. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus.

+

This line of text is meant to be treated as fine print.

+

The following snippet of text is rendered as bold text.

+

The following snippet of text is rendered as italicized text.

+

An abbreviation of the word attribute is attr.

+
+ +
+
+
+

Emphasis classes

+

Fusce dapibus, tellus ac cursus commodo, tortor mauris nibh.

+

Nullam id dolor id nibh ultricies vehicula ut id elit.

+

Etiam porta sem malesuada magna mollis euismod.

+

Donec ullamcorper nulla non metus auctor fringilla.

+

Duis mollis, est non commodo luctus, nisi erat porttitor ligula.

+

Maecenas sed diam eget risus varius blandit sit amet non magna.

+
+ +
+
+ + + +
+
+

Blockquotes

+
+
+
+
+
+
+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.

+ Someone famous in Source Title +
+
+
+
+
+
+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.

+ Someone famous in Source Title +
+
+
+
+
+ + +
+
+
+ + +

Standard Table

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#Column headingColumn headingColumn heading
1Column contentColumn contentColumn content
2Column contentColumn contentColumn content
3Column contentColumn contentColumn content
4Column contentColumn contentColumn content
5Column contentColumn contentColumn content
6Column contentColumn contentColumn content
7Column contentColumn contentColumn content
+
+ +

Bordered Table

+
+ + + + + + + + + + + + + + + + + + + + + + + +
#Column headingColumn headingColumn heading
1Column contentColumn contentColumn content
2Column contentColumn contentColumn content
+
+
+
+
+ + +
+
+
+ +
+
+ +
+
+
+
+
+ Legend +
+ +
+ +
+
+
+ +
+ +
+ +
+
+
+
+ +
+ + A longer block of help text that breaks onto a new line and may extend beyond one line. +
+
+
+ +
+
+ +
+
+ +
+
+
+
+ +
+ +
+ +
+
+
+
+ + +
+
+
+
+
+
+
+ +
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ +
+ $ + + + + +
+
+
+
+
+
+ + +
+
+
+ +
+
+ +
+
+ +
+ +
+
+

Donec ullamcorper nulla non metus auctor fringilla. Cras mattis consectetur purus sit amet fermentum. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Nullam id dolor id nibh ultricies vehicula ut id elit. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum.

+
+
+

Curabitur blandit tempus porttitor. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Maecenas faucibus mollis interdum. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Sed posuere consectetur est at lobortis.

+
+ + +
+
+
+ +
+ +
+ + + + + +
+
+
+ +
+
+

Pagination

+
+ + + + + +
+
+
+

Pager

+
+ + + +
+
+
+ +
+
+
+ + +
+
+
+ +
+
+ +
+
+

Alerts

+
+
+ +

Warning!

+

Somethings not quite right. Maecenas sed diam eget risus varius blandit sit amet non magna!

+
+
+
+
+
+
+
+
+ + Oh snap! + Change a few things up + and try submitting again. +
+
+
+
+
+
+ + Well done! + You successfully read + this important alert message. +
+
+
+
+
+
+ + Heads up! + This + alert needs your attention, + but it's not super important. +
+
+
+
+
+
+

Labels

+
+ Default + Primary + Success + Warning + Danger + Info +
+
+
+

Badges

+ +
+
+
+ + +
+ +
+
+ + +

Basic

+
+
+
+
+
+ +

Contextual alternatives

+
+
+
+
+ +
+
+
+ +
+
+
+ +
+
+
+
+ +

Striped

+
+
+
+
+ +
+
+
+ +
+
+
+ +
+
+
+
+ +

Animated

+
+
+
+
+
+ +

Stacked

+
+
+
+
+
+
+
+
+
+
+ + +
+ +
+
+ +
+
+

Jumbotron

+

This is a simple hero unit, a simple jumbotron-style component for calling extra attention to featured content or information.

+

Learn more

+
+
+
+
+ + +
+
+

List groups

+
+
+ + + +
+
+

Panels

+
+
+
+
+
+
+
Basic panel
+
+ +
+
Panel heading
+
Panel content
+
+ +
+
Panel content
+ +
+
+
+
+
+
+
+

Panel primary

+
+
Panel content
+
+ +
+
+

Panel success

+
+
Panel content
+
+ +
+
+

Panel warning

+
+
Panel content
+
+
+
+
+
+
+
+

Panel danger

+
+
Panel content
+
+ +
+
+

Panel info

+
+
Panel content
+
+
+
+
+ +
+
+

Wells

+
+
+
+
+
+
+ Look, I'm in a well! +
+
+
+
+
+
+ Look, I'm in a small well! +
+
+
+
+
+
+ Look, I'm in a large well! +
+
+
+
+
+ + +
+ +
+
+ +
+
+
+
+

Modals

+
+ +
+
+
+

Popovers

+
+ + + + +
+

Tooltips

+
+ + + + +
+
+
+
+ + diff --git a/openstack_dashboard/contrib/developer/static/dashboard/developer/theme-preview/theme-preview.module.js b/openstack_dashboard/contrib/developer/static/dashboard/developer/theme-preview/theme-preview.module.js new file mode 100644 index 000000000..9bdfd3f10 --- /dev/null +++ b/openstack_dashboard/contrib/developer/static/dashboard/developer/theme-preview/theme-preview.module.js @@ -0,0 +1,28 @@ +/* + * (c) Copyright 2015 Cisco Systems, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +(function () { + 'use strict'; + + /** + * @ngdoc module + * @ngname horizon.dashboard.developer.theme-preview + * @description + * Dashboard module for the bootstrap theme preview panel. + */ + angular + .module('horizon.dashboard.developer.theme-preview', []) +})(); diff --git a/openstack_dashboard/contrib/developer/static/dashboard/developer/theme-preview/theme-preview.module.spec.js b/openstack_dashboard/contrib/developer/static/dashboard/developer/theme-preview/theme-preview.module.spec.js new file mode 100644 index 000000000..5669f8e76 --- /dev/null +++ b/openstack_dashboard/contrib/developer/static/dashboard/developer/theme-preview/theme-preview.module.spec.js @@ -0,0 +1,25 @@ +/* + * (c) Copyright 2015 Cisco Systems, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +(function () { + 'use strict'; + + describe('horizon.dashboard.developer.theme-preview', function () { + it('should be defined', function () { + expect(angular.module('horizon.dashboard.developer.theme-preview')).toBeDefined(); + }); + }); + +})(); diff --git a/openstack_dashboard/contrib/developer/static/dashboard/developer/theme-preview/theme-preview.scss b/openstack_dashboard/contrib/developer/static/dashboard/developer/theme-preview/theme-preview.scss new file mode 100644 index 000000000..8da7e38c3 --- /dev/null +++ b/openstack_dashboard/contrib/developer/static/dashboard/developer/theme-preview/theme-preview.scss @@ -0,0 +1,53 @@ +@import "/custom/variables"; + +themepreview { + + #source-button { + font-weight: 700; + position: absolute; + right: 0; + top: 0; + z-index: 100; + } + + .bs-component { + position: relative; + } + + .bs-component .modal-dialog { + width: 90%; + } + + .bs-component .modal { + bottom: auto; + display: block; + left: auto; + position: relative; + right: auto; + top: auto; + z-index: 1; + } + + .bs-component .popover { + display: inline-block; + margin: 20px; + position: relative; + width: 220px; + } + + .left .tooltip-inner { + float: right; + } + + #nav-tabs .nav-tabs { + margin-bottom: 15px; + } + + .nav-pills.nav-pills-stacked { + max-width: 300px; + } + + .navbar { + margin-bottom: $padding-large-horizontal*2; + } +} diff --git a/openstack_dashboard/contrib/developer/tests.py b/openstack_dashboard/contrib/developer/tests.py new file mode 100644 index 000000000..a6b73f601 --- /dev/null +++ b/openstack_dashboard/contrib/developer/tests.py @@ -0,0 +1,27 @@ +# Copyright 2015 Cisco Systems, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + + +import horizon +from horizon import base + +from openstack_dashboard.test import helpers as test + + +class DeveloperTests(test.TestCase): + + # Tests are run with DEBUG=False, so check that dashboard isn't registered + def test_registration_failure(self): + with self.assertRaises(base.NotRegistered): + horizon.get_dashboard("developer") diff --git a/openstack_dashboard/contrib/developer/theme_preview/__init__.py b/openstack_dashboard/contrib/developer/theme_preview/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/openstack_dashboard/contrib/developer/theme_preview/panel.py b/openstack_dashboard/contrib/developer/theme_preview/panel.py new file mode 100644 index 000000000..5c34fe0cc --- /dev/null +++ b/openstack_dashboard/contrib/developer/theme_preview/panel.py @@ -0,0 +1,22 @@ +# Copyright 2015 Cisco Systems, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from django.utils.translation import ugettext_lazy as _ + +import horizon + + +class Preview(horizon.Panel): + name = _("Bootstrap Theme Preview") + slug = 'theme_preview' diff --git a/openstack_dashboard/contrib/developer/theme_preview/templates/theme_preview/index.html b/openstack_dashboard/contrib/developer/theme_preview/templates/theme_preview/index.html new file mode 100644 index 000000000..c9580cd1a --- /dev/null +++ b/openstack_dashboard/contrib/developer/theme_preview/templates/theme_preview/index.html @@ -0,0 +1,14 @@ +{% extends 'base.html' %} +{% load i18n %} + +{% block title %} + {% trans "Theme Preview" %} +{% endblock %} + +{% block page_header %} +

{{ skin }} {{ skin_desc }}

+{% endblock %} + +{% block main %} + +{% endblock %} diff --git a/openstack_dashboard/contrib/developer/theme_preview/tests.py b/openstack_dashboard/contrib/developer/theme_preview/tests.py new file mode 100644 index 000000000..009f4c709 --- /dev/null +++ b/openstack_dashboard/contrib/developer/theme_preview/tests.py @@ -0,0 +1,45 @@ +# Copyright 2015 Cisco Systems, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + + +from django.conf import settings +from django.core import urlresolvers +from django.core.urlresolvers import reverse +from django.utils.importlib import import_module # noqa + +from horizon import base + +from openstack_dashboard.contrib.developer.dashboard import Developer +from openstack_dashboard.test import helpers as test + + +class ThemePreviewTests(test.TestCase): + + # Manually register Developer Dashboard, as DEBUG=False in tests + def setUp(self): + super(ThemePreviewTests, self).setUp() + urlresolvers.clear_url_caches() + reload(import_module(settings.ROOT_URLCONF)) + base.Horizon.register(Developer) + base.Horizon._urls() + + def tearDown(self): + super(ThemePreviewTests, self).tearDown() + base.Horizon.unregister(Developer) + base.Horizon._urls() + + def test_index(self): + index = reverse('horizon:developer:theme_preview:index') + res = self.client.get(index) + self.assertTemplateUsed(res, 'developer/theme_preview/index.html') diff --git a/openstack_dashboard/contrib/developer/theme_preview/urls.py b/openstack_dashboard/contrib/developer/theme_preview/urls.py new file mode 100644 index 000000000..dd89ec595 --- /dev/null +++ b/openstack_dashboard/contrib/developer/theme_preview/urls.py @@ -0,0 +1,24 @@ +# Copyright 2015 Cisco Systems, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from django.conf.urls import patterns +from django.conf.urls import url + +from openstack_dashboard.contrib.developer.theme_preview import views + + +urlpatterns = patterns( + 'openstack_dashboard.contrib.developer.theme_preview.views', + url(r'^$', views.IndexView.as_view(), name='index'), +) diff --git a/openstack_dashboard/contrib/developer/theme_preview/views.py b/openstack_dashboard/contrib/developer/theme_preview/views.py new file mode 100644 index 000000000..405ae9092 --- /dev/null +++ b/openstack_dashboard/contrib/developer/theme_preview/views.py @@ -0,0 +1,34 @@ +# Copyright 2015 Cisco Systems, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import logging + +from django.conf import settings +from django.utils.translation import ugettext_lazy as _ + +from horizon import views + +LOG = logging.getLogger(__name__) + + +class IndexView(views.HorizonTemplateView): + template_name = 'developer/theme_preview/index.html' + page_title = _("Bootstrap Theme Preview") + + def get_context_data(self, **kwargs): + theme_path = settings.CUSTOM_THEME_PATH + context = super(IndexView, self).get_context_data(**kwargs) + context['skin'] = theme_path.split('/')[-1] + context['skin_desc'] = theme_path + return context diff --git a/openstack_dashboard/enabled/_9001_developer.py b/openstack_dashboard/enabled/_9001_developer.py new file mode 100644 index 000000000..2484392bd --- /dev/null +++ b/openstack_dashboard/enabled/_9001_developer.py @@ -0,0 +1,36 @@ +# Copyright 2015 Cisco Systems, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from django.conf import settings + +DASHBOARD = 'developer' + +ADD_ANGULAR_MODULES = [ + 'horizon.dashboard.developer' +] + +ADD_INSTALLED_APPS = [ + 'openstack_dashboard.contrib.developer' +] + +ADD_SCSS_FILES = [ + 'dashboard/developer/developer.scss', +] + +AUTO_DISCOVER_STATIC_FILES = True + +DISABLED = True + +if getattr(settings, 'DEBUG', False): + DISABLED = False diff --git a/openstack_dashboard/enabled/_9010_preview.py b/openstack_dashboard/enabled/_9010_preview.py new file mode 100644 index 000000000..5d5bff1f2 --- /dev/null +++ b/openstack_dashboard/enabled/_9010_preview.py @@ -0,0 +1,21 @@ +# Copyright 2015 Cisco Systems, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +PANEL = 'theme_preview' +PANEL_GROUP = 'default' +PANEL_DASHBOARD = 'developer' + +ADD_PANEL = \ + 'openstack_dashboard.contrib.developer.theme_preview.panel.Preview' diff --git a/openstack_dashboard/settings.py b/openstack_dashboard/settings.py index a87729055..7126d8d9f 100644 --- a/openstack_dashboard/settings.py +++ b/openstack_dashboard/settings.py @@ -327,6 +327,18 @@ if os.path.exists(os.path.join(CUSTOM_THEME, 'img')): # specs files and external templates. find_static_files(HORIZON_CONFIG) +# Ensure that we always have a SECRET_KEY set, even when no local_settings.py +# file is present. See local_settings.py.example for full documentation on the +# horizon.utils.secret_key module and its use. +if not SECRET_KEY: + if not LOCAL_PATH: + LOCAL_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), + 'local') + + from horizon.utils import secret_key + SECRET_KEY = secret_key.generate_or_read_from_file(os.path.join(LOCAL_PATH, + '.secret_key_store')) + # Load the pluggable dashboard settings import openstack_dashboard.enabled import openstack_dashboard.local.enabled @@ -343,18 +355,6 @@ settings.update_dashboards( ) INSTALLED_APPS[0:0] = ADD_INSTALLED_APPS -# Ensure that we always have a SECRET_KEY set, even when no local_settings.py -# file is present. See local_settings.py.example for full documentation on the -# horizon.utils.secret_key module and its use. -if not SECRET_KEY: - if not LOCAL_PATH: - LOCAL_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), - 'local') - - from horizon.utils import secret_key - SECRET_KEY = secret_key.generate_or_read_from_file(os.path.join(LOCAL_PATH, - '.secret_key_store')) - from openstack_auth import policy POLICY_CHECK_FUNCTION = policy.check diff --git a/openstack_dashboard/test/settings.py b/openstack_dashboard/test/settings.py index c20b30514..ceee26935 100644 --- a/openstack_dashboard/test/settings.py +++ b/openstack_dashboard/test/settings.py @@ -35,6 +35,8 @@ TEMPLATE_DIRS = ( os.path.join(TEST_DIR, 'templates'), ) +CUSTOM_THEME_PATH = 'themes/default' + TEMPLATE_CONTEXT_PROCESSORS += ( 'openstack_dashboard.context_processors.openstack', ) diff --git a/releasenotes/notes/bp-bootstrap-theme-preview-65da171c9b943646.yaml b/releasenotes/notes/bp-bootstrap-theme-preview-65da171c9b943646.yaml new file mode 100644 index 000000000..ac5b91546 --- /dev/null +++ b/releasenotes/notes/bp-bootstrap-theme-preview-65da171c9b943646.yaml @@ -0,0 +1,8 @@ +--- +features: + - Added the Developer dashboard plugin to contrib. This runs when + ``DEBUG=True``, and adds tooling to the UI to aid in development. + - Added the Bootstrap Theme Preview panel to the Developer dashboard. This + panel contains a list of Bootstrap components with source code, so that + developers can see examples of how to structure this code and the + effects their theme will have upon it.