Generate JavaScript file file for brand configs

closes: CNVS-34333

things like inst-ui can now just look for a global
variable named `CANVAS_ACTIVE_BRAND_VARIABLES` that
will be present on every page to get all the colors/variables
they need to do theming.

you may need to run:
`bundle exec rake brand_configs:generate_and_upload_all`

to generate these files for all the brands you already
have in your local db for testing this locally.  that rake
task is ran in every deploy so they will get created for all the existing
brand_cofigs in prod/beta

test plan:
* with no brand applied:
* load a page
* view source and make sure there is a script tag something like this:
  <script src="/dist/brandable_css/default/variables-xxxxx.js"></script>
* open your dev console and type:
  console.log(CANVAS_ACTIVE_BRAND_VARIABLES['ic-brand-primary’])
* it should log “#008EE2” (the default canvas brand primary color)

* go to the theme editor and set your “brand primary” to e.g: #629f56
* load a page, and open your dev console and type:
  console.log(CANVAS_ACTIVE_BRAND_VARIABLES['ic-brand-primary’])
* it should log “#629f56”

Change-Id: Ie48d0dbcb8a79429d3d55779efdbf4ef07c636c6
Reviewed-on: https://gerrit.instructure.com/99509
Tested-by: Jenkins
Reviewed-by: Ed Schiebel <eschiebel@instructure.com>
QA-Review: Jeremy Putnam <jeremyp@instructure.com>
Product-Review: Ryan Shaw <ryan@instructure.com>
This commit is contained in:
Ryan Shaw 2017-01-12 16:26:23 -07:00
parent 6bcc5ddbbd
commit 98e45ee75e
8 changed files with 160 additions and 21 deletions

View File

@ -739,6 +739,12 @@ module ApplicationHelper
"#{Canvas::Cdn.config.host}/#{path}"
end
def active_brand_config_js_url(opts={})
path = active_brand_config(opts).try(:public_js_path)
path ||= BrandableCSS.public_default_js_path
"#{Canvas::Cdn.config.host}/#{path}"
end
def brand_config_for_account(opts={})
account = Context.get_account(@context || @course)

View File

@ -101,10 +101,18 @@ class BrandConfig < ActiveRecord::Base
BrandableCSS.all_brand_variable_values(self).to_json
end
def to_js
BrandableCSS.all_brand_variable_values_as_js(self)
end
def json_file
public_brand_dir.join("variables-#{BrandableCSS.default_variables_md5}.json")
end
def js_file
public_brand_dir.join("variables-#{BrandableCSS.default_variables_md5}.js")
end
def scss_dir
BrandableCSS.branded_scss_folder.join(md5)
end
@ -121,6 +129,10 @@ class BrandConfig < ActiveRecord::Base
"#{public_folder}/variables-#{BrandableCSS.default_variables_md5}.json"
end
def public_js_path
"#{public_folder}/variables-#{BrandableCSS.default_variables_md5}.js"
end
def save_scss_file!
logger.info "saving brand variables file: #{scss_file}"
scss_dir.mkpath
@ -128,16 +140,35 @@ class BrandConfig < ActiveRecord::Base
end
def save_json_file!
logger.info "saving brand variables file: #{json_file}"
logger.info "saving brand variables json file: #{json_file}"
public_brand_dir.mkpath
json_file.write(to_json)
move_json_to_s3_if_enabled!
end
def save_js_file!
logger.info "saving brand variables js file: #{js_file}"
public_brand_dir.mkpath
js_file.write(to_js)
move_js_to_s3_if_enabled!
end
def move_json_to_s3_if_enabled!
return unless Canvas::Cdn.enabled?
s3_uploader.upload_file(public_json_path)
File.delete(json_file)
begin
File.delete(json_file)
rescue Errno::ENOENT # continue if something else deleted it in another process
end
end
def move_js_to_s3_if_enabled!
return unless Canvas::Cdn.enabled?
s3_uploader.upload_file(public_js_path)
begin
File.delete(json_file)
rescue Errno::ENOENT # continue if something else deleted it in another process
end
end
def s3_uploader
@ -147,6 +178,7 @@ class BrandConfig < ActiveRecord::Base
def save_all_files!
save_scss_file!
save_json_file!
save_js_file!
end
def remove_scss_dir!

View File

@ -1,3 +1,4 @@
<%= javascript_include_tag(active_brand_config_js_url) %>
<script>
INST = <%= raw(inst_env.to_json) %>;
ENV = <%= raw StringifyIds.recursively_stringify_ids(js_env.clone).to_json %>;

View File

@ -120,6 +120,10 @@ module BrandableCSS
end
end
def all_brand_variable_values_as_js(active_brand_config=nil)
"CANVAS_ACTIVE_BRAND_VARIABLES = #{all_brand_variable_values(active_brand_config).to_json};"
end
def branded_scss_folder
Pathname.new(CONFIG['paths']['branded_scss_folder'])
end
@ -136,20 +140,46 @@ module BrandableCSS
default_brand_folder.join("variables-#{default_variables_md5}.json")
end
def default_brand_js_file
default_brand_folder.join("variables-#{default_variables_md5}.js")
end
def default_json
all_brand_variable_values.to_json
end
def default_js
all_brand_variable_values_as_js
end
def save_default_json!
default_brand_folder.mkpath
default_brand_json_file.write(default_json)
move_default_json_to_s3_if_enabled!
end
def save_default_js!
default_brand_folder.mkpath
default_brand_js_file.write(default_js)
move_default_js_to_s3_if_enabled!
end
def move_default_json_to_s3_if_enabled!
return unless Canvas::Cdn.enabled?
return unless defined?(Canvas) && Canvas::Cdn.enabled?
s3_uploader.upload_file(public_default_json_path)
File.delete(default_brand_json_file)
begin
File.delete(default_brand_json_file)
rescue Errno::ENOENT # continue if something else deleted it in another process
end
end
def move_default_js_to_s3_if_enabled!
return unless defined?(Canvas) && Canvas::Cdn.enabled?
s3_uploader.upload_file(public_default_js_path)
begin
File.delete(default_brand_js_file)
rescue Errno::ENOENT # continue if something else deleted it in another process
end
end
def s3_uploader
@ -160,6 +190,10 @@ module BrandableCSS
"dist/brandable_css/default/variables-#{default_variables_md5}.json"
end
def public_default_js_path
"dist/brandable_css/default/variables-#{default_variables_md5}.js"
end
def variants
@variants ||= CONFIG['variants'].keys.freeze
end

View File

@ -26,6 +26,7 @@ namespace :brand_configs do
task :generate_and_upload_all => :environment do
Rake::Task['brand_configs:clean'].invoke
BrandableCSS.save_default_json!
BrandableCSS.save_default_js!
Rake::Task['brand_configs:write'].invoke
# This'll pick up on all those written brand_configs and compile their css.

View File

@ -10,6 +10,8 @@ namespace :css do
require 'lib/brandable_css'
puts "--> Starting: 'compile css (including custom brands)'"
time = Benchmark.realtime { BrandableCSS.compile_all! }
BrandableCSS.save_default_json!
BrandableCSS.save_default_js!
puts "--> Finished: 'compile css (including custom brands)' in #{time}"
end
end

View File

@ -66,6 +66,13 @@ describe BrandableCSS do
end
end
describe "all_brand_variable_values_as_js" do
it "eports the default js to the right global variable" do
expected_js = "CANVAS_ACTIVE_BRAND_VARIABLES = #{BrandableCSS.default_json};"
expect(BrandableCSS.default_js).to eq expected_js
end
end
describe "default_json" do
it "includes default variables not found in brand config" do
brand_variables = JSON.parse(BrandableCSS.default_json)
@ -73,8 +80,8 @@ describe BrandableCSS do
end
end
describe "save_default_file!" do
it "writes the default json represendation to the default json file" do
describe "save_default_json!" do
it "writes the default json representation to the default json file" do
Canvas::Cdn.stubs(:enabled?).returns(false)
file = StringIO.new
BrandableCSS.stubs(:default_brand_json_file).returns(file)
@ -82,7 +89,7 @@ describe BrandableCSS do
expect(file.string).to eq BrandableCSS.default_json
end
it 'uploads file to s3 if cdn is enabled' do
it 'uploads json file to s3 if cdn is enabled' do
Canvas::Cdn.stubs(:enabled?).returns(true)
Canvas::Cdn.stubs(:config).returns(ActiveSupport::OrderedOptions.new.merge(region: 'us-east-1'))
@ -93,7 +100,7 @@ describe BrandableCSS do
BrandableCSS.save_default_json!
end
it 'delete the local file if cdn is enabled' do
it 'deletes the local json file if cdn is enabled' do
Canvas::Cdn.stubs(:enabled?).returns(true)
Canvas::Cdn.stubs(:config).returns(ActiveSupport::OrderedOptions.new.merge(region: 'us-east-1'))
file = StringIO.new
@ -103,4 +110,35 @@ describe BrandableCSS do
BrandableCSS.save_default_json!
end
end
describe "save_default_js!" do
it "writes the default javascript representation to the default js file" do
Canvas::Cdn.stubs(:enabled?).returns(false)
file = StringIO.new
BrandableCSS.stubs(:default_brand_js_file).returns(file)
BrandableCSS.save_default_js!
expect(file.string).to eq BrandableCSS.default_js
end
it 'uploads javascript file to s3 if cdn is enabled' do
Canvas::Cdn.stubs(:enabled?).returns(true)
Canvas::Cdn.stubs(:config).returns(ActiveSupport::OrderedOptions.new.merge(region: 'us-east-1'))
file = StringIO.new
BrandableCSS.stubs(:default_brand_js_file).returns(file)
File.stubs(:delete)
BrandableCSS.s3_uploader.expects(:upload_file).with(BrandableCSS.public_default_js_path)
BrandableCSS.save_default_js!
end
it 'delete the local javascript file if cdn is enabled' do
Canvas::Cdn.stubs(:enabled?).returns(true)
Canvas::Cdn.stubs(:config).returns(ActiveSupport::OrderedOptions.new.merge(region: 'us-east-1'))
file = StringIO.new
BrandableCSS.stubs(:default_brand_js_file).returns(file)
File.expects(:delete).with(BrandableCSS.default_brand_js_file)
BrandableCSS.s3_uploader.expects(:upload_file)
BrandableCSS.save_default_js!
end
end
end

View File

@ -106,31 +106,48 @@ describe BrandConfig do
end
end
describe "to_js" do
before :once do
setup_subaccount_with_config
end
it "exports to the correct global variable" do
expect(@subaccount_bc.to_js).to eq "CANVAS_ACTIVE_BRAND_VARIABLES = #{@subaccount_bc.to_json};"
end
end
describe "save_all_files!" do
before :once do
setup_subaccount_with_config
end
before :each do
before do
@json_file = StringIO.new
@js_file = StringIO.new
@scss_file = StringIO.new
@subaccount_bc.stubs(:json_file).returns(@json_file)
@subaccount_bc.stubs(:js_file).returns(@js_file)
@subaccount_bc.stubs(:scss_file).returns(@scss_file)
end
describe "with cdn disabled" do
before :each do
Canvas::Cdn.expects(:enabled?).returns(false)
before do
Canvas::Cdn.expects(:enabled?).at_least_once.returns(false)
@subaccount_bc.expects(:s3_uploader).never
File.expects(:delete).never
end
it "writes the json represendation to the json file" do
it "writes the json representation to the json file" do
@subaccount_bc.save_all_files!
expect(@json_file.string).to eq @subaccount_bc.to_json
end
it "writes the scss represendation to scss file" do
it "writes the JavaScript representation to the js file" do
@subaccount_bc.save_all_files!
expect(@js_file.string).to eq "CANVAS_ACTIVE_BRAND_VARIABLES = #{@subaccount_bc.to_json};"
end
it "writes the scss representation to scss file" do
@subaccount_bc.save_all_files!
expect(@scss_file.string).to eq @subaccount_bc.to_scss
end
@ -138,25 +155,33 @@ describe BrandConfig do
describe "with cdn enabled" do
before :each do
Canvas::Cdn.expects(:enabled?).returns(true)
Canvas::Cdn.expects(:enabled?).at_least_once.returns(true)
s3 = stub(bucket: nil)
Aws::S3::Resource.stubs(:new).returns(s3)
@upload_expectation = @subaccount_bc.s3_uploader.expects(:upload_file).once
@delete_expectation = File.expects(:delete).once
@upload_expectation = @subaccount_bc.s3_uploader.expects(:upload_file).twice
@delete_expectation = File.expects(:delete).twice
end
it "writes the json represendation to the json file" do
it "writes the json representation to the json file" do
@subaccount_bc.save_all_files!
expect(@json_file.string).to eq @subaccount_bc.to_json
end
it 'uploads json file to s3 if cdn enabled' do
@upload_expectation.with(@subaccount_bc.public_json_path)
it "writes the javascript representation to the js file" do
@subaccount_bc.save_all_files!
expect(@js_file.string).to eq @subaccount_bc.to_js
end
it 'uploads json & js file to s3' do
@upload_expectation.with(any_of(
@subaccount_bc.public_json_path,
@subaccount_bc.public_js_path
))
@subaccount_bc.save_all_files!
end
it 'deletes local json file if cdn enabled' do
@delete_expectation.with(@subaccount_bc.json_file)
it 'deletes local json & js file when its done' do
@delete_expectation.with(@subaccount_bc.js_file).then.with(@subaccount_bc.json_file)
@subaccount_bc.save_all_files!
end
end