diff --git a/HACKING.themes.md b/HACKING.themes.md index 8239f91..0a097c2 100644 --- a/HACKING.themes.md +++ b/HACKING.themes.md @@ -3,6 +3,7 @@ Noosfero Instructions for Theme Developers To build Noosfero themes you must to know HTML and CSS. You may also get some advantages with Ruby and Noosfero hacking knowledge because all customizable pieces of the theme's HTML structure are [erb](http://en.wikipedia.org/wiki/ERuby) files. + Organization Basics ------------------- @@ -29,6 +30,7 @@ You can add more files like javascript and modularized CSS, but you must to refe To refer one of this files trough the web the path is `/designs/themes//`. + theme.yml --------- @@ -46,3 +48,13 @@ About non obvious: * `icon_theme` point to something inside `public/designs/icons/`. * `gravatar` set the default gravatar *(avatar picture)* for people without picture. + +Theme Intervention from Environment Theme +----------------------------------------- + +Sometimes an environment (as instace http://cirandas.net) wants to allow profiles to set its own theme, but with some environment identification or functions, like a top bar with the social network logo and a top menu (as instace http://cirandas.net/rango-vegan). +To make the magic happens you can add some files to the environment theme. +All are optional: +* `global.css` — this must be used to style all extra html added by your intervention partials. As it is a free form css file you can style anything, but this is a conflict risk. +* `global_header.html.erb` — Will add content to `#global-header`. +* `global_footer.html.erb` — Will add content to `#global-footer`. diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 37b73b4..571d3f9 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -398,19 +398,27 @@ module ApplicationHelper end end - def theme_view_file(template) + def theme_view_file(template, theme=nil) # Since we cannot control what people are doing in external themes, we # will keep looking for the deprecated .rhtml extension here. - file = Rails.root.join('public', theme_path[1..-1], template + '.html.erb') + addr = theme ? "designs/themes/#{theme}" : theme_path[1..-1] + file = Rails.root.join('public', addr, template + '.html.erb') return file if File.exists?(file) nil end def theme_include(template, options = {}) - file = theme_view_file(template) - options.merge!({:file => file, :use_full_path => false}) + from_theme_include(nil, template, options) + end + + def env_theme_include(template, options = {}) + from_theme_include(environment.theme, template, options) + end + + def from_theme_include(theme, template, options = {}) + file = theme_view_file(template, theme) if file - render options + render options.merge(file: file, use_full_path: false) else nil end @@ -446,6 +454,14 @@ module ApplicationHelper @theme_extra_navigation ||= theme_include 'navigation' end + def global_header + @global_header ||= env_theme_include 'global_header' + end + + def global_footer + @global_footer ||= env_theme_include 'global_footer' + end + def is_testing_theme !controller.session[:theme].nil? end diff --git a/app/helpers/layout_helper.rb b/app/helpers/layout_helper.rb index aec2c0b..74b0bcc 100644 --- a/app/helpers/layout_helper.rb +++ b/app/helpers/layout_helper.rb @@ -51,22 +51,30 @@ module LayoutHelper 'chat', pngfix_stylesheet_path, ] + tokeninput_stylesheets - plugins_stylesheets = @plugins.select(&:stylesheet?).map { |plugin| plugin.class.public_path('style.css') } - - output = '' - output += stylesheet_link_tag standard_stylesheets, :cache => 'cache/application' - output += stylesheet_link_tag template_stylesheet_path - output += stylesheet_link_tag icon_theme_stylesheet_path - output += stylesheet_link_tag jquery_ui_theme_stylesheet_path + plugins_stylesheets = @plugins.select(&:stylesheet?).map { |plugin| + plugin.class.public_path('style.css') + } + global_css_pub = "/designs/themes/#{environment.theme}/global.css" + global_css_at_fs = Rails.root.join 'public' + global_css_pub + + output = [] + output << stylesheet_link_tag(standard_stylesheets, :cache => 'cache/application') + output << stylesheet_link_tag(template_stylesheet_path) + output << stylesheet_link_tag(icon_theme_stylesheet_path) + output << stylesheet_link_tag(jquery_ui_theme_stylesheet_path) unless plugins_stylesheets.empty? - output += stylesheet_link_tag plugins_stylesheets, :cache => "cache/plugins-#{Digest::MD5.hexdigest plugins_stylesheets.to_s}" + cacheid = "cache/plugins-#{Digest::MD5.hexdigest plugins_stylesheets.to_s}" + output << stylesheet_link_tag(plugins_stylesheets, :cache => cacheid) end - output += stylesheet_link_tag theme_stylesheet_path - output + if File.exists? global_css_at_fs + output << stylesheet_link_tag(global_css_pub) + end + output << stylesheet_link_tag(theme_stylesheet_path) + output.join "\n" end def pngfix_stylesheet_path - 'iepngfix/iepngfix.css' + 'iepngfix/iepngfix.css' #TODO: deprecate it end def tokeninput_stylesheets diff --git a/app/views/layouts/application-ng.html.erb b/app/views/layouts/application-ng.html.erb index 1d2b91f..a0bbaae 100644 --- a/app/views/layouts/application-ng.html.erb +++ b/app/views/layouts/application-ng.html.erb @@ -22,7 +22,7 @@ end.join("\n") %> - @@ -35,9 +35,12 @@ if content.respond_to?(:call) then instance_exec(&content).to_s.html_safe else content.to_s.html_safe end end.join("\n") %> +
-
+
<%= theme_header %>
@@ -57,9 +60,14 @@
<%= render_environment_features(:logged_in) if logged_in? %> - + <%= noosfero_layout_features %> <%= addthis_javascript %> <%= diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 34b6ce4..d3fffd7 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -52,6 +52,9 @@ registerDocumentSize(); // --> +
<%= _('Go to content') %> @@ -112,8 +115,13 @@
+ + +
<%# if you need to add HTML stuff to the layout, include it in app/views/shared/noosfero_layout_features.html.erb! %> diff --git a/public/stylesheets/application.css b/public/stylesheets/application.css index c01682f..79ea613 100644 --- a/public/stylesheets/application.css +++ b/public/stylesheets/application.css @@ -77,19 +77,6 @@ div#errorExplanation h2 { #footer_content { clear: both; } -#footer { - text-align: center; - clear: both; - font-size: 10px; - color: #777; -} -#footer a { - color: #777; - text-decoration: none; -} -#footer a:hover { - color: #555; -} div#profile-disabled { border: 2px solid #944; text-align: center; diff --git a/test/unit/application_helper_test.rb b/test/unit/application_helper_test.rb index 8ca9cdc..747504d 100644 --- a/test/unit/application_helper_test.rb +++ b/test/unit/application_helper_test.rb @@ -961,6 +961,47 @@ class ApplicationHelperTest < ActionView::TestCase assert_equal '', manage_communities end + should 'include file from current theme out of a profile page' do + def profile; nil; end + def environment; e={}; def e.theme; 'env-theme'; end; e; end + def render(opt); opt; end + File.stubs(:exists?).returns(false) + file = Rails.root.join 'public/designs/themes/env-theme/somefile.html.erb' + assert_nil theme_include('somefile') # exists? = false + File.expects(:exists?).with(file).returns(true).at_least_once + assert_equal file, theme_include('somefile')[:file] # exists? = true + end + + should 'include file from current theme inside a profile page' do + def profile; p={}; def p.theme; 'my-theme'; end; p; end + def render(opt); opt; end + File.stubs(:exists?).returns(false) + file = Rails.root.join 'public/designs/themes/my-theme/otherfile.html.erb' + assert_nil theme_include('otherfile') # exists? = false + File.expects(:exists?).with(file).returns(true).at_least_once + assert_equal file, theme_include('otherfile')[:file] # exists? = true + end + + should 'include file from env theme' do + def profile; p={}; def p.theme; 'my-theme'; end; p; end + def environment; e={}; def e.theme; 'env-theme'; end; e; end + def render(opt); opt; end + File.stubs(:exists?).returns(false) + file = Rails.root.join 'public/designs/themes/env-theme/afile.html.erb' + assert_nil env_theme_include('afile') # exists? = false + File.expects(:exists?).with(file).returns(true).at_least_once + assert_equal file, env_theme_include('afile')[:file] # exists? = true + end + + should 'include file from some theme' do + def render(opt); opt; end + File.stubs(:exists?).returns(false) + file = Rails.root.join 'public/designs/themes/atheme/afile.html.erb' + assert_nil from_theme_include('atheme', 'afile') # exists? = false + File.expects(:exists?).with(file).returns(true).at_least_once + assert_equal file, from_theme_include('atheme', 'afile')[:file] # exists? = true + end + protected include NoosferoTestHelper diff --git a/test/unit/layout_helper_test.rb b/test/unit/layout_helper_test.rb index ccfecde..3e38946 100644 --- a/test/unit/layout_helper_test.rb +++ b/test/unit/layout_helper_test.rb @@ -1,6 +1,7 @@ require_relative "../test_helper" class LayoutHelperTest < ActionView::TestCase + include ApplicationHelper should 'append logged-in class in body when user is logged-in' do expects(:logged_in?).returns(true) @@ -14,4 +15,19 @@ class LayoutHelperTest < ActionView::TestCase assert_not_includes body_classes.split, 'logged-in' end + should 'add global.css to noosfero_stylesheets if env theme has it' do + env = fast_create Environment + env.theme = 'my-theme' + @plugins = [] + expects(:profile).returns(nil).at_least_once + expects(:environment).returns(env).at_least_once + expects(:theme_option).with(:icon_theme).returns(['my-icons']).at_least_once + expects(:jquery_theme).returns('jquery-nice').at_least_once + global_css = Rails.root.join "public/designs/themes/#{env.theme}/global.css" + File.stubs(:exists?).returns(false) + File.expects(:exists?).with(global_css).returns(true).at_least_once + css = noosfero_stylesheets + assert_match /