diff --git a/app/assets/javascripts/admin/models/site_customization.js b/app/assets/javascripts/admin/models/site_customization.js
index 8e90d13cef7..71143b89683 100644
--- a/app/assets/javascripts/admin/models/site_customization.js
+++ b/app/assets/javascripts/admin/models/site_customization.js
@@ -7,7 +7,7 @@
@module Discourse
**/
Discourse.SiteCustomization = Discourse.Model.extend({
- trackedProperties: ['enabled', 'name', 'stylesheet', 'header', 'override_default_style'],
+ trackedProperties: ['enabled', 'name', 'stylesheet', 'header', 'mobile_stylesheet', 'mobile_header', 'override_default_style'],
init: function() {
this._super();
@@ -33,7 +33,7 @@ Discourse.SiteCustomization = Discourse.Model.extend({
return changed;
- }.property('override_default_style', 'enabled', 'name', 'stylesheet', 'header', 'originals'),
+ }.property('override_default_style', 'enabled', 'name', 'stylesheet', 'header', 'mobile_stylesheet', 'mobile_header', 'originals'),
startTrackingChanges: function() {
var _this = this;
@@ -62,6 +62,8 @@ Discourse.SiteCustomization = Discourse.Model.extend({
enabled: this.enabled,
stylesheet: this.stylesheet,
header: this.header,
+ mobile_stylesheet: this.mobile_stylesheet,
+ mobile_header: this.mobile_header,
override_default_style: this.override_default_style
};
diff --git a/app/assets/javascripts/admin/templates/customize.js.handlebars b/app/assets/javascripts/admin/templates/customize.js.handlebars
index 6a32ccee663..44b1307b9b4 100644
--- a/app/assets/javascripts/admin/templates/customize.js.handlebars
+++ b/app/assets/javascripts/admin/templates/customize.js.handlebars
@@ -12,25 +12,38 @@
{{#if selectedItem}}
-
-
{{#with selectedItem}}
{{textField class="style-name" value=name}}
+
+
+
{{#if view.headerActive}}
{{aceEditor content=header mode="html"}}
{{/if}}
{{#if view.stylesheetActive}}
{{aceEditor content=stylesheet mode="scss"}}
{{/if}}
+ {{#if view.mobileHeaderActive}}
+ {{aceEditor content=mobile_header mode="html"}}
+ {{/if}}
+ {{#if view.mobileStylesheetActive}}
+ {{aceEditor content=mobile_stylesheet mode="scss"}}
+ {{/if}}
{{/with}}
diff --git a/app/assets/javascripts/admin/views/admin_customize_view.js b/app/assets/javascripts/admin/views/admin_customize_view.js
index a030d43244b..31761233661 100644
--- a/app/assets/javascripts/admin/views/admin_customize_view.js
+++ b/app/assets/javascripts/admin/views/admin_customize_view.js
@@ -11,20 +11,16 @@
Discourse.AdminCustomizeView = Discourse.View.extend({
templateName: 'admin/templates/customize',
classNames: ['customize'],
+ headerActive: Ember.computed.equal('selected', 'header'),
+ stylesheetActive: Ember.computed.equal('selected', 'stylesheet'),
+ mobileHeaderActive: Ember.computed.equal('selected', 'mobileHeader'),
+ mobileStylesheetActive: Ember.computed.equal('selected', 'mobileStylesheet'),
init: function() {
this._super();
this.set('selected', 'stylesheet');
},
- headerActive: (function() {
- return this.get('selected') === 'header';
- }).property('selected'),
-
- stylesheetActive: (function() {
- return this.get('selected') === 'stylesheet';
- }).property('selected'),
-
selectHeader: function() {
this.set('selected', 'header');
},
@@ -33,6 +29,14 @@ Discourse.AdminCustomizeView = Discourse.View.extend({
this.set('selected', 'stylesheet');
},
+ selectMobileHeader: function() {
+ this.set('selected', 'mobileHeader');
+ },
+
+ selectMobileStylesheet: function() {
+ this.set('selected', 'mobileStylesheet');
+ },
+
didInsertElement: function() {
var controller = this.get('controller');
return Mousetrap.bindGlobal(['meta+s', 'ctrl+s'], function() {
diff --git a/app/controllers/admin/site_customizations_controller.rb b/app/controllers/admin/site_customizations_controller.rb
index 855b947bd9b..d2595a3f11c 100644
--- a/app/controllers/admin/site_customizations_controller.rb
+++ b/app/controllers/admin/site_customizations_controller.rb
@@ -49,7 +49,7 @@ class Admin::SiteCustomizationsController < Admin::AdminController
private
def site_customization_params
- params.require(:site_customization).permit(:name, :stylesheet, :header, :position, :enabled, :key, :override_default_style, :stylesheet_baked)
+ params.require(:site_customization).permit(:name, :stylesheet, :header, :mobile_stylesheet, :mobile_header, :position, :enabled, :key, :override_default_style, :stylesheet_baked)
end
def log_site_customization_change(old_record, new_params)
diff --git a/app/models/site_customization.rb b/app/models/site_customization.rb
index 40814ea7917..c52eb4841e9 100644
--- a/app/models/site_customization.rb
+++ b/app/models/site_customization.rb
@@ -12,31 +12,35 @@ class SiteCustomization < ActiveRecord::Base
end
before_save do
- if stylesheet_changed?
- begin
- self.stylesheet_baked = Sass.compile stylesheet
- rescue Sass::SyntaxError => e
- error = e.sass_backtrace_str("custom stylesheet")
- error.gsub!("\n", '\A ')
- error.gsub!("'", '\27 ')
+ ['stylesheet', 'mobile_stylesheet'].each do |stylesheet_attr|
+ if self.send("#{stylesheet_attr}_changed?")
+ begin
+ self.send("#{stylesheet_attr}_baked=", Sass.compile(self.send(stylesheet_attr)))
+ rescue Sass::SyntaxError => e
+ error = e.sass_backtrace_str("custom stylesheet")
+ error.gsub!("\n", '\A ')
+ error.gsub!("'", '\27 ')
- self.stylesheet_baked =
-"#main {display: none;}
-footer {white-space: pre; margin-left: 100px;}
-footer:after{ content: '#{error}' }"
+ self.send("#{stylesheet_attr}_baked=",
+ "#main {display: none;}
+ footer {white-space: pre; margin-left: 100px;}
+ footer:after{ content: '#{error}' }")
+ end
end
end
end
after_save do
if stylesheet_changed?
- if File.exists?(stylesheet_fullpath)
- File.delete stylesheet_fullpath
- end
+ File.delete(stylesheet_fullpath) if File.exists?(stylesheet_fullpath)
+ end
+ if mobile_stylesheet_changed?
+ File.delete(stylesheet_fullpath(:mobile)) if File.exists?(stylesheet_fullpath(:mobile))
end
remove_from_cache!
- if stylesheet_changed?
- ensure_stylesheet_on_disk!
+ if stylesheet_changed? or mobile_stylesheet_changed?
+ ensure_stylesheets_on_disk!
+ # TODO: this is broken now because there's mobile stuff too
MessageBus.publish "/file-change/#{key}", stylesheet_hash
end
MessageBus.publish "/header-change/#{key}", header if header_changed?
@@ -47,6 +51,9 @@ footer:after{ content: '#{error}' }"
if File.exists?(stylesheet_fullpath)
File.delete stylesheet_fullpath
end
+ if File.exists?(stylesheet_fullpath(:mobile))
+ File.delete stylesheet_fullpath(:mobile)
+ end
self.remove_from_cache!
end
@@ -71,17 +78,17 @@ footer:after{ content: '#{error}' }"
end
end
- def self.custom_stylesheet(preview_style)
+ def self.custom_stylesheet(preview_style, target=:desktop)
preview_style ||= enabled_style_key
style = lookup_style(preview_style)
- style.stylesheet_link_tag.html_safe if style
+ style.stylesheet_link_tag(target).html_safe if style
end
- def self.custom_header(preview_style)
+ def self.custom_header(preview_style, target=:desktop)
preview_style ||= enabled_style_key
style = lookup_style(preview_style)
- if style && style.header
- style.header.html_safe
+ if style && ((target == :mobile && style.mobile_header) || style.header)
+ target == :mobile ? style.mobile_header.html_safe : style.header.html_safe
else
""
end
@@ -104,7 +111,7 @@ footer:after{ content: '#{error}' }"
@lock.synchronize do
style = where(key: key).first
- style.ensure_stylesheet_on_disk! if style
+ style.ensure_stylesheets_on_disk! if style
@cache[key] = style
end
end
@@ -135,39 +142,49 @@ footer:after{ content: '#{error}' }"
self.class.remove_from_cache!(key)
end
- def stylesheet_hash
- Digest::MD5.hexdigest(stylesheet)
+ def stylesheet_hash(target=:desktop)
+ Digest::MD5.hexdigest( target == :mobile ? mobile_stylesheet : stylesheet )
end
def cache_fullpath
"#{Rails.root}/public/#{CACHE_PATH}"
end
- def ensure_stylesheet_on_disk!
- path = stylesheet_fullpath
- dir = cache_fullpath
- FileUtils.mkdir_p(dir)
- unless File.exists?(path)
- File.open(path, "w") do |f|
- f.puts stylesheet_baked
+ def ensure_stylesheets_on_disk!
+ [[:desktop, 'stylesheet_baked'], [:mobile, 'mobile_stylesheet_baked']].each do |target, baked_attr|
+ path = stylesheet_fullpath(target)
+ dir = cache_fullpath
+ FileUtils.mkdir_p(dir)
+ unless File.exists?(path)
+ File.open(path, "w") do |f|
+ f.puts self.send(baked_attr)
+ end
end
end
end
- def stylesheet_filename
- "/#{self.key}.css"
+ def stylesheet_filename(target=:desktop)
+ target == :desktop ? "/#{self.key}.css" : "/#{target}_#{self.key}.css"
end
- def stylesheet_fullpath
- "#{cache_fullpath}#{stylesheet_filename}"
+ def stylesheet_fullpath(target=:desktop)
+ "#{cache_fullpath}#{stylesheet_filename(target)}"
end
- def stylesheet_link_tag
+ def stylesheet_link_tag(target=:desktop)
+ return mobile_stylesheet_link_tag if target == :mobile
return "" unless stylesheet.present?
return @stylesheet_link_tag if @stylesheet_link_tag
- ensure_stylesheet_on_disk!
+ ensure_stylesheets_on_disk!
@stylesheet_link_tag = ""
end
+
+ def mobile_stylesheet_link_tag
+ return "" unless mobile_stylesheet.present?
+ return @mobile_stylesheet_link_tag if @mobile_stylesheet_link_tag
+ ensure_stylesheets_on_disk!
+ @mobile_stylesheet_link_tag = ""
+ end
end
# == Schema Information
diff --git a/app/views/common/_discourse_stylesheet.html.erb b/app/views/common/_discourse_stylesheet.html.erb
index 168617f6ae5..460ef7a2436 100644
--- a/app/views/common/_discourse_stylesheet.html.erb
+++ b/app/views/common/_discourse_stylesheet.html.erb
@@ -10,6 +10,4 @@
<%= stylesheet_link_tag "admin"%>
<%-end%>
-<% unless mobile_view? %>
- <%= SiteCustomization.custom_stylesheet(session[:preview_style]) %>
-<% end %>
+<%= SiteCustomization.custom_stylesheet(session[:preview_style], mobile_view? ? :mobile : :desktop) %>
diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb
index d47df7d539b..473ac8ab129 100644
--- a/app/views/layouts/application.html.erb
+++ b/app/views/layouts/application.html.erb
@@ -30,9 +30,7 @@
- <% unless mobile_view? %>
- <%= SiteCustomization.custom_header(session[:preview_style]) %>
- <% end %>
+ <%= SiteCustomization.custom_header(session[:preview_style], mobile_view? ? :mobile : :desktop) %>
diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml
index a255634273e..47a5ac557ff 100644
--- a/config/locales/client.en.yml
+++ b/config/locales/client.en.yml
@@ -1166,6 +1166,8 @@ en:
long_title: "Site Customizations"
header: "Header"
css: "Stylesheet"
+ mobile_header: "Mobile Header"
+ mobile_css: "Mobile Stylesheet"
override_default: "Do not include standard style sheet"
enabled: "Enabled?"
preview: "preview"
diff --git a/db/migrate/20130913210454_add_mobile_to_site_customizations.rb b/db/migrate/20130913210454_add_mobile_to_site_customizations.rb
new file mode 100644
index 00000000000..681788ce6e1
--- /dev/null
+++ b/db/migrate/20130913210454_add_mobile_to_site_customizations.rb
@@ -0,0 +1,7 @@
+class AddMobileToSiteCustomizations < ActiveRecord::Migration
+ def change
+ add_column :site_customizations, :mobile_stylesheet, :text
+ add_column :site_customizations, :mobile_header, :text
+ add_column :site_customizations, :mobile_stylesheet_baked, :text
+ end
+end
diff --git a/spec/models/site_customization_spec.rb b/spec/models/site_customization_spec.rb
index f602b1c7621..e40dc9d7e22 100644
--- a/spec/models/site_customization_spec.rb
+++ b/spec/models/site_customization_spec.rb
@@ -6,8 +6,16 @@ describe SiteCustomization do
Fabricate(:user)
end
+ let :customization_params do
+ {name: 'my name', user_id: user.id, header: "my awesome header", stylesheet: "my awesome css", mobile_stylesheet: '', mobile_header: ''}
+ end
+
let :customization do
- SiteCustomization.create!(name: 'my name', user_id: user.id, header: "my awesome header", stylesheet: "my awesome css")
+ SiteCustomization.create!(customization_params)
+ end
+
+ let :customization_with_mobile do
+ SiteCustomization.create!(customization_params.merge(mobile_stylesheet: ".mobile {better: true;}", mobile_header: "fancy mobile stuff"))
end
it 'should set default key when creating a new customization' do
@@ -50,15 +58,46 @@ describe SiteCustomization do
c = customization
c.remove_from_cache!
File.delete(c.stylesheet_fullpath)
+ File.delete(c.stylesheet_fullpath(:mobile))
SiteCustomization.custom_stylesheet(c.key)
File.exists?(c.stylesheet_fullpath).should == true
-
+ File.exists?(c.stylesheet_fullpath(:mobile)).should == true
end
- it 'should allow me to lookup a filename containing my preview stylesheet' do
- SiteCustomization.custom_stylesheet(customization.key).should ==
- ""
+ context '#custom_stylesheet' do
+ it 'should allow me to lookup a filename containing my preview stylesheet' do
+ SiteCustomization.custom_stylesheet(customization.key).should ==
+ ""
+ end
+
+ it "should return blank link tag for mobile if mobile_stylesheet is blank" do
+ SiteCustomization.custom_stylesheet(customization.key, :mobile).should == ""
+ end
+
+ it "should return link tag for mobile custom stylesheet" do
+ SiteCustomization.custom_stylesheet(customization_with_mobile.key, :mobile).should ==
+ ""
+ end
+ end
+
+ context '#custom_header' do
+ it "returns empty string when there is no custom header" do
+ c = SiteCustomization.create!(customization_params.merge(header: ''))
+ SiteCustomization.custom_header(c.key).should == ''
+ end
+
+ it "can return the custom header html" do
+ SiteCustomization.custom_header(customization.key).should == customization_params[:header]
+ end
+
+ it "returns empty string for mobile header when there's no custom mobile header" do
+ SiteCustomization.custom_header(customization.key, :mobile).should == ''
+ end
+
+ it "can return the custom mobile header html" do
+ SiteCustomization.custom_header(customization_with_mobile.key, :mobile).should == customization_with_mobile.mobile_header
+ end
end
it 'should fix stylesheet files after changing the stylesheet' do
@@ -72,13 +111,31 @@ describe SiteCustomization do
SiteCustomization.custom_stylesheet(customization.key).should_not == original
end
+ it 'should fix mobile stylesheet files after changing the mobile_stylesheet' do
+ old_file = customization_with_mobile.stylesheet_fullpath(:mobile)
+ original = SiteCustomization.custom_stylesheet(customization_with_mobile.key, :mobile)
+
+ File.exists?(old_file).should == true
+ customization_with_mobile.mobile_stylesheet = "div { clear:both; }"
+ customization_with_mobile.save
+
+ SiteCustomization.custom_stylesheet(customization_with_mobile.key).should_not == original
+ end
+
it 'should delete old stylesheet files after deleting' do
old_file = customization.stylesheet_fullpath
- customization.ensure_stylesheet_on_disk!
+ customization.ensure_stylesheets_on_disk!
customization.destroy
File.exists?(old_file).should == false
end
+ it 'should delete old mobile stylesheet files after deleting' do
+ old_file = customization_with_mobile.stylesheet_fullpath(:mobile)
+ customization_with_mobile.ensure_stylesheets_on_disk!
+ customization_with_mobile.destroy
+ File.exists?(old_file).should == false
+ end
+
it 'should nuke old revs out of the cache' do
old_style = SiteCustomization.custom_stylesheet(customization.key)
@@ -87,16 +144,35 @@ describe SiteCustomization do
SiteCustomization.custom_stylesheet(customization.key).should_not == old_style
end
+ it 'should nuke old revs out of the cache for mobile too' do
+ old_style = SiteCustomization.custom_stylesheet(customization_with_mobile.key)
+
+ customization_with_mobile.mobile_stylesheet = "hello worldz"
+ customization_with_mobile.save
+ SiteCustomization.custom_stylesheet(customization.key, :mobile).should_not == old_style
+ end
+
it 'should compile scss' do
c = SiteCustomization.create!(user_id: user.id, name: "test", stylesheet: '$black: #000; #a { color: $black; }', header: '')
c.stylesheet_baked.should == "#a {\n color: black; }\n"
end
+ it 'should compile mobile scss' do
+ c = SiteCustomization.create!(user_id: user.id, name: "test", stylesheet: '', header: '', mobile_stylesheet: '$black: #000; #a { color: $black; }', mobile_header: '')
+ c.mobile_stylesheet_baked.should == "#a {\n color: black; }\n"
+ end
+
it 'should provide an awesome error on failure' do
c = SiteCustomization.create!(user_id: user.id, name: "test", stylesheet: "$black: #000; #a { color: $black; }\n\n\nboom", header: '')
-
c.stylesheet_baked.should =~ /Syntax error/
+ c.mobile_stylesheet_baked.should_not be_present
+ end
+
+ it 'should provide an awesome error on failure for mobile too' do
+ c = SiteCustomization.create!(user_id: user.id, name: "test", stylesheet: '', header: '', mobile_stylesheet: "$black: #000; #a { color: $black; }\n\n\nboom", mobile_header: '')
+ c.mobile_stylesheet_baked.should =~ /Syntax error/
+ c.stylesheet_baked.should_not be_present
end
end