diff --git a/app/controllers/admin/site_settings_controller.rb b/app/controllers/admin/site_settings_controller.rb new file mode 100644 index 0000000..9272f31 --- /dev/null +++ b/app/controllers/admin/site_settings_controller.rb @@ -0,0 +1,31 @@ +class Admin::SiteSettingsController < Admin::BaseController + include ThemesManagementHelper + before_filter :get_settings + before_filter :get_themes, :only => [:edit] + + protected + def get_settings + @settings = settings # This is defined in site_settings_helper + end + + def get_themes + @themes = list_themes + end + + public + def show + end + + def edit + end + + def update + if @settings.update_attributes(params[:site_setting]) + flash[:notice] = "Site Settings were updated successfully." + redirect_to :action => 'show' + else + flash.now[:error] = "There was a problem updating the site settings." + render :action => 'edit' + end + end +end diff --git a/app/controllers/application.rb b/app/controllers/application.rb index 98a2c7b..6d799e4 100644 --- a/app/controllers/application.rb +++ b/app/controllers/application.rb @@ -1,7 +1,9 @@ class ApplicationController < ActionController::Base include AuthenticatedSystem + include SiteSettingsHelper before_filter :login_from_cookie, :setup_plugin_nav, :set_layout_variables helper :all + theme :get_theme_setting def set_layout_variables @root = Page.root diff --git a/app/models/site_setting.rb b/app/models/site_setting.rb new file mode 100644 index 0000000..6972393 --- /dev/null +++ b/app/models/site_setting.rb @@ -0,0 +1,6 @@ +class SiteSetting < ActiveRecord::Base + def get_theme_setting + theme_setting = self.send(:user_theme_name) + theme_setting.blank? ? 'default' : theme_setting + end +end diff --git a/app/views/admin/_tabs.html.erb b/app/views/admin/_tabs.html.erb index 1b92992..2f981dc 100644 --- a/app/views/admin/_tabs.html.erb +++ b/app/views/admin/_tabs.html.erb @@ -2,8 +2,9 @@
<%= render :partial => "admin/page_plugins/admin_plugins_nav" -%> diff --git a/app/views/admin/site_settings/edit.html.erb b/app/views/admin/site_settings/edit.html.erb new file mode 100644 index 0000000..7fe12f3 --- /dev/null +++ b/app/views/admin/site_settings/edit.html.erb @@ -0,0 +1,7 @@ +

Edit Site Settings

+<% form_tag 'update' do -%> + <% fields_for @settings do |f| -%> + <%= f.select(:user_theme_name, @themes) -%> + <%= submit_tag 'Update' -%> + <% end -%> +<% end -%> diff --git a/app/views/admin/site_settings/show.html.erb b/app/views/admin/site_settings/show.html.erb new file mode 100644 index 0000000..c8d8b1a --- /dev/null +++ b/app/views/admin/site_settings/show.html.erb @@ -0,0 +1,5 @@ +

Site Settings

+<% content_for :sidebar do -%> + <%= link_to 'Edit Settings', edit_admin_site_settings_path -%> +<% end -%> +User Theme: <%= @settings.get_theme_setting -%> diff --git a/config/routes.rb b/config/routes.rb index 34633b8..cf51691 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -11,6 +11,7 @@ admin.resources :plugins admin.resource :account admin.connect 'account/:action/:id', :controller => 'account' + admin.resource :site_settings end map.connect '/admin', :controller => 'admin/pages' diff --git a/db/migrate/20080913132029_create_site_settings.rb b/db/migrate/20080913132029_create_site_settings.rb new file mode 100644 index 0000000..ef26a73 --- /dev/null +++ b/db/migrate/20080913132029_create_site_settings.rb @@ -0,0 +1,14 @@ +class CreateSiteSettings < ActiveRecord::Migration + def self.up + create_table :site_settings do |t| + t.string :name + t.string :user_theme_name + + t.timestamps + end + end + + def self.down + drop_table :site_settings + end +end diff --git a/lib/site_settings_helper.rb b/lib/site_settings_helper.rb new file mode 100644 index 0000000..8b4b032 --- /dev/null +++ b/lib/site_settings_helper.rb @@ -0,0 +1,13 @@ +module SiteSettingsHelper + def get_setting(name) + settings.send(name) + end + + def get_theme_setting + settings.get_theme_setting + end + + def settings + SiteSetting.find_or_create_by_name(:default) + end +end diff --git a/lib/tasks/utils.rake b/lib/tasks/utils.rake index 708c152..af927d7 100644 --- a/lib/tasks/utils.rake +++ b/lib/tasks/utils.rake @@ -10,4 +10,4 @@ namespace :utils do puts "Initial user already exists, exiting" end end -end \ No newline at end of file +end diff --git a/lib/themes_management_helper.rb b/lib/themes_management_helper.rb new file mode 100644 index 0000000..f0883cb --- /dev/null +++ b/lib/themes_management_helper.rb @@ -0,0 +1,9 @@ +module ThemesManagementHelper + def list_themes + themes_dir.entries.sort.delete_if{|e| e =~ /^\.$|^\.\.$/ } + end + + def themes_dir + Dir.new("#{RAILS_ROOT}/themes") + end +end diff --git a/public/stylesheets/admin.css b/public/stylesheets/admin.css index 3c5829d..c9d77bc 100644 --- a/public/stylesheets/admin.css +++ b/public/stylesheets/admin.css @@ -79,7 +79,7 @@ body{ padding:5px; width: 71%; margin-left: 10px; - border-width: 0 2px 4px 0px; + border-width: 0 2px 2px 0px; border-style: solid; border-color: #aaa; } diff --git a/public/themes/default/images/background-red-squares-7.png b/public/themes/default/images/background-red-squares-7.png new file mode 100644 index 0000000..eacd33b Binary files /dev/null and b/public/themes/default/images/background-red-squares-7.png differ diff --git a/public/themes/default/images/images/background-red-squares-7.png b/public/themes/default/images/images/background-red-squares-7.png new file mode 100644 index 0000000..eacd33b Binary files /dev/null and b/public/themes/default/images/images/background-red-squares-7.png differ diff --git a/public/themes/default/stylesheets/stylesheets/base.css b/public/themes/default/stylesheets/stylesheets/base.css new file mode 100644 index 0000000..1b8f4dc --- /dev/null +++ b/public/themes/default/stylesheets/stylesheets/base.css @@ -0,0 +1,129 @@ +html { + background:#000; + color: #ddd; + /* background-image: url(/images/background-blue-squares.png); */ + /* background-image: url(/images/background-blue-squares-2.png); */ + /* background-image: url(/images/background-blue-squares-3.png); */ + /* background-image: url(/images/background-blue-squares-4.png); */ + /* background-image: url(/images/background-blue-squares-5.png); */ + /* background-image: url(/images/background-blue-squares-6.png); */ + /* background-image: url(/images/background-blue-squares-7.png); */ + background-image: url(/themes/default/images/background-red-squares-7.png); + background-repeat: repeat-x; +} +body{ + font-family: "Gill Sans","Franklin Gothic Medium","Lucida Grande",Arial,Helvetica; +} +#main{ + width: 800px; + margin: 0 auto; + position: relative; +} +#header{ + margin-bottom: 10px; +} +#header h1{ + font-size: 260%; + color: #fff; + background-color: #000; + padding: 10px 0; + width: 260px; +} +#header .credits{ + display: block; + background-color: #c2c655; + color: #111; + position: absolute; + top: 0; + left: 500px; + padding: 4px 10px 10px 10px; + line-height: 1.4em; +} +#header .credits a{ + background-color: #868a1f; + padding: 2px; + color: white; +} +#header h1 span.logo{ + padding-left: 20px; + background-image: url(/images/ansuz_logo.png); + background-repeat: no-repeat; + background-position: center; + background-color: #111; + margin-right: 10px; +} +#navigation{ + width: 200px; + float: left; + margin: 0 10px 0 0; +} +#navigation h3{ + display: none; +} +#navigation li a{ + padding: 5px 10px; + background-color: #111; + color: #ccc; + display: block; + text-decoration: none; +} +#navigation li.active a, +#navigation li.active a:hover { + background-color: #c8379a; + color: white; + cursor: default; +} +#navigation li a:hover { + color: white; + border-left: 4px solid #0084ff; + padding-left: 6px; + background-color: #222; +} +div#breadcrumb{ + background-color: #222; + margin: -10px -10px 5px -10px; + padding: 10px; +} +#content{ + width: 570px; + background-color: #333; + float: left; + padding: 10px; +} +#footer{ + margin-top: 10px; + background-color: #111; + color: #aaa; + padding: 10px; +} +div.clear{ + clear: both; +} +h2{ + font-size: 175%; + color: #0084ff; +} +h3{ + font-size: 120%; + color: #0084ff; + background-color: #111; + padding: 6px 10px; + margin: 20px 0 6px; +} +p{ + margin-bottom: 10px; +} +ol{ + margin-left: 20px; +} +ol li{ + list-style-type: decimal; +} +.module{ + background-color: #333; + color: #ccc; + padding: 10px; +} +a{ + color: #0084FF; +} diff --git a/test/fixtures/site_settings.yml b/test/fixtures/site_settings.yml new file mode 100644 index 0000000..c975e7c --- /dev/null +++ b/test/fixtures/site_settings.yml @@ -0,0 +1,7 @@ +# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html + +one: + user_theme_name: MyString + +two: + user_theme_name: MyString diff --git a/test/unit/site_setting_test.rb b/test/unit/site_setting_test.rb new file mode 100644 index 0000000..05cb34a --- /dev/null +++ b/test/unit/site_setting_test.rb @@ -0,0 +1,8 @@ +require 'test_helper' + +class SiteSettingTest < ActiveSupport::TestCase + # Replace this with your real tests. + def test_truth + assert true + end +end diff --git a/themes/default-pink/about.markdown b/themes/default-pink/about.markdown new file mode 100644 index 0000000..de35179 --- /dev/null +++ b/themes/default-pink/about.markdown @@ -0,0 +1 @@ +Default Ansuz Theme diff --git a/themes/default-pink/images/background-red-squares-7.png b/themes/default-pink/images/background-red-squares-7.png new file mode 100644 index 0000000..eacd33b Binary files /dev/null and b/themes/default-pink/images/background-red-squares-7.png differ diff --git a/themes/default-pink/layouts/application.html.erb b/themes/default-pink/layouts/application.html.erb new file mode 100644 index 0000000..c3aa019 --- /dev/null +++ b/themes/default-pink/layouts/application.html.erb @@ -0,0 +1,43 @@ + + + + + Ansuz with Themes! + + + + + + + <%= stylesheet_link_tag 'yui-reset-fonts' -%> + <%= stylesheet_link_tag 'base' -%> + <%= stylesheet_link_tag 'sprite' -%> + <%= stylesheet_link_tag 'lightbox' -%> + <%= javascript_include_tag :defaults, 'effects', 'builder', 'lightbox', 'niftycube', 'handle_rounded_corners', 'jquery', 'jqModal', 'jquery.growl.js' -%> + + + +
+
+ +
+ <%= @content_for_layout -%> +
+
+ <%= render :partial => "page/footer" -%> +
+
+ + diff --git a/themes/default-pink/layouts/page.html.erb b/themes/default-pink/layouts/page.html.erb new file mode 100644 index 0000000..3582820 --- /dev/null +++ b/themes/default-pink/layouts/page.html.erb @@ -0,0 +1,46 @@ + + + + + Ansuz - <%= @page.title if @page -%> - with themes! + + + + + + + <%= stylesheet_link_tag 'yui-reset-fonts' -%> + <%= theme_stylesheet_link_tag 'base' -%> + <%= stylesheet_link_tag 'sprite' -%> + <%= stylesheet_link_tag 'lightbox' -%> + <%= javascript_include_tag :defaults, 'effects', 'builder', 'lightbox', 'niftycube', 'handle_rounded_corners', 'jquery', 'jqModal', 'jquery.growl.js', 'ansuz/growls' -%> + + + +
+
+ + <%= render :partial => "page/top_nav" -%> +
+ <%= render :partial => "page/breadcrumb" if (@page && (@page != @root)) -%> + <%= @content_for_layout -%> + <%= render :partial => "page/child_nav" if (@page && (!@page.children.empty?)) -%> +
+
+ <%= render :partial => "page/footer" -%> +
+
+ + diff --git a/themes/default-pink/stylesheets/base.css b/themes/default-pink/stylesheets/base.css new file mode 100644 index 0000000..4170195 --- /dev/null +++ b/themes/default-pink/stylesheets/base.css @@ -0,0 +1,129 @@ +html { + background:#000; + color: #ddd; + /* background-image: url(/images/background-blue-squares.png); */ + /* background-image: url(/images/background-blue-squares-2.png); */ + /* background-image: url(/images/background-blue-squares-3.png); */ + /* background-image: url(/images/background-blue-squares-4.png); */ + /* background-image: url(/images/background-blue-squares-5.png); */ + /* background-image: url(/images/background-blue-squares-6.png); */ + /* background-image: url(/images/background-blue-squares-7.png); */ + background-image: url(/themes/default/images/background-red-squares-7.png); + background-repeat: repeat-x; +} +body{ + font-family: "Gill Sans","Franklin Gothic Medium","Lucida Grande",Arial,Helvetica; +} +#main{ + width: 800px; + margin: 0 auto; + position: relative; +} +#header{ + margin-bottom: 10px; +} +#header h1{ + font-size: 260%; + color: #fff; + background-color: #000; + padding: 10px 0; + width: 260px; +} +#header .credits{ + display: block; + background-color: #c2c655; + color: #111; + position: absolute; + top: 0; + left: 500px; + padding: 4px 10px 10px 10px; + line-height: 1.4em; +} +#header .credits a{ + background-color: #868a1f; + padding: 2px; + color: white; +} +#header h1 span.logo{ + padding-left: 20px; + background-image: url(/images/ansuz_logo.png); + background-repeat: no-repeat; + background-position: center; + background-color: #111; + margin-right: 10px; +} +#navigation{ + width: 200px; + float: left; + margin: 0 10px 0 0; +} +#navigation h3{ + display: none; +} +#navigation li a{ + padding: 5px 10px; + background-color: #111; + color: #ccc; + display: block; + text-decoration: none; +} +#navigation li.active a, +#navigation li.active a:hover { + background-color: #c8379a; + color: white; + cursor: default; +} +#navigation li a:hover { + color: white; + border-left: 4px solid #C8379A; + padding-left: 6px; + background-color: #222; +} +div#breadcrumb{ + background-color: #222; + margin: -10px -10px 5px -10px; + padding: 10px; +} +#content{ + width: 570px; + background-color: #333; + float: left; + padding: 10px; +} +#footer{ + margin-top: 10px; + background-color: #111; + color: #aaa; + padding: 10px; +} +div.clear{ + clear: both; +} +h2{ + font-size: 175%; + color: #C8379A; +} +h3{ + font-size: 120%; + color: #C8379A; + background-color: #111; + padding: 6px 10px; + margin: 20px 0 6px; +} +p{ + margin-bottom: 10px; +} +ol{ + margin-left: 20px; +} +ol li{ + list-style-type: decimal; +} +.module{ + background-color: #333; + color: #ccc; + padding: 10px; +} +a{ + color: #C8379A; +} diff --git a/themes/default/about.markdown b/themes/default/about.markdown new file mode 100644 index 0000000..de35179 --- /dev/null +++ b/themes/default/about.markdown @@ -0,0 +1 @@ +Default Ansuz Theme diff --git a/themes/default/images/background-red-squares-7.png b/themes/default/images/background-red-squares-7.png new file mode 100644 index 0000000..eacd33b Binary files /dev/null and b/themes/default/images/background-red-squares-7.png differ diff --git a/themes/default/layouts/application.html.erb b/themes/default/layouts/application.html.erb new file mode 100644 index 0000000..c3aa019 --- /dev/null +++ b/themes/default/layouts/application.html.erb @@ -0,0 +1,43 @@ + + + + + Ansuz with Themes! + + + + + + + <%= stylesheet_link_tag 'yui-reset-fonts' -%> + <%= stylesheet_link_tag 'base' -%> + <%= stylesheet_link_tag 'sprite' -%> + <%= stylesheet_link_tag 'lightbox' -%> + <%= javascript_include_tag :defaults, 'effects', 'builder', 'lightbox', 'niftycube', 'handle_rounded_corners', 'jquery', 'jqModal', 'jquery.growl.js' -%> + + + +
+
+ +
+ <%= @content_for_layout -%> +
+
+ <%= render :partial => "page/footer" -%> +
+
+ + diff --git a/themes/default/layouts/page.html.erb b/themes/default/layouts/page.html.erb new file mode 100644 index 0000000..3582820 --- /dev/null +++ b/themes/default/layouts/page.html.erb @@ -0,0 +1,46 @@ + + + + + Ansuz - <%= @page.title if @page -%> - with themes! + + + + + + + <%= stylesheet_link_tag 'yui-reset-fonts' -%> + <%= theme_stylesheet_link_tag 'base' -%> + <%= stylesheet_link_tag 'sprite' -%> + <%= stylesheet_link_tag 'lightbox' -%> + <%= javascript_include_tag :defaults, 'effects', 'builder', 'lightbox', 'niftycube', 'handle_rounded_corners', 'jquery', 'jqModal', 'jquery.growl.js', 'ansuz/growls' -%> + + + +
+
+ + <%= render :partial => "page/top_nav" -%> +
+ <%= render :partial => "page/breadcrumb" if (@page && (@page != @root)) -%> + <%= @content_for_layout -%> + <%= render :partial => "page/child_nav" if (@page && (!@page.children.empty?)) -%> +
+
+ <%= render :partial => "page/footer" -%> +
+
+ + diff --git a/themes/default/stylesheets/base.css b/themes/default/stylesheets/base.css new file mode 100644 index 0000000..3041141 --- /dev/null +++ b/themes/default/stylesheets/base.css @@ -0,0 +1,128 @@ +html { + background:#000; + color: #ddd; + /* background-image: url(/images/background-blue-squares.png); */ + /* background-image: url(/images/background-blue-squares-2.png); */ + /* background-image: url(/images/background-blue-squares-3.png); */ + /* background-image: url(/images/background-blue-squares-4.png); */ + /* background-image: url(/images/background-blue-squares-5.png); */ + /* background-image: url(/images/background-blue-squares-6.png); */ + background-image: url(/images/background-blue-squares-7.png); + background-repeat: repeat-x; +} +body{ + font-family: "Gill Sans","Franklin Gothic Medium","Lucida Grande",Arial,Helvetica; +} +#main{ + width: 800px; + margin: 0 auto; + position: relative; +} +#header{ + margin-bottom: 10px; +} +#header h1{ + font-size: 260%; + color: #fff; + background-color: #000; + padding: 10px 0; + width: 260px; +} +#header .credits{ + display: block; + background-color: #c2c655; + color: #111; + position: absolute; + top: 0; + left: 500px; + padding: 4px 10px 10px 10px; + line-height: 1.4em; +} +#header .credits a{ + background-color: #868a1f; + padding: 2px; + color: white; +} +#header h1 span.logo{ + padding-left: 20px; + background-image: url(/images/ansuz_logo.png); + background-repeat: no-repeat; + background-position: center; + background-color: #111; + margin-right: 10px; +} +#navigation{ + width: 200px; + float: left; + margin: 0 10px 0 0; +} +#navigation h3{ + display: none; +} +#navigation li a{ + padding: 5px 10px; + background-color: #111; + color: #ccc; + display: block; + text-decoration: none; +} +#navigation li.active a, +#navigation li.active a:hover { + background-color: #0084ff; + color: white; + cursor: default; +} +#navigation li a:hover { + color: white; + border-left: 4px solid #0084ff; + padding-left: 6px; + background-color: #222; +} +div#breadcrumb{ + background-color: #222; + margin: -10px -10px 5px -10px; + padding: 10px; +} +#content{ + width: 570px; + background-color: #333; + float: left; + padding: 10px; +} +#footer{ + margin-top: 10px; + background-color: #111; + color: #aaa; + padding: 10px; +} +div.clear{ + clear: both; +} +h2{ + font-size: 175%; + color: #0084ff; +} +h3{ + font-size: 120%; + color: #0084ff; + background-color: #111; + padding: 6px 10px; + margin: 20px 0 6px; +} +p{ + margin-bottom: 10px; +} +ol{ + margin-left: 20px; +} +ol li{ + list-style-type: decimal; +} +.module{ + background-color: #333; + color: #ccc; + padding: 10px; +} +a{ + color: #0084FF; +} diff --git a/vendor/plugins/ansuz_photo_album/app/controllers/photo_albums_controller.rb b/vendor/plugins/ansuz_photo_album/app/controllers/photo_albums_controller.rb index 064944d..ce23a7e 100644 --- a/vendor/plugins/ansuz_photo_album/app/controllers/photo_albums_controller.rb +++ b/vendor/plugins/ansuz_photo_album/app/controllers/photo_albums_controller.rb @@ -1,4 +1,4 @@ -class PhotoAlbumsController < ApplicationController +class PhotoAlbumsController < Admin::BaseController unloadable # This is required if you subclass a controller provided by the base rails app before_filter :load_photo_album, :only => [:show, :update] @@ -15,6 +15,7 @@ def load_photos end public def show + render :layout => false end def update diff --git a/vendor/plugins/theme_support/LICENSE b/vendor/plugins/theme_support/LICENSE new file mode 100755 index 0000000..1fef251 --- /dev/null +++ b/vendor/plugins/theme_support/LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2005 Matt McCray, based on code from Typo by Tobias Luetke + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWAR \ No newline at end of file diff --git a/vendor/plugins/theme_support/README b/vendor/plugins/theme_support/README new file mode 100755 index 0000000..64d0e6a --- /dev/null +++ b/vendor/plugins/theme_support/README @@ -0,0 +1,202 @@ +This theme_support version has been updated by Damien Le Berrigaud for Rails 2.0 +http://www.webdrivenblog.com/ + += Theme Support for Rails Applications + +This plugin provides support for themes to the rails application environment. +It supports theme specific images, stylesheets, javascripts, and views. The +views can be in ERb (rhtml) or liquid formats. Optionally, you can configure +the theme system to ignore any templates except liquid ones. + + +== Usage + +This plugin automatically makes any patches needed for theme support. You can +use the theme_generator to create the file structure needed, or create it +yourself. + +It expects the following theme folder structure. + + $app_root + themes/ + [theme_name] + layouts/ <- layout .rhtml or .liquid templates + images/ + stylesheets/ + javascripts/ + views/ <- you can override application views + about.markdown + preview.png + +When run in production mode, it will automatically cache the theme files so that +the web-server will deliver them in subsequent requests. + +It bears noting that, like Typo, this will mean your apache/fcgi process will need +write permissions. This could be a possible security vulnerability. + +With that in mind, it is best to pre-cache all of the theme files by using the +included rake tasks: + + $ rake theme_create_cache + +The theme file cache generates the following file structure: + + $app_root + public/ + themes/ + [theme_name]/ + images/ + stylesheets/ + javascripts/ + +There are other rake tasks available: + + - theme_create_cache + - theme_remove_cache + - theme_update_cache + +You specify which theme to use in your controller by using the 'theme' helper. +It's used just like the 'layout' helper. In fact, you can use them both +simultaneously. The following will render actions using the 'default' layout +in the 'blue_bird' theme (theme/blue_bird/layouts/default.rhtml): + + class ApplicationController < ActionController::Base + layout 'default' + + theme 'blue_bird' + + ... + end + +You can also defer the theme lookup to a controller method: + + class ApplicationController < ActionController::Base + layout 'default' + + theme :get_theme + + def get_theme + + # If you let the user choose their own theme, you might + # add a User#theme field... + + current_user.theme + end + + ... + end + + +Note: By setting the theme in the ApplicationController you can set +the theme for the whole application. + +In your application views, there are theme specific helper tags +available to you. For ERb templates they are: + + - theme_image_tag + - theme_image_path + - theme_javascript_include_tag + - theme_javascript_path + - theme_stylesheet_link_tag + - theme_stylesheet_path + +For liquid templates there is a single helper, themeitem, that will determine +the path base on the theme file extension. Here's how you'd use it: + + + ... + + +The output from those two calls are: + + + ... + + +New in version 1.4 is ActionMailer support. Note, this is still experimental. However, +if you would like your themes to be able to override your ActionMailer views, you can +send the theme in your deliver_* method call. For example, assuming we have an ActionMailer +class named Mailer, and have implemented theme_support as shown above, here's how you would +allowing themes in emails: + + + def send_email + Mailer.deliver_my_email( 'a variable', :theme=>get_theme ) + end + + +== Contributors + +The theme_support pluging includs patches from the following: + +* agkr +* D.J. Vogel + +Thanks guys! + +== Changelog + + 1.4.0 - Better support for Rails 1.1+. Updated the liquid themeitem tag. + Liquid layouts are no longer generated by default.Added a couple + of patches. One allows theme sub-directories. For example, you + can have: + + [theme_dir] + stylesheets/ + admin/ + main.css + + Added experimental support for themeing ActionMailer classes. + They work as normal, if you want to all theme's to override the + .rhtml|.liquid views, send the theme in the deliver_* method. For + example: + + Mailer.deliver_signup( user, :theme=>get_theme() ) + + In that example, `get_theme` is a method on the controller and at + the top we've used: + + layout 'default' + theme :get_theme + + 1.3.0 - The theme_system component is no longer needed. All of the + theme support is driven by a single plugin named, oddly enough, + 'theme_support'. Also improved theme route support. Instead of + overriding RouteSet#reload, RouteSet#draw is overridden, making + the theme support entirely transparent -- hopefully ;-) + + 1.2.2 - More Bug-fixes. + + 1.2.1 - Bug-fixes and documentation clean up. + + 1.2.0 - Updated actionview_ex with the new render_file additions from + Typo. Renamed the rake tasks so that they all start with + 'theme' (theme_create_cache, theme_remove_cache, + theme_update_cache). You can update the system files by running: + + $ ./script/generate theme _system_ + + Full support for Liquid templates, as well as an option to only + allow Liquid templates in a theme. + + 1.1.1 - Added rake tasks for pre-caching the themes, and removing the + cached themes. + + 1.1.0 - [Breaking] Abstraction of the Typo theme system. The themes are + now the same as is used in Typo. The theme engine itself is a + combination of plugins and a component. No more symlinks, thank + goodness. + + 1.0.2 - The current_theme is now retrieved from the controller. Where + symlinks are created on *nix systems, shortcuts are created + on Windows if Win32Utils is installed. + + 1.0.1 - Added 'themes' directory, theme definition file, and symlinks + to the appropriate directories on supported platforms. + + 1.0.0 - Initial release + + +--- +Copyright (c) 2005 Matt McCray, based on code from Typo by Tobias Luetke +released under the MIT license diff --git a/vendor/plugins/theme_support/generators/theme/USAGE b/vendor/plugins/theme_support/generators/theme/USAGE new file mode 100755 index 0000000..6927cbd --- /dev/null +++ b/vendor/plugins/theme_support/generators/theme/USAGE @@ -0,0 +1,15 @@ +NAME + theme - Creates the folder structure for a new theme + +SYNOPSIS + theme [theme_name] + +DESCRIPTION + This generator creates the folder structure for a new theme. It creates all of + the folders for your theme content (images, stylesheets, javascripts, layouts, + and views). + +EXAMPLE + ./script/generate theme default + + This will generate the file structure for a theme named 'default'. diff --git a/vendor/plugins/theme_support/generators/theme/templates/about.markdown b/vendor/plugins/theme_support/generators/theme/templates/about.markdown new file mode 100755 index 0000000..fb3b3c9 --- /dev/null +++ b/vendor/plugins/theme_support/generators/theme/templates/about.markdown @@ -0,0 +1,5 @@ +### <%= class_name.underscore.humanize.titleize %> + +Author: *Me* + +This description can be found in themes/<%= file_name %>/about.markdown diff --git a/vendor/plugins/theme_support/generators/theme/templates/layout.liquid b/vendor/plugins/theme_support/generators/theme/templates/layout.liquid new file mode 100755 index 0000000..b24718c --- /dev/null +++ b/vendor/plugins/theme_support/generators/theme/templates/layout.liquid @@ -0,0 +1,11 @@ + + + + + + + + {{ content_for_layout }} + + \ No newline at end of file diff --git a/vendor/plugins/theme_support/generators/theme/templates/layout.rhtml b/vendor/plugins/theme_support/generators/theme/templates/layout.rhtml new file mode 100755 index 0000000..a74995c --- /dev/null +++ b/vendor/plugins/theme_support/generators/theme/templates/layout.rhtml @@ -0,0 +1,11 @@ + + + + + <%%= theme_stylesheet_link_tag '<%= file_name %>' %> + + + <%%= @content_for_layout %> + + \ No newline at end of file diff --git a/vendor/plugins/theme_support/generators/theme/templates/preview.png b/vendor/plugins/theme_support/generators/theme/templates/preview.png new file mode 100755 index 0000000..182c1f7 Binary files /dev/null and b/vendor/plugins/theme_support/generators/theme/templates/preview.png differ diff --git a/vendor/plugins/theme_support/generators/theme/templates/theme.css b/vendor/plugins/theme_support/generators/theme/templates/theme.css new file mode 100755 index 0000000..44471b1 --- /dev/null +++ b/vendor/plugins/theme_support/generators/theme/templates/theme.css @@ -0,0 +1,7 @@ +/* + Main StyleSheet for the '<%= class_name %>' theme +*/ + +BODY { + +} \ No newline at end of file diff --git a/vendor/plugins/theme_support/generators/theme/templates/theme.yml b/vendor/plugins/theme_support/generators/theme/templates/theme.yml new file mode 100755 index 0000000..f067d16 --- /dev/null +++ b/vendor/plugins/theme_support/generators/theme/templates/theme.yml @@ -0,0 +1,4 @@ +enabled: true +title: <%= class_name.underscore.humanize.titleize %> +author: Matt McCray +description: This is the description... All light and fluffy. diff --git a/vendor/plugins/theme_support/generators/theme/templates/views_readme b/vendor/plugins/theme_support/generators/theme/templates/views_readme new file mode 100755 index 0000000..548ce6b --- /dev/null +++ b/vendor/plugins/theme_support/generators/theme/templates/views_readme @@ -0,0 +1,13 @@ +# Overriding Views + +You can override views by putting custom `rhtml` or `liquid` +templates in this directory. You use the same folder structure +as Rails: + + views/ + [controller_name]/ + _overriden_partial.rhtml + overriden_action.rhtml + +*Note:* These are overrides! They will only work if they have +a matching view in the main rails `app/views` folder. \ No newline at end of file diff --git a/vendor/plugins/theme_support/generators/theme/theme_generator.rb b/vendor/plugins/theme_support/generators/theme/theme_generator.rb new file mode 100755 index 0000000..170a0e9 --- /dev/null +++ b/vendor/plugins/theme_support/generators/theme/theme_generator.rb @@ -0,0 +1,27 @@ +class ThemeGenerator < Rails::Generator::NamedBase + + def manifest + record do |m| + # Theme folder(s) + m.directory File.join( "themes", file_name ) + # theme content folders + m.directory File.join( "themes", file_name, "images" ) + m.directory File.join( "themes", file_name, "javascript" ) + m.directory File.join( "themes", file_name, "layouts" ) + m.directory File.join( "themes", file_name, "views" ) + m.directory File.join( "themes", file_name, "stylesheets" ) + # Default files... + # about + m.template 'about.markdown', File.join( 'themes', file_name, 'about.markdown' ) + # image + m.file 'preview.png', File.join( 'themes', file_name, 'images', 'preview.png' ) + # stylesheet + m.template "theme.css", File.join( "themes", file_name, "stylesheets", "#{file_name}.css" ) + # layouts + m.template 'layout.rhtml', File.join( 'themes', file_name, 'layouts', 'default.rhtml' ) + #m.template 'layout.liquid', File.join( 'themes', file_name, 'layouts', 'default.liquid' ) + # view readme + m.template 'views_readme', File.join( 'themes', file_name, 'views', 'views_readme.txt' ) + end + end +end \ No newline at end of file diff --git a/vendor/plugins/theme_support/init.rb b/vendor/plugins/theme_support/init.rb new file mode 100755 index 0000000..e5d87a9 --- /dev/null +++ b/vendor/plugins/theme_support/init.rb @@ -0,0 +1,18 @@ +# Initializes theme support by extending some of the core Rails classes +require 'patches/actionview_ex' +require 'patches/actioncontroller_ex' +require 'patches/actionmailer_ex' +require 'patches/routeset_ex' + +# Add the tag helpers for rhtml and, optionally, liquid templates +require 'helpers/rhtml_theme_tags' + +# Commented out to remove the message +# "Liquid doesn't seem to be loaded... uninitialized constant Liquid" + +#begin +# require 'helpers/liquid_theme_tags' +#rescue +# # I guess Liquid isn't being used... +# STDERR.puts "Liquid doesn't seem to be loaded... #{$!}" +#end diff --git a/vendor/plugins/theme_support/lib/helpers/liquid_theme_tags.rb b/vendor/plugins/theme_support/lib/helpers/liquid_theme_tags.rb new file mode 100755 index 0000000..51a30b0 --- /dev/null +++ b/vendor/plugins/theme_support/lib/helpers/liquid_theme_tags.rb @@ -0,0 +1,31 @@ +# A Liquid Tag for retrieving path information for theme specific media +# +# Returns the path based on the file extension +# +class Themeitem < Liquid::Block + + @@image_exts = %w( .png .jpg .jpeg .jpe .gif ) + @@stylesheet_exts = %w( .css ) + @@javascript_exts = %w( .js .htc ) + + def render(context) + # Which, if either, of these are correct? + base_url = context['request'].relative_url_root || ActionController::Base.asset_host.to_s + theme_name = @theme_name || context['active_theme'] + + filename = @nodelist.join('').strip + ext = File.extname( filename ) + + if @@image_exts.include?( ext ) + "#{base_url}/themes/#{theme_name}/images/#{filename}" + + elsif @@stylesheet_exts.include?( ext ) + "#{base_url}/themes/#{theme_name}/stylesheets/#{filename}" + + elsif @@javascript_exts.include?( ext ) + "#{base_url}/themes/#{theme_name}/javascript/#{filename}" + end + end +end + +Liquid::Template.register_tag( 'themeitem', Themeitem ) \ No newline at end of file diff --git a/vendor/plugins/theme_support/lib/helpers/rhtml_theme_tags.rb b/vendor/plugins/theme_support/lib/helpers/rhtml_theme_tags.rb new file mode 100755 index 0000000..bbd16f2 --- /dev/null +++ b/vendor/plugins/theme_support/lib/helpers/rhtml_theme_tags.rb @@ -0,0 +1,66 @@ +# +# These are theme helper tags +# +module ActionView::Helpers::AssetTagHelper + + # returns the public path to a theme stylesheet + def theme_stylesheet_path( source=nil, theme=nil ) + theme = theme || controller.current_theme + compute_public_path(source || "theme", "themes/#{theme}/stylesheets", 'css') + end + + # returns the path to a theme image + def theme_image_path( source, theme=nil ) + theme = theme || controller.current_theme + compute_public_path(source, "themes/#{theme}/images", 'png') + end + + # returns the path to a theme javascript + def theme_javascript_path( source, theme=nil ) + theme = theme || controller.current_theme + compute_public_path(source, "themes/#{theme}/javascript", 'js') + end + + + # This tag it will automatially include theme specific css files + def theme_stylesheet_link_tag(*sources) + sources.uniq! + options = sources.last.is_a?(Hash) ? sources.pop.stringify_keys : { } + sources.collect { |source| + source = theme_stylesheet_path(source) + tag("link", { "rel" => "Stylesheet", "type" => "text/css", "media" => "screen", "href" => source }.merge(options)) + }.join("\n") + end + + # This tag will return a theme-specific IMG + def theme_image_tag(source, options = {}) + options.symbolize_keys + + options[:src] = theme_image_path(source) + options[:alt] ||= File.basename(options[:src], '.*').split('.').first.capitalize + + if options[:size] + options[:width], options[:height] = options[:size].split("x") + options.delete :size + end + + tag("img", options) + end + + # This tag can be used to return theme-specific javscripts + def theme_javascript_include_tag(*sources) + options = sources.last.is_a?(Hash) ? sources.pop.stringify_keys : { } + if sources.include?(:defaults) + sources = sources[0..(sources.index(:defaults))] + + @@javascript_default_sources.dup + + sources[(sources.index(:defaults) + 1)..sources.length] + sources.delete(:defaults) + sources << "application" if defined?(RAILS_ROOT) && File.exists?("#{RAILS_ROOT}/public/javascripts/application.js") + end + sources.collect { |source| + source = theme_javascript_path(source) + content_tag("script", "", { "type" => "text/javascript", "src" => source }.merge(options)) + }.join("\n") + end + +end \ No newline at end of file diff --git a/vendor/plugins/theme_support/lib/patches/actioncontroller_ex.rb b/vendor/plugins/theme_support/lib/patches/actioncontroller_ex.rb new file mode 100755 index 0000000..6cc9bc6 --- /dev/null +++ b/vendor/plugins/theme_support/lib/patches/actioncontroller_ex.rb @@ -0,0 +1,59 @@ +# Extend the Base ActionController to support themes +ActionController::Base.class_eval do + + attr_accessor :current_theme + attr_accessor :force_liquid_template + + # Use this in your controller just like the layout macro. + # Example: + # + # theme 'theme_name' + # + # -or- + # + # theme :get_theme + # + # def get_theme + # 'theme_name' + # end + def self.theme(theme_name, conditions = {}) + # TODO: Allow conditions... (?) + write_inheritable_attribute "theme", theme_name + end + + # Set force_liquid to true in your controlelr to only allow + # Liquid template in themes. + # Example: + # + # force_liquid true + def self.force_liquid(force_liquid_value, conditions = {}) + # TODO: Allow conditions... (?) + write_inheritable_attribute "force_liquid", force_liquid_value + end + + # Retrieves the current set theme + def current_theme(passed_theme=nil) + theme = passed_theme || self.class.read_inheritable_attribute("theme") + + @active_theme = case theme + when Symbol then send(theme) + when Proc then theme.call(self) + when String then theme + end + end + + # Retrieves the force liquid flag + def force_liquid_template(passed_value=nil) + force_liquid = passed_value || self.class.read_inheritable_attribute("force_liquid") + + force_liquid_template = case force_liquid + when Symbol then send(force_liquid) + when Proc then force_liquid.call(self) + when String then force_liquid == 'true' + when TrueClass then force_liquid + when FalseClass then force_liquid + when Fixnum then force_liquid == 1 + end + end + +end \ No newline at end of file diff --git a/vendor/plugins/theme_support/lib/patches/actionmailer_ex.rb b/vendor/plugins/theme_support/lib/patches/actionmailer_ex.rb new file mode 100755 index 0000000..c42db66 --- /dev/null +++ b/vendor/plugins/theme_support/lib/patches/actionmailer_ex.rb @@ -0,0 +1,27 @@ +# Extend the Base ActionController to support themes +ActionMailer::Base.class_eval do + + alias_method :__render, :render + alias_method :__initialize, :initialize + + @current_theme = nil + + attr_reader :current_theme + + def initialize(method_name=nil, *parameters) + if parameters[-1].is_a? Hash and (parameters[-1].include? :theme) + @current_theme = parameters[-1][:theme] + parameters[-1].delete :theme + parameters[-1][:current_theme] = @current_theme + end + create!(method_name, *parameters) if method_name + end + + def render(opts) + body = opts.delete(:body) + body[:current_theme] = @current_theme + opts[:file] = "#{mailer_name}/#{opts[:file]}" + initialize_template_class(body).render(opts) + end + +end \ No newline at end of file diff --git a/vendor/plugins/theme_support/lib/patches/actionview_ex.rb b/vendor/plugins/theme_support/lib/patches/actionview_ex.rb new file mode 100755 index 0000000..96c6992 --- /dev/null +++ b/vendor/plugins/theme_support/lib/patches/actionview_ex.rb @@ -0,0 +1,45 @@ +# Extending ActionView::Base to support rendering themes +# +module ActionView + + # Extending ActionView::Base to support rendering themes + class Base + alias_method :theme_support_old_render_file, :render_file + # Overrides the default Base#render_file to allow theme-specific views + def render_file(template_path, use_full_path = false, local_assigns = {}) + + search_path = [ + "#{RAILS_ROOT}/themes/#{controller.current_theme}/views", # for components + "#{RAILS_ROOT}/themes/#{controller.current_theme}", # for layouts + ] + + @finder.prepend_view_path(search_path) + local_assigns['active_theme'] = get_current_theme(local_assigns) + theme_support_old_render_file(template_path, use_full_path, local_assigns) + + end + private + + def force_liquid? + unless controller.nil? + if controller.respond_to?('force_liquid_template') + controller.force_liquid_template + end + else + false + end + end + + def get_current_theme(local_assigns) + unless controller.nil? + if controller.respond_to?('current_theme') + return controller.current_theme || false + end + end + # Used with ActionMailers + if local_assigns.include? :current_theme + return local_assigns.delete :current_theme + end + end + end +end diff --git a/vendor/plugins/theme_support/lib/patches/routeset_ex.rb b/vendor/plugins/theme_support/lib/patches/routeset_ex.rb new file mode 100755 index 0000000..9617f2d --- /dev/null +++ b/vendor/plugins/theme_support/lib/patches/routeset_ex.rb @@ -0,0 +1,26 @@ +# Extends ActionController::Routing::RouteSet to automatically add the theme routes +class ActionController::Routing::RouteSet + + alias_method :__draw, :draw + + # Overrides the default RouteSet#draw to automatically + # include the routes needed by the ThemeController + def draw + clear! + map = Mapper.new(self) + + create_theme_routes(map) + yield map + + named_routes.install + end + + # Creates the required routes for the ThemeController... + def create_theme_routes(map) + map.theme_images "/themes/:theme/images/*filename", :controller=>'theme', :action=>'images' + map.theme_stylesheets "/themes/:theme/stylesheets/*filename", :controller=>'theme', :action=>'stylesheets' + map.theme_javascript "/themes/:theme/javascript/*filename", :controller=>'theme', :action=>'javascript' + map.connect "/themes/*whatever", :controller=>'theme', :action=>'error' + end + +end \ No newline at end of file diff --git a/vendor/plugins/theme_support/lib/theme.rb b/vendor/plugins/theme_support/lib/theme.rb new file mode 100755 index 0000000..4562784 --- /dev/null +++ b/vendor/plugins/theme_support/lib/theme.rb @@ -0,0 +1,58 @@ +class Theme + cattr_accessor :cache_theme_lookup + @@cache_theme_lookup = false + + attr_accessor :name, :title, :description, :preview_image + + def initialize(name) + @name = name + @title = name.underscore.humanize.titleize + @description_html = nil + end + + def description + if @description_html.nil? + @description_html = RedCloth.new(File.read( File.join(Theme.path_to_theme(name), "about.markdown") )).to_html(:markdown, :textile) rescue "#{title}" + end + @description_html + end + + def has_preview? + File.exists?( File.join( Theme.path_to_theme(name), 'images', 'preview.png' ) ) rescue false + end + + def preview_image + 'preview.png' + end + + def self.find_all + installed_themes.inject([]) do |array, path| + array << theme_from_path(path) + end + end + +private + + def self.themes_root + File.join(RAILS_ROOT, "themes") + end + + def self.path_to_theme(theme) + File.join(themes_root, theme) + end + + def self.theme_from_path(path) + name = path.scan(/[-\w]+$/i).flatten.first + self.new(name) + end + + def self.installed_themes + cache_theme_lookup ? @theme_cache ||= search_theme_directory : search_theme_directory + end + + def self.search_theme_directory + Dir.glob("#{themes_root}/[-_a-zA-Z0-9]*").collect do |file| + file if File.directory?(file) + end.compact + end +end diff --git a/vendor/plugins/theme_support/lib/theme_controller.rb b/vendor/plugins/theme_support/lib/theme_controller.rb new file mode 100755 index 0000000..76d7ba2 --- /dev/null +++ b/vendor/plugins/theme_support/lib/theme_controller.rb @@ -0,0 +1,61 @@ +# The controller for serving/cacheing theme content... +# +class ThemeController < ActionController::Base + + after_filter :cache_theme_files + + def stylesheets + render_theme_item(:stylesheets, params[:filename].to_s, params[:theme], 'text/css') + end + + def javascript + render_theme_item(:javascript, params[:filename].to_s, params[:theme], 'text/javascript') + end + + def images + render_theme_item(:images, params[:filename].to_s, params[:theme]) + end + + def error + render :nothing => true, :status => 404 + end + + private + + def render_theme_item(type, file, theme, mime = mime_for(file)) + render :text => "Not Found", :status => 404 and return if file.split(%r{[\\/]}).include?("..") + send_file "#{Theme.path_to_theme(theme)}/#{type}/#{file}", :type => mime, :disposition => 'inline', :stream => false + end + + def cache_theme_files + path = request.request_uri + begin + ThemeController.cache_page( response.body, path ) + rescue + STERR.puts "Cache Exception: #{$!}" + end + end + + + def mime_for(filename) + case filename.downcase + when /\.js$/ + 'text/javascript' + when /\.css$/ + 'text/css' + when /\.gif$/ + 'image/gif' + when /(\.jpg|\.jpeg)$/ + 'image/jpeg' + when /\.png$/ + 'image/png' + when /\.swf$/ + 'application/x-shockwave-flash' + else + 'application/binary' + end + end + +end + + diff --git a/vendor/plugins/theme_support/lib/theme_error.rb b/vendor/plugins/theme_support/lib/theme_error.rb new file mode 100755 index 0000000..85e4e3e --- /dev/null +++ b/vendor/plugins/theme_support/lib/theme_error.rb @@ -0,0 +1,4 @@ +# ThemeError is thrown when force_liquid is true, and +# a .liquid template isn't found. +class ThemeError < StandardError +end diff --git a/vendor/plugins/theme_support/lib/theme_helper.rb b/vendor/plugins/theme_support/lib/theme_helper.rb new file mode 100755 index 0000000..61e429e --- /dev/null +++ b/vendor/plugins/theme_support/lib/theme_helper.rb @@ -0,0 +1,3 @@ +# this is here so that Rails doesn't complain about a missing default helper... +module ThemeHelper +end \ No newline at end of file diff --git a/vendor/plugins/theme_support/tasks/themes.rake b/vendor/plugins/theme_support/tasks/themes.rake new file mode 100755 index 0000000..260dd68 --- /dev/null +++ b/vendor/plugins/theme_support/tasks/themes.rake @@ -0,0 +1,23 @@ + +desc "Creates the cached (public) theme folders" +task :theme_create_cache do + for theme in Dir.glob("#{RAILS_ROOT}/themes/*") + theme_name = theme.split( File::Separator )[-1] + puts "Creating #{RAILS_ROOT}/public/themes/#{theme_name}" + + FileUtils.mkdir_p "#{RAILS_ROOT}/public/themes/#{theme_name}" + + FileUtils.cp_r "#{theme}/images", "#{RAILS_ROOT}/public/themes/#{theme_name}/images", :verbose => true + FileUtils.cp_r "#{theme}/stylesheets", "#{RAILS_ROOT}/public/themes/#{theme_name}/stylesheets", :verbose => true + FileUtils.cp_r "#{theme}/javascript", "#{RAILS_ROOT}/public/themes/#{theme_name}/javascript", :verbose => true + end +end + +desc "Removes the cached (public) theme folders" +task :theme_remove_cache do + puts "Removing #{RAILS_ROOT}/public/themes" + FileUtils.rm_r "#{RAILS_ROOT}/public/themes", :force => true +end + +desc "Updates the cached (public) theme folders" +task :theme_update_cache => [:theme_remove_cache, :theme_create_cache] \ No newline at end of file