From fc184a7cea4821055a17f938c7cbff1360e56b5f Mon Sep 17 00:00:00 2001 From: Harry Bomrah Date: Fri, 19 Dec 2014 17:14:31 +0800 Subject: [PATCH 01/19] fix for members category --- app/controllers/pages_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/pages_controller.rb b/app/controllers/pages_controller.rb index b243590..9f3c149 100644 --- a/app/controllers/pages_controller.rb +++ b/app/controllers/pages_controller.rb @@ -89,8 +89,8 @@ class PagesController < ApplicationController categories << c end end + categories = ["all"] if categories.blank? end - categories = ["all"] if categories.blank? @manifest = @key OrbitHelper.set_params params,current_user OrbitHelper.set_site_locale locale From e3e15a1ef2b74951664084aa84242cc965399a84 Mon Sep 17 00:00:00 2001 From: Harry Bomrah Date: Fri, 19 Dec 2014 17:53:24 +0800 Subject: [PATCH 02/19] fix for all members --- app/controllers/pages_controller.rb | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/app/controllers/pages_controller.rb b/app/controllers/pages_controller.rb index 9f3c149..48ef10f 100644 --- a/app/controllers/pages_controller.rb +++ b/app/controllers/pages_controller.rb @@ -76,10 +76,14 @@ class PagesController < ApplicationController params[:url] = page.url categories = [] if page.module == "member" - page.categories.each do |c| - category = Role.find(c) rescue nil - if !category.nil? && !category.disabled - categories << c + if page.categories.first == "all" + categories = ["all"] + else + page.categories.each do |c| + category = Role.find(c) rescue nil + if !category.nil? && !category.disabled + categories << c + end end end else From 71ea2eb2dd5f7cc2e5b8e64eb7114a71e558f11b Mon Sep 17 00:00:00 2001 From: JiangRu Date: Fri, 26 Dec 2014 10:26:40 +0800 Subject: [PATCH 03/19] fix menu tag --- app/controllers/pages_controller.rb | 46 +++++++++++++---------------- 1 file changed, 21 insertions(+), 25 deletions(-) diff --git a/app/controllers/pages_controller.rb b/app/controllers/pages_controller.rb index 48ef10f..5cfca10 100644 --- a/app/controllers/pages_controller.rb +++ b/app/controllers/pages_controller.rb @@ -11,7 +11,7 @@ class PagesController < ApplicationController before_filter :set_edit_mode def index - @pages = Page.all + @pages = Page.all # render json: @pages end @@ -75,26 +75,13 @@ class PagesController < ApplicationController end params[:url] = page.url categories = [] - if page.module == "member" - if page.categories.first == "all" - categories = ["all"] - else - page.categories.each do |c| - category = Role.find(c) rescue nil - if !category.nil? && !category.disabled - categories << c - end - end + page.categories.each do |c| + category = Category.find(c) rescue nil + if !category.nil? && !category.disable + categories << c end - else - page.categories.each do |c| - category = Category.find(c) rescue nil - if !category.nil? && !category.disable - categories << c - end - end - categories = ["all"] if categories.blank? end + categories = ["all"] if categories.blank? @manifest = @key OrbitHelper.set_params params,current_user OrbitHelper.set_site_locale locale @@ -190,30 +177,38 @@ class PagesController < ApplicationController "id" => cat.id.to_s } end + tags = module_app.tags.collect do |t| + { + "name" => t.name, + "id" => t.id.to_s + } + end else categories = [] + tags = [] end end roles = roles.nil? ? [] : roles categories = categories.nil? ? [] : categories + tags = tags.nil? ? [] : tags if module_app.data_count.nil? - render :json => {"categories" => categories, "tags" => module_app.tags,"roles" => roles,"layouts" => (get_layouts module_app.key),"data_count" => {"present"=>false}, "locale" => I18n.locale.to_s}.to_json + render :json => {"categories" => categories, "tags" => tags,"roles" => roles,"layouts" => (get_layouts module_app.key),"data_count" => {"present"=>false}, "locale" => I18n.locale.to_s}.to_json else - render :json => {"categories" => categories, "tags" => module_app.tags,"roles" => roles,"layouts" => (get_layouts module_app.key),"data_count" => {"present"=>true,"start"=>module_app.data_count.begin, "end" => module_app.data_count.end}, "locale" => I18n.locale.to_s}.to_json + render :json => {"categories" => categories, "tags" => tags,"roles" => roles,"layouts" => (get_layouts module_app.key),"data_count" => {"present"=>true,"start"=>module_app.data_count.begin, "end" => module_app.data_count.end}, "locale" => I18n.locale.to_s}.to_json end end def new - @page = Page.new( + @page = Page.new( :enabled_for_mobile=>true, :menu_enabled_for=>["en", "zh_tw"], :enabled_for=>["en", "zh_tw"], :enabled_for_sitemap=>["en", "zh_tw"] ) - @pages = Page.where(:page_id.ne => "" , :page_id.exists => true) - @modules = ModuleApp.all.frontend_enabled.order_by(:key=>'asc') + @pages = Page.where(:page_id.ne => "" , :page_id.exists => true) + @modules = ModuleApp.all.frontend_enabled.order_by(:key=>'asc') end @@ -264,7 +259,7 @@ class PagesController < ApplicationController end end - private + private def get_layouts(module_app) layout_types = [] @@ -436,6 +431,7 @@ class PagesController < ApplicationController p = params.require(:page).permit(:number, :page_type, :page_id, :module, :layout, :parent_page, :data_count, :enabled_for_mobile, :member_sort_position, enabled_for_sitemap: [], enabled_for: [],menu_enabled_for: [], categories: [], tags: [], role_status: [], name_translations: valid_locales, external_url_translations: valid_locales) p["role_status"] = p["role_status"] || [] p["categories"] = p["categories"] || [] + p["tags"] = p["tags"] || [] p["enabled_for"] = p["enabled_for"] || [] p["menu_enabled_for"] = p["menu_enabled_for"] || [] p["enabled_for_sitemap"] = p["enabled_for_sitemap"] || [] From 207fc9c0f83bdd8903b1b348630f4a198bd0844e Mon Sep 17 00:00:00 2001 From: JiangRu Date: Fri, 26 Dec 2014 16:20:47 +0800 Subject: [PATCH 04/19] fix member plugin intro or complete list & fix journal all author --- app/controllers/admin/import_controller.rb | 6 ++- app/controllers/members_controller.rb | 46 ++++++++++++++-------- 2 files changed, 35 insertions(+), 17 deletions(-) diff --git a/app/controllers/admin/import_controller.rb b/app/controllers/admin/import_controller.rb index e427eca..563e3a9 100644 --- a/app/controllers/admin/import_controller.rb +++ b/app/controllers/admin/import_controller.rb @@ -1040,7 +1040,11 @@ class Admin::ImportController < OrbitAdminController :paper_title_translations => { "en" => rss2_journal["paper_title"]["en"], - "zh_tw" => rss2_journal["paper_title"]["zh-tw"]} + "zh_tw" => rss2_journal["paper_title"]["zh-tw"]}, + + :authors_translations => { + "en" => rss2_journal["author"], + "zh_tw" => rss2_journal["author"]} } journal = JournalPaper.where(:rss2_id => rss2_journal["rss_id"]).first diff --git a/app/controllers/members_controller.rb b/app/controllers/members_controller.rb index 13cb49d..aba6008 100644 --- a/app/controllers/members_controller.rb +++ b/app/controllers/members_controller.rb @@ -139,29 +139,44 @@ class MembersController < ApplicationController plugins = OrbitApp::Plugin::Registration.all rescue nil plugin_list = plugins.collect.with_index do |plugin, idx| intro = PersonalPluginIntro.find_by(member_profile_id: member.id, _type: "#{plugin.app_name}Intro") rescue nil - if intro.nil? or intro.complete_list - plugin_data = plugin.app_name.constantize.where(member_profile_id: member) rescue nil - pd = plugin_data.collect do |p| - slug_title = ["JournalPaper","WritingConference"].include?(plugin.app_name) ? p.create_link : p.slug_title - { - "data_title" => slug_title, - "link_to_show" => OrbitHelper.url_to_plugin_show(p.to_param,plugin.module_app_name.underscore) - } + if !intro.blank? + if !intro.complete_list.blank? + plugin_data = plugin.app_name.constantize.where(member_profile_id: member) rescue nil + pd = plugin_data.collect do |p| + slug_title = ["JournalPaper","WritingConference"].include?(plugin.app_name) ? p.create_link : p.slug_title + { + "data_title" => slug_title, + "link_to_show" => OrbitHelper.url_to_plugin_show(p.to_param,plugin.module_app_name.underscore) + } + end end - elsif intro.brief_intro == true - pd = [] - pd << {"data_title" => intro.text.html_safe} - end - { + if !intro.brief_intro.blank? + pdi = [] + pdi << {"data_intro_title" => intro.text.html_safe} + end + + if intro.complete_list.blank? + complete_display = "hide" + end + + if intro.brief_intro.blank? + brief_display = "hide" + end + end + + { "plugin_data" => pd, + "plugin_data_intro" => pdi, + "complete_display" => complete_display, + "brief_display" => brief_display, "plugin_name" => plugin.module_app_name.underscore, "plugin_title" => t('module_name.'+plugin.module_app_name.underscore), "plugin_class" => idx==0 ? "active" : "" - } + } end - plugin_list = plugin_list.reject{|plugin| plugin['plugin_data'].blank?} + plugin_list = plugin_list.reject{|plugin| plugin['plugin_data'].blank? and plugin['plugin_data_intro'].blank?} { "plugins" => plugin_list, "profile_data" => profile_data, @@ -175,7 +190,6 @@ class MembersController < ApplicationController def member_data(member, fields_to_show) profile_data = [] fields_to_show.each do |field| - # debugger case field['type'] when 'profile' field_data = member.get_attribute_data(field) rescue {} From aac913514959b5685f8473d9428a5bf37bbe51e9 Mon Sep 17 00:00:00 2001 From: JiangRu Date: Fri, 26 Dec 2014 16:23:51 +0800 Subject: [PATCH 05/19] member plugin front page show --- app/templates/orbit_bootstrap/modules/member/show.html.erb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/templates/orbit_bootstrap/modules/member/show.html.erb b/app/templates/orbit_bootstrap/modules/member/show.html.erb index df04c1f..62f7a3b 100644 --- a/app/templates/orbit_bootstrap/modules/member/show.html.erb +++ b/app/templates/orbit_bootstrap/modules/member/show.html.erb @@ -19,8 +19,11 @@
+ + + - +
{{data_intro_title}}
{{data_title}}
{{data_title}}
From 4575fce2a98af927c52d3a71ae255dd5e219338f Mon Sep 17 00:00:00 2001 From: Harry Bomrah Date: Fri, 26 Dec 2014 16:55:28 +0800 Subject: [PATCH 06/19] counter added and also some changes for store --- Gemfile | 2 +- app/assets/javascripts/validator.js | 57 +++++++++++-------- app/controllers/admin/sites_controller.rb | 4 +- app/controllers/store_api_controller.rb | 48 ++++++++++++++++ app/helpers/application_helper.rb | 2 + .../orbit_bootstrap/home/footer.html.erb | 1 + config/routes.rb | 1 + 7 files changed, 88 insertions(+), 27 deletions(-) diff --git a/Gemfile b/Gemfile index fd3868a..dda513e 100644 --- a/Gemfile +++ b/Gemfile @@ -34,7 +34,7 @@ gem 'mongoid', github: "mongoid/mongoid" gem "mini_magick", "3.5.0" gem 'carrierwave' gem 'carrierwave-mongoid', :require => 'carrierwave/mongoid' - +gem 'zip-zip' gem 'kaminari' gem "impressionist" gem "chartkick" diff --git a/app/assets/javascripts/validator.js b/app/assets/javascripts/validator.js index 847a6d4..89c653a 100644 --- a/app/assets/javascripts/validator.js +++ b/app/assets/javascripts/validator.js @@ -25,7 +25,10 @@ var FormValidator = function(form){ nospace : function(value){ return (/\s/.test(value) ? false : true); }, - email : function(value){ + lowercase : function(value){ + return (value == value.toLowerCase() ? true : false); + }, + email : function(){ var re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; return re.test(value); } @@ -40,35 +43,39 @@ var FormValidator = function(form){ var _attachSubmitHandler = function(){ fv.form.on("submit",function(){ - failed_elements = []; - $.each(elements_data,function(key,element){ - var validators = element.validators, - messages = element.messages, - el = fv.form.find("#" + key); - for(i = 0; i < validators.length; i++){ - var error_span = (fv.form.find("div[for=" + key + "]").length ? $("div[for=" + key + "]") : $("
")); - if(typeof fv.validate_functions[validators[i]] == "function"){ - if(!fv.validate_functions[validators[i]](el.val(),el)){ - error_span.text(messages[i]); - el.after(error_span); - failed_elements.push(el); - break; - }else{ - error_span.remove(); - } + return fv.isFormValidated(); + }) + } + + this.isFormValidated = function(){ + failed_elements = []; + $.each(elements_data,function(key,element){ + var validators = element.validators, + messages = element.messages, + el = fv.form.find("#" + key); + for(i = 0; i < validators.length; i++){ + var error_span = (fv.form.find("div[for=" + key + "]").length ? $("div[for=" + key + "]") : $("
")); + if(typeof fv.validate_functions[validators[i]] == "function"){ + if(!fv.validate_functions[validators[i]](el.val(),el)){ + error_span.text(messages[i]); + el.after(error_span); + failed_elements.push(el); + break; }else{ - console.info("Not validating for " + validators[i] + ". Skipping."); + error_span.remove(); } + }else{ + console.info("Not validating for " + validators[i] + ". Skipping."); } - }) - if(failed_elements.length){ - var offset = failed_elements[0].offset().top - fv.form.offset().top + fv.form.scrollTop(); - fv.form.parent().animate({scrollTop:offset-50}, '300', 'swing'); - return false; - }else{ - return true; } }) + if(failed_elements.length){ + var offset = failed_elements[0].offset().top - fv.form.offset().top + fv.form.scrollTop(); + fv.form.parent().animate({scrollTop:offset-50}, '300', 'swing'); + return false; + }else{ + return true; + } } var _putFieldsValidatorAndMessage = function(){ diff --git a/app/controllers/admin/sites_controller.rb b/app/controllers/admin/sites_controller.rb index 87175db..eb9c299 100644 --- a/app/controllers/admin/sites_controller.rb +++ b/app/controllers/admin/sites_controller.rb @@ -106,7 +106,9 @@ class Admin::SitesController < OrbitAdminController else result = "success" # Bundler.with_clean_env { `cd #{Rails.root} && bundle update` } - Bundler.with_clean_env { `cd #{Rails.root} && BUNDLE_GEMFILE=built_in_extensions.rb bundle update && bundle` } + Bundler.with_clean_env { `cd #{Rails.root} && BUNDLE_GEMFILE=built_in_extensions.rb bundle update && bundle` } + Bundler.with_clean_env { `cd #{Rails.root} && BUNDLE_GEMFILE=downloaded_extensions.rb bundle update && bundle` } + end render :text => result diff --git a/app/controllers/store_api_controller.rb b/app/controllers/store_api_controller.rb index 50eb645..b526e54 100644 --- a/app/controllers/store_api_controller.rb +++ b/app/controllers/store_api_controller.rb @@ -1,3 +1,6 @@ +require "net/http" +require 'open-uri' +require 'zip/zip' class StoreApiController < ApplicationController def confirmation site_token = params[:site_token] @@ -11,4 +14,49 @@ class StoreApiController < ApplicationController render :json => {"success" => false}.to_json end end + + def install_module + file = File.join(Rails.root,"downloaded_extensions.rb") + g = "gem '#{params[:module_key]}', git: '#{params[:git_path]}'" + File.open(file,"a+") { |f| f.puts(g) } + if !directory_exists?(File.join(Rails.root,"app","templates","#{Site.first.template}","modules","#{params[:module_key]}")) + download_template(params[:template],params[:template_filename]) + end + bundle_install + render :json => {"success" => true} .to_json + end + + private + def bundle_install + Bundler.with_clean_env { `cd #{Rails.root} && BUNDLE_GEMFILE=downloaded_extensions.rb bundle update && bundle` } + %x(kill -s USR2 `cat tmp/pids/unicorn.pid`) + sleep 5 + end + + def download_template(url,name) + dir = File.join(Rails.root,"public","template_cache") + destination = File.join(Rails.root,"app","templates","#{Site.first.template}","modules") + if !directory_exists?(dir) + Dir.mkdir dir + end + zipfile = File.join(Rails.root, "public" , "template_cache", name) + open(zipfile, 'wb') do |fo| + fo.print open(url).read + end + unzip_file(zipfile,destination) + end + + def directory_exists?(directory) + File.directory?(directory) + end + + def unzip_file (file, destination) + Zip::ZipFile.open(file) { |zip_file| + zip_file.each { |f| + f_path=File.join(destination, f.name) + FileUtils.mkdir_p(File.dirname(f_path)) + zip_file.extract(f, f_path) unless File.exist?(f_path) + } + } + end end \ No newline at end of file diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 624d2f5..7d1f857 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -64,6 +64,8 @@ module ApplicationHelper end site_footer = site_footer.nil? ? "" : site_footer html = html.gsub("{{footer-data}}",site_footer) + counter = Page.root.view_count.to_s rescue "" + html = html.gsub("{{site-counter}}",counter) html.html_safe end diff --git a/app/templates/orbit_bootstrap/home/footer.html.erb b/app/templates/orbit_bootstrap/home/footer.html.erb index 76aa7cc..110eb8f 100644 --- a/app/templates/orbit_bootstrap/home/footer.html.erb +++ b/app/templates/orbit_bootstrap/home/footer.html.erb @@ -1,5 +1,6 @@
\ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index cd62b5e..2da0372 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -27,6 +27,7 @@ Orbit::Application.routes.draw do get "/module/:name" => "home#index" get "/module/:name/show" => "home#show" post "/store/confirmation" => "store_api#confirmation" + post "/store/install_module" => "store_api#install_module" # The priority is based upon order of creation: first created -> highest priority. # See how all your routes lay out with "rake routes". From c8d395aca1a0d08b321c64334023e904497bd21c Mon Sep 17 00:00:00 2001 From: Harry Bomrah Date: Sun, 28 Dec 2014 14:43:34 +0800 Subject: [PATCH 07/19] fixed tags and also some store commits --- app/assets/javascripts/validator.js | 2 +- .../lib/orbit_bar/orbit-bar.scss.erb | 6 +++- .../admin/module_store_controller.rb | 2 +- app/controllers/store_api_controller.rb | 30 +++++++++++++++---- app/helpers/orbit_helper.rb | 4 +-- config/routes.rb | 1 + 6 files changed, 34 insertions(+), 11 deletions(-) diff --git a/app/assets/javascripts/validator.js b/app/assets/javascripts/validator.js index 89c653a..435d4d7 100644 --- a/app/assets/javascripts/validator.js +++ b/app/assets/javascripts/validator.js @@ -28,7 +28,7 @@ var FormValidator = function(form){ lowercase : function(value){ return (value == value.toLowerCase() ? true : false); }, - email : function(){ + email : function(value){ var re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; return re.test(value); } diff --git a/app/assets/stylesheets/lib/orbit_bar/orbit-bar.scss.erb b/app/assets/stylesheets/lib/orbit_bar/orbit-bar.scss.erb index 384cbd5..d3c4639 100644 --- a/app/assets/stylesheets/lib/orbit_bar/orbit-bar.scss.erb +++ b/app/assets/stylesheets/lib/orbit_bar/orbit-bar.scss.erb @@ -334,7 +334,7 @@ $orbit-bar-bgc-lighter: lighten($orbit-bar-bgc, 20%) !default; display: none; top: 0; margin: 0 2em; - padding: 0.3em 0; + padding: 0; color: #FFF; font-size: 1.4em; text-align: center; @@ -344,6 +344,9 @@ $orbit-bar-bgc-lighter: lighten($orbit-bar-bgc, 20%) !default; a { color: #FFF; } + .page-main & { + padding: 0.3em 0; + } } .orbit-bar-search-sign-language { float: right; @@ -355,6 +358,7 @@ $orbit-bar-bgc-lighter: lighten($orbit-bar-bgc, 20%) !default; input[type="search"] { color: $orbit-bar-bgc-lighter; border: none; + margin-bottom: 0; border-radius: 1.7em; line-height: 1.3em; padding: 0.2em 0.8em; diff --git a/app/controllers/admin/module_store_controller.rb b/app/controllers/admin/module_store_controller.rb index c6ac85f..7385bbd 100644 --- a/app/controllers/admin/module_store_controller.rb +++ b/app/controllers/admin/module_store_controller.rb @@ -3,7 +3,7 @@ class Admin::ModuleStoreController < OrbitAdminController def index @extensions = [] - @downloaded_extensions = get_downloaded_extension + @downloaded_extensions = [] # if current_site.site_token? # if current_site.store_confirmation # @extensions = get_extensions diff --git a/app/controllers/store_api_controller.rb b/app/controllers/store_api_controller.rb index b526e54..a5c5d81 100644 --- a/app/controllers/store_api_controller.rb +++ b/app/controllers/store_api_controller.rb @@ -16,14 +16,31 @@ class StoreApiController < ApplicationController end def install_module - file = File.join(Rails.root,"downloaded_extensions.rb") - g = "gem '#{params[:module_key]}', git: '#{params[:git_path]}'" - File.open(file,"a+") { |f| f.puts(g) } - if !directory_exists?(File.join(Rails.root,"app","templates","#{Site.first.template}","modules","#{params[:module_key]}")) - download_template(params[:template],params[:template_filename]) + if current_site.store_token.nil? + response = {"success" => false} + elsif current_site.store_token == params[:site_token] + file = File.join(Rails.root,"downloaded_extensions.rb") + g = "gem '#{params[:module_key]}', git: '#{params[:git_path]}'" + File.open(file,"a+") { |f| f.puts(g) } + if !directory_exists?(File.join(Rails.root,"app","templates","#{Site.first.template}","modules","#{params[:module_key]}")) + download_template(params[:template],params[:template_filename]) + end + response = {"success" => true} + else + response = {"success" => false} end + render :json => response.to_json + bundle_install if response["success"] + end + + def uninstall_module + file = File.join(Rails.root,"downloaded_extensions.rb") + data = File.read(file) + g = "gem '#{params[:module_key]}', git: '#{params[:git_path]}'\n" + data = data.gsub(g,"") + File.write(file,data) bundle_install - render :json => {"success" => true} .to_json + render :json => {"success" => true}.to_json end private @@ -58,5 +75,6 @@ class StoreApiController < ApplicationController zip_file.extract(f, f_path) unless File.exist?(f_path) } } + FileUtils.rm_rf(File.join(Rails.root,"public","template_cache")) end end \ No newline at end of file diff --git a/app/helpers/orbit_helper.rb b/app/helpers/orbit_helper.rb index cd133a6..c23e2d6 100644 --- a/app/helpers/orbit_helper.rb +++ b/app/helpers/orbit_helper.rb @@ -136,11 +136,11 @@ module OrbitHelper end def self.set_widget_tags(tags) - @tags = tags; + @widget_tags = tags; end def self.widget_tags - @tags + @widget_tags end def self.user_can_edit?(obj) diff --git a/config/routes.rb b/config/routes.rb index 2da0372..8d95df9 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -28,6 +28,7 @@ Orbit::Application.routes.draw do get "/module/:name/show" => "home#show" post "/store/confirmation" => "store_api#confirmation" post "/store/install_module" => "store_api#install_module" + post "/store/uninstall_module" => "store_api#uninstall_module" # The priority is based upon order of creation: first created -> highest priority. # See how all your routes lay out with "rake routes". From 6e27bbd4839613fa11130f489b0874c1cd577017 Mon Sep 17 00:00:00 2001 From: Harry Bomrah Date: Tue, 30 Dec 2014 18:38:11 +0800 Subject: [PATCH 08/19] module store changes --- app/controllers/store_api_controller.rb | 4 ++ app/helpers/orbit_backend_helper.rb | 11 ++++- app/models/module_app.rb | 1 + app/models/orbit_store.rb | 1 + .../store_api/render_license_denied.html.erb | 2 + config/environment.rb | 1 + config/routes.rb | 5 ++- lib/orbit_app/helper/side_bar_renderer.rb | 28 +++++++++---- lib/orbit_app/register_module.rb | 41 +++++++++++++++++++ lib/orbit_core_lib.rb | 6 ++- lib/tasks/register_with_store.rake | 24 +++++++++++ 11 files changed, 110 insertions(+), 14 deletions(-) create mode 100644 app/views/store_api/render_license_denied.html.erb create mode 100644 lib/tasks/register_with_store.rake diff --git a/app/controllers/store_api_controller.rb b/app/controllers/store_api_controller.rb index a5c5d81..d35c175 100644 --- a/app/controllers/store_api_controller.rb +++ b/app/controllers/store_api_controller.rb @@ -43,6 +43,10 @@ class StoreApiController < ApplicationController render :json => {"success" => true}.to_json end + def render_license_denied + render :layout => "back_end" + end + private def bundle_install Bundler.with_clean_env { `cd #{Rails.root} && BUNDLE_GEMFILE=downloaded_extensions.rb bundle update && bundle` } diff --git a/app/helpers/orbit_backend_helper.rb b/app/helpers/orbit_backend_helper.rb index 73734d2..25eb17a 100644 --- a/app/helpers/orbit_backend_helper.rb +++ b/app/helpers/orbit_backend_helper.rb @@ -172,8 +172,15 @@ module OrbitBackendHelper http = Net::HTTP.new(uri.host,uri.port) request = Net::HTTP::Get.new("/site/permissions") request.body = params_to_send.to_query - response = http.request(request) - data = JSON.parse(response.body) + response = http.request(request) rescue nil + if response.nil? + data = {} + data["message"] = "Could not connect to the store." + data["error"] = "CONNECTION_REFUSED" + data["success"] = false + else + data = JSON.parse(response.body) + end if !data["success"] case data["error"] when "INVALID_SITE_TOKEN" diff --git a/app/models/module_app.rb b/app/models/module_app.rb index cd1d4a1..efee743 100644 --- a/app/models/module_app.rb +++ b/app/models/module_app.rb @@ -14,6 +14,7 @@ class ModuleApp field :widget_methods field :desktop_enabled, type: Boolean, default: false field :widget_settings + field :store_permission_granted, type: Boolean, default: false has_many :categories, dependent: :destroy, :autosave => true has_and_belongs_to_many :tags, dependent: :destroy, :autosave => true diff --git a/app/models/orbit_store.rb b/app/models/orbit_store.rb index 9c9b64f..1217dc2 100644 --- a/app/models/orbit_store.rb +++ b/app/models/orbit_store.rb @@ -1,3 +1,4 @@ class OrbitStore URL = "http://store.tp.rulingcom.com" + MODULE_EXCEPTIONS = ["category","tag","authorization"] end \ No newline at end of file diff --git a/app/views/store_api/render_license_denied.html.erb b/app/views/store_api/render_license_denied.html.erb new file mode 100644 index 0000000..702732d --- /dev/null +++ b/app/views/store_api/render_license_denied.html.erb @@ -0,0 +1,2 @@ +

License Denied.

+

Please contact www.rulingdigital.com.

\ No newline at end of file diff --git a/config/environment.rb b/config/environment.rb index a176bdd..437818a 100644 --- a/config/environment.rb +++ b/config/environment.rb @@ -5,6 +5,7 @@ require File.expand_path('../application', __FILE__) Orbit::Application.initialize! Orbit::Application.config.secret_key_base = 'acc6ffc5a7d360c9cf2a7bdb4ddf9a897942ec6767413a5c0324a0fa8b86197a96298288a66bd46d8770d8b6edf509aad65716961c2c364ce006b475e6cfd418' OrbitApp.cleanup_modules +OrbitApp.check_module_permissions if Site.count == 0 site = Site.new diff --git a/config/routes.rb b/config/routes.rb index 8d95df9..266d912 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -16,6 +16,7 @@ Orbit::Application.routes.draw do get "/page_parts/getwidgets" => "page_parts#getwidgets" get "/page_parts/info" => "page_parts#info" get "/page_parts/edit_sub_part" => "page_parts#edit_sub_part" + get "/admin/license_denied" => "store_api#render_license_denied" resources :pages resources :page_parts do @@ -95,7 +96,7 @@ Orbit::Application.routes.draw do get "members/get_role_fields/:id" => "members#get_role_fields", :as => :get_role_fields get "members/import_members" => "members#import_members" - get "members/unapproved_members" => "members#unapproved_members" + get "members/unapproved_members" => "members#unapproved_members" resources :members do collection do @@ -197,7 +198,7 @@ Orbit::Application.routes.draw do get 'check_updates' get 'update_orbit' get 'restart_server' - get 'delete_mail_log' + get 'delete_mail_log' end resources :designs do diff --git a/lib/orbit_app/helper/side_bar_renderer.rb b/lib/orbit_app/helper/side_bar_renderer.rb index e4fe6a9..ed4fecd 100644 --- a/lib/orbit_app/helper/side_bar_renderer.rb +++ b/lib/orbit_app/helper/side_bar_renderer.rb @@ -13,12 +13,14 @@ module SideBarRenderer @app_available_for = af if display? content_tag :div, class: "sub-nav-block #{@icon_class}" do - concat content_tag :h4, I18n.t(@head_label) - concat (content_tag :ul, class: "nav nav-list" do - @context_links.sort_by {| obj | obj.priority}.map{ |link| - link.render(request, params, @current_module_app, @current_user, @belong_module_app, link.get_active_action, link.available_for) - }.join.html_safe - end) + if @belong_module_app.store_permission_granted + concat content_tag :h4, I18n.t(@head_label) + concat (content_tag :ul, class: "nav nav-list" do + @context_links.sort_by {| obj | obj.priority}.map{ |link| + link.render(request, params, @current_module_app, @current_user, @belong_module_app, link.get_active_action, link.available_for) + }.join.html_safe + end) + end end end end @@ -33,9 +35,17 @@ module SideBarRenderer @app_available_for = available_for if display? content_tag :li, class: (module_sidebar_active? ? 'active' : nil) do - link_to Rails.application.routes.url_helpers.send(@head_link) do - content_tag :span do - content_tag(:i, nil, class: @icon_class) + if @belong_module_app.store_permission_granted + link_to Rails.application.routes.url_helpers.send(@head_link) do + content_tag :span do + content_tag(:i, nil, class: @icon_class) + end + end + else + link_to "/admin/license_denied" do + content_tag :span do + content_tag(:i, nil, class: @icon_class + " text-error") + end end end end diff --git a/lib/orbit_app/register_module.rb b/lib/orbit_app/register_module.rb index 44797d7..ad019fd 100644 --- a/lib/orbit_app/register_module.rb +++ b/lib/orbit_app/register_module.rb @@ -20,5 +20,46 @@ module OrbitApp end end end + + def check_module_permissions + store_token = Site.first.store_token + module_apps = ModuleApp.all + exceptions = OrbitStore::MODULE_EXCEPTIONS + if !store_token.nil? + ids = [] + module_index = {} + module_apps.each do |ma| + ids << ma.key + module_index[ma.key] = ma + end + params_to_send = {'store_token' => store_token, "apps" => ids} + uri = URI.parse(OrbitStore::URL) + http = Net::HTTP.new(uri.host,uri.port) + request = Net::HTTP::Post.new("/store/check_module_permissions") + request.body = params_to_send.to_query + response = http.request(request) rescue nil + if !response.nil? + data = JSON.parse(response.body) + if response.code == "200" + permissions = data["permissions"] + permissions.each do |permission| + ma = module_index[permission["app"]] + ma.store_permission_granted = (exceptions.include?(ma.key) ? true : permission["granted"]) + ma.save + end + end + else + module_apps.each do |ma| + ma.store_permission_granted = (exceptions.include?(ma.key) ? true : false) + ma.save + end + end + else + module_apps.each do |ma| + ma.store_permission_granted = (exceptions.include?(ma.key) ? true : false) + ma.save + end + end + end end end \ No newline at end of file diff --git a/lib/orbit_core_lib.rb b/lib/orbit_core_lib.rb index 6b46264..53e9d1b 100644 --- a/lib/orbit_core_lib.rb +++ b/lib/orbit_core_lib.rb @@ -62,7 +62,11 @@ module OrbitCoreLib return end if !@module_app.nil? - check_user_can_use + if @module_app.store_permission_granted || params["controller"] == "admin/authorizations" + check_user_can_use + else + redirect_to admin_license_denied_path + end else if current_user.nil? || !current_user.is_admin? if params["controller"] != "admin/assets" diff --git a/lib/tasks/register_with_store.rake b/lib/tasks/register_with_store.rake new file mode 100644 index 0000000..9e76058 --- /dev/null +++ b/lib/tasks/register_with_store.rake @@ -0,0 +1,24 @@ +namespace :register_with_store do + task :register,[:arg] => :environment do |task,args| + modules = ModuleApp.all + ids = modules.collect{|ma| ma.key} + store_token = Site.first.store_token + module_apps = ModuleApp.all + exceptions = OrbitStore::MODULE_EXCEPTIONS + if !store_token.nil? + params_to_send = {'store_token' => store_token, "apps" => ids} + uri = URI.parse(OrbitStore::URL) + http = Net::HTTP.new(uri.host,uri.port) + request = Net::HTTP::Post.new("/store/register_old_sites_modules") + request.body = params_to_send.to_query + response = http.request(request) rescue nil + if response.nil? + puts "Cannot connect to store." + else + puts "All modules registered." + end + else + puts "Cannot register modules, site is not registered with store." + end + end +end \ No newline at end of file From 380e2cd4f913e94962402182f62531103b8b0524 Mon Sep 17 00:00:00 2001 From: Ray Date: Tue, 30 Dec 2014 20:40:45 +0800 Subject: [PATCH 09/19] License Denied. --- app/assets/images/license-denied.png | Bin 0 -> 39411 bytes app/assets/stylesheets/basic/global.css | 15 +++++++++++++ .../store_api/render_license_denied.html.erb | 21 ++++++++++++++++-- lib/orbit_app/helper/side_bar_renderer.rb | 6 ++--- 4 files changed, 37 insertions(+), 5 deletions(-) create mode 100644 app/assets/images/license-denied.png diff --git a/app/assets/images/license-denied.png b/app/assets/images/license-denied.png new file mode 100644 index 0000000000000000000000000000000000000000..2641519ac78f062cbd0456b54340542baf4f737d GIT binary patch literal 39411 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

ri4u48>Feg)=(2_0Z`VZ)NVR)V1PE6F|hX=kaK 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 O0000yp literal 0 HcmV?d00001 diff --git a/app/assets/stylesheets/basic/global.css b/app/assets/stylesheets/basic/global.css index 3f05c30..c22a181 100644 --- a/app/assets/stylesheets/basic/global.css +++ b/app/assets/stylesheets/basic/global.css @@ -122,6 +122,20 @@ legend { text-align: center; list-style: none; } +#sidebar .sidebar-nav .license-denied { + cursor: not-allowed; +} +#sidebar .sidebar-nav .license-denied > span { + position: relative; + width: 60px; +} +#sidebar .sidebar-nav .license-denied > span:before { + position: absolute; + top: 10px; + left: 12px; + font-size: 3.1em; + color: rgba(205, 10, 10, 0.46); +} #sidebar > h2.position { margin: 0; width: 61px; @@ -188,6 +202,7 @@ legend { } #sidebar .sidebar-nav > li a { display: block; + text-decoration: none; } #sidebar .sidebar-nav > li i { font-size: 1.6em; diff --git a/app/views/store_api/render_license_denied.html.erb b/app/views/store_api/render_license_denied.html.erb index 702732d..1f3535a 100644 --- a/app/views/store_api/render_license_denied.html.erb +++ b/app/views/store_api/render_license_denied.html.erb @@ -1,2 +1,19 @@ -

License Denied.

-

Please contact www.rulingdigital.com.

\ No newline at end of file + +
+

License Denied.

+

Please contact www.rulingdigital.com.

+
\ No newline at end of file diff --git a/lib/orbit_app/helper/side_bar_renderer.rb b/lib/orbit_app/helper/side_bar_renderer.rb index ed4fecd..ede07be 100644 --- a/lib/orbit_app/helper/side_bar_renderer.rb +++ b/lib/orbit_app/helper/side_bar_renderer.rb @@ -42,9 +42,9 @@ module SideBarRenderer end end else - link_to "/admin/license_denied" do - content_tag :span do - content_tag(:i, nil, class: @icon_class + " text-error") + link_to "/admin/license_denied", class: "license-denied" do + content_tag :span, class: "icons-blocked" do + content_tag(:i, nil, class: @icon_class) end end end From 76397de5efeb9d73292ffb48a77ee47977903a22 Mon Sep 17 00:00:00 2001 From: JiangRu Date: Wed, 31 Dec 2014 10:11:39 +0800 Subject: [PATCH 10/19] fix member list --- app/controllers/pages_controller.rb | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/app/controllers/pages_controller.rb b/app/controllers/pages_controller.rb index 5cfca10..7bda6bf 100644 --- a/app/controllers/pages_controller.rb +++ b/app/controllers/pages_controller.rb @@ -75,13 +75,26 @@ class PagesController < ApplicationController end params[:url] = page.url categories = [] - page.categories.each do |c| - category = Category.find(c) rescue nil - if !category.nil? && !category.disable - categories << c + if page.module == "member" + if page.categories.first == "all" + categories = ["all"] + else + page.categories.each do |c| + category = Role.find(c) rescue nil + if !category.nil? && !category.disabled + categories << c + end + end end + else + page.categories.each do |c| + category = Category.find(c) rescue nil + if !category.nil? && !category.disable + categories << c + end + end + categories = ["all"] if categories.blank? end - categories = ["all"] if categories.blank? @manifest = @key OrbitHelper.set_params params,current_user OrbitHelper.set_site_locale locale From 4425063a6836e421a0bbad1b44d43d588a73b14d Mon Sep 17 00:00:00 2001 From: JiangRu Date: Wed, 31 Dec 2014 15:13:49 +0800 Subject: [PATCH 11/19] add module update button --- app/views/admin/sites/update_manager.erb | 19 +++++++++++++++++++ config/locales/en.yml | 1 + config/locales/zh_tw.yml | 1 + config/routes.rb | 1 + 4 files changed, 22 insertions(+) diff --git a/app/views/admin/sites/update_manager.erb b/app/views/admin/sites/update_manager.erb index ac42d64..d76e3ff 100644 --- a/app/views/admin/sites/update_manager.erb +++ b/app/views/admin/sites/update_manager.erb @@ -126,6 +126,8 @@
<% if @store_permissions["permission_granted"] %> + + <% else %> Please register here. <% end %> @@ -245,10 +247,27 @@ } } + function check_module_updates(){ + $("#progress_msg").html("<%= t("update_manager_.updating_orbit") %>"); + $("#new_update_container").fadeOut(function(){ + $("#update_done").fadeOut(function(){ + $("#update_status").fadeIn(function(){ + $("#update_progress").fadeIn(); + $.get("<%= admin_site_bundle_install_path %>",function(result){ + $("#update_progress").fadeOut(function(){$("#update_done").fadeIn();}); + $("#update_status").fadeIn(); + }); + }); + }); + }); + } + $(document).ready(function(){ check_updates(); get_update_history(); + $("#module_update_btn").click(check_module_updates); + $("#chech_update_btn").click(check_updates); $("#update_btn").click(function(){ diff --git a/config/locales/en.yml b/config/locales/en.yml index 659ca3a..4168243 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -603,6 +603,7 @@ en: check_update: Check Update checking_update: Checking for Updates system_update: Install Updates + module_update: Module Updates update_done: System is update to date update_faild: Update failed. Merge is require in the update. Please login to server and update manually. update_history: Update Histroy diff --git a/config/locales/zh_tw.yml b/config/locales/zh_tw.yml index 9f99e3c..27993ad 100644 --- a/config/locales/zh_tw.yml +++ b/config/locales/zh_tw.yml @@ -612,6 +612,7 @@ zh_tw: check_update: 檢查更新 checking_update: 檢查更新中 system_update: 安裝更新 + module_update: 模組更新 update_done: 系統已是最新版本 update_faild: 更新失敗. 更新需要合併程式碼. 請登入伺服器手動進行更新. update_history: 更新紀錄 diff --git a/config/routes.rb b/config/routes.rb index 266d912..e413d1c 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -197,6 +197,7 @@ Orbit::Application.routes.draw do get 'get_update_history' get 'check_updates' get 'update_orbit' + get 'bundle_install' get 'restart_server' get 'delete_mail_log' end From 487d84c1d1c87aa7a163b3f7b3a9d91af1422f4c Mon Sep 17 00:00:00 2001 From: JiangRu Date: Wed, 31 Dec 2014 15:16:24 +0800 Subject: [PATCH 12/19] help designer's to push code --- app/assets/javascripts/frontend.js | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/app/assets/javascripts/frontend.js b/app/assets/javascripts/frontend.js index fa2e95a..c717991 100644 --- a/app/assets/javascripts/frontend.js +++ b/app/assets/javascripts/frontend.js @@ -1,8 +1,16 @@ (function($) { - $("document").ready(function(){ + $("document").ready(function(){ // Get link data-attribute and make the banner clickable - $('.w-ad-banner__slide').not('[data-link=""]').not(".youtube").addClass('cursor').on("click",function(){ - window.open($(this).data("link"),"_blank"); + $('.w-ad-banner__slide') + .not('[data-link=""]') + .not(".youtube") + .addClass('cursor') + .on("click",function(){ + if( $(this).data('target') === '_blank' ) { + window.open($(this).data("link"), "_blank"); + } else { + window.location.href = ($(this).data("link")); + } }) }) }(jQuery)); \ No newline at end of file From 343294858e505a26c5ca0cbcd518904386c7ab07 Mon Sep 17 00:00:00 2001 From: Harry Bomrah Date: Wed, 31 Dec 2014 15:27:18 +0800 Subject: [PATCH 13/19] fix for non registered site and module update button --- app/controllers/admin/sites_controller.rb | 1 + app/views/admin/sites/update_manager.erb | 5 ++++- lib/orbit_app/register_module.rb | 17 ++++++++++++----- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/app/controllers/admin/sites_controller.rb b/app/controllers/admin/sites_controller.rb index eb9c299..acb8485 100644 --- a/app/controllers/admin/sites_controller.rb +++ b/app/controllers/admin/sites_controller.rb @@ -119,6 +119,7 @@ class Admin::SitesController < OrbitAdminController def bundle_install Bundler.with_clean_env { `cd #{Rails.root} && BUNDLE_GEMFILE=built_in_extensions.rb bundle update && bundle` } + Bundler.with_clean_env { `cd #{Rails.root} && BUNDLE_GEMFILE=downloaded_extensions.rb bundle update && bundle` } %x(kill -s USR2 `cat tmp/pids/unicorn.pid`) sleep 5 render :nothing => true diff --git a/app/views/admin/sites/update_manager.erb b/app/views/admin/sites/update_manager.erb index d76e3ff..8df58bc 100644 --- a/app/views/admin/sites/update_manager.erb +++ b/app/views/admin/sites/update_manager.erb @@ -127,7 +127,7 @@ <% if @store_permissions["permission_granted"] %> - + <% else %> Please register here. <% end %> @@ -173,6 +173,9 @@
+ <% if @store_permissions["permission_granted"] %> + + <% end %>
diff --git a/lib/orbit_app/register_module.rb b/lib/orbit_app/register_module.rb index ad019fd..ad9b2da 100644 --- a/lib/orbit_app/register_module.rb +++ b/lib/orbit_app/register_module.rb @@ -41,11 +41,18 @@ module OrbitApp if !response.nil? data = JSON.parse(response.body) if response.code == "200" - permissions = data["permissions"] - permissions.each do |permission| - ma = module_index[permission["app"]] - ma.store_permission_granted = (exceptions.include?(ma.key) ? true : permission["granted"]) - ma.save + if data["success"] + permissions = data["permissions"] + permissions.each do |permission| + ma = module_index[permission["app"]] + ma.store_permission_granted = (exceptions.include?(ma.key) ? true : permission["granted"]) + ma.save + end + else + module_apps.each do |ma| + ma.store_permission_granted = (exceptions.include?(ma.key) ? true : false) + ma.save + end end end else From ceca2c58c0b8fd6f4b7044870b5d3dc77bd2bea7 Mon Sep 17 00:00:00 2001 From: Harry Bomrah Date: Wed, 31 Dec 2014 16:33:33 +0800 Subject: [PATCH 14/19] fix for module permissions --- app/controllers/store_api_controller.rb | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/app/controllers/store_api_controller.rb b/app/controllers/store_api_controller.rb index d35c175..d693539 100644 --- a/app/controllers/store_api_controller.rb +++ b/app/controllers/store_api_controller.rb @@ -30,7 +30,10 @@ class StoreApiController < ApplicationController response = {"success" => false} end render :json => response.to_json - bundle_install if response["success"] + if response["success"] + bundle_install + give_permissions(params[:module_key]) + end end def uninstall_module @@ -54,6 +57,14 @@ class StoreApiController < ApplicationController sleep 5 end + def give_permissions(key) + ma = ModuleApp.find_by_key(key) rescue nil + if !ma.nil? + ma.store_permission_granted = true + ma.save + end + end + def download_template(url,name) dir = File.join(Rails.root,"public","template_cache") destination = File.join(Rails.root,"app","templates","#{Site.first.template}","modules") From 12107376b63a90b06ef891b8a3eff6124ab24841 Mon Sep 17 00:00:00 2001 From: Harry Bomrah Date: Wed, 31 Dec 2014 16:41:47 +0800 Subject: [PATCH 15/19] fix for restarting server --- app/controllers/store_api_controller.rb | 12 +++++------- config/routes.rb | 1 + 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/app/controllers/store_api_controller.rb b/app/controllers/store_api_controller.rb index d693539..4bd74e8 100644 --- a/app/controllers/store_api_controller.rb +++ b/app/controllers/store_api_controller.rb @@ -32,7 +32,7 @@ class StoreApiController < ApplicationController render :json => response.to_json if response["success"] bundle_install - give_permissions(params[:module_key]) + # give_permissions(params[:module_key]) end end @@ -57,14 +57,12 @@ class StoreApiController < ApplicationController sleep 5 end - def give_permissions(key) - ma = ModuleApp.find_by_key(key) rescue nil - if !ma.nil? - ma.store_permission_granted = true - ma.save - end + def restart_server_after_install + %x(kill -s USR2 `cat tmp/pids/unicorn.pid`) + sleep 5 end + def download_template(url,name) dir = File.join(Rails.root,"public","template_cache") destination = File.join(Rails.root,"app","templates","#{Site.first.template}","modules") diff --git a/config/routes.rb b/config/routes.rb index e413d1c..73d5b9f 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -30,6 +30,7 @@ Orbit::Application.routes.draw do post "/store/confirmation" => "store_api#confirmation" post "/store/install_module" => "store_api#install_module" post "/store/uninstall_module" => "store_api#uninstall_module" + post "/store/restart_srever_after_install" => "store_api#restart_server_after_install" # The priority is based upon order of creation: first created -> highest priority. # See how all your routes lay out with "rake routes". From f1acfa34ac9a3fdf896f01369bc7b16bafeeda2e Mon Sep 17 00:00:00 2001 From: rulingcom Date: Tue, 6 Jan 2015 15:22:41 +0800 Subject: [PATCH 16/19] template default modified --- .../orbit_bootstrap/assets/javascripts/app.js | 174 +++++++++--------- .../stylesheets/template/base/_genernal.scss | 8 - .../stylesheets/template/base/_global.scss | 26 +++ .../stylesheets/template/base/_variables.scss | 57 +----- .../template/modules/announcement.scss | 61 +++--- .../stylesheets/template/modules/member.scss | 139 ++++++-------- .../assets/stylesheets/template/template.scss | 11 +- .../stylesheets/template/widget/sitemenu.scss | 100 ++++------ .../orbit_bootstrap/home/index.html.erb | 2 +- .../orbit_bootstrap/home/pagination.html.erb | 8 +- .../ad_banner/_ad_banner_widget1.html.erb | 4 +- .../ad_banner/_ad_banner_widget2.html.erb | 18 ++ .../_ad_banner_widget2_video.html.erb | 3 +- .../ad_banner/_ad_banner_widget3.html.erb | 13 +- .../modules/ad_banner/info.json | 15 +- .../announcement/_annc_widget1.html.erb | 2 +- .../announcement/_annc_widget10.html.erb | 2 +- .../announcement/_annc_widget11.html.erb | 2 +- .../announcement/_annc_widget12.html.erb | 2 +- .../announcement/_annc_widget2.html.erb | 2 +- .../announcement/_annc_widget3.html.erb | 2 +- .../announcement/_annc_widget4.html.erb | 2 +- .../announcement/_annc_widget5.html.erb | 2 +- .../announcement/_annc_widget6.html.erb | 2 +- .../announcement/_annc_widget7.html.erb | 2 +- .../announcement/_annc_widget8.html.erb | 2 +- .../announcement/_annc_widget9.html.erb | 2 +- .../modules/announcement/annc_index1.html.erb | 2 +- .../modules/announcement/annc_index2.html.erb | 2 +- .../modules/announcement/show.html.erb | 45 +++-- .../modules/archive/_archive_widget1.html.erb | 2 +- .../modules/archive/archive_index1.html.erb | 2 +- .../modules/archive/archive_index2.html.erb | 1 + .../modules/archive/show.html.erb | 4 +- ..._widget.html.erb => _faq_widget1.html.erb} | 0 ...widget1.html.erb => _faq_widget2.html.erb} | 0 .../{index.html.erb => faq_index.html1.erb} | 0 .../{index1.html.erb => faq_index2.html.erb} | 0 .../orbit_bootstrap/modules/faq/show.html.erb | 2 +- ...get.html.erb => _gallery_widget1.html.erb} | 0 ...et1.html.erb => _gallery_widget2.html.erb} | 2 +- ...et2.html.erb => _gallery_widget3.html.erb} | 2 +- ...index.html.erb => gallery_index1.html.erb} | 0 ...ndex1.html.erb => gallery_index2.html.erb} | 0 ..._staff.html.erb => member_index1.html.erb} | 22 +-- ...r.html.erb => member_index_staff.html.erb} | 22 +-- ...html.erb => member_index_teacher.html.erb} | 19 +- .../modules/member/show.html.erb | 32 +++- ...get.html.erb => _web_res_widget1.html.erb} | 0 ...et1.html.erb => _web_res_widget2.html.erb} | 0 ...index.html.erb => web_res_index1.html.erb} | 0 ...ndex1.html.erb => web_res_index2.html.erb} | 0 .../widgets/site_menu_widget/_widget.html.erb | 16 +- built_in_extensions.rb | 2 +- config/mongoid.yml | 6 +- config/unicorn.rb | 2 +- 56 files changed, 389 insertions(+), 459 deletions(-) delete mode 100644 app/templates/orbit_bootstrap/assets/stylesheets/template/base/_genernal.scss create mode 100644 app/templates/orbit_bootstrap/assets/stylesheets/template/base/_global.scss create mode 100644 app/templates/orbit_bootstrap/modules/ad_banner/_ad_banner_widget2.html.erb rename app/templates/orbit_bootstrap/modules/faq/{_widget.html.erb => _faq_widget1.html.erb} (100%) rename app/templates/orbit_bootstrap/modules/faq/{_widget1.html.erb => _faq_widget2.html.erb} (100%) rename app/templates/orbit_bootstrap/modules/faq/{index.html.erb => faq_index.html1.erb} (100%) rename app/templates/orbit_bootstrap/modules/faq/{index1.html.erb => faq_index2.html.erb} (100%) rename app/templates/orbit_bootstrap/modules/gallery/{_widget.html.erb => _gallery_widget1.html.erb} (100%) rename app/templates/orbit_bootstrap/modules/gallery/{_widget1.html.erb => _gallery_widget2.html.erb} (93%) rename app/templates/orbit_bootstrap/modules/gallery/{_widget2.html.erb => _gallery_widget3.html.erb} (86%) rename app/templates/orbit_bootstrap/modules/gallery/{index.html.erb => gallery_index1.html.erb} (100%) rename app/templates/orbit_bootstrap/modules/gallery/{index1.html.erb => gallery_index2.html.erb} (100%) rename app/templates/orbit_bootstrap/modules/member/{index_staff.html.erb => member_index1.html.erb} (51%) rename app/templates/orbit_bootstrap/modules/member/{index_teacher.html.erb => member_index_staff.html.erb} (51%) rename app/templates/orbit_bootstrap/modules/member/{index.html.erb => member_index_teacher.html.erb} (51%) rename app/templates/orbit_bootstrap/modules/web_resource/{_widget.html.erb => _web_res_widget1.html.erb} (100%) rename app/templates/orbit_bootstrap/modules/web_resource/{_widget1.html.erb => _web_res_widget2.html.erb} (100%) rename app/templates/orbit_bootstrap/modules/web_resource/{index.html.erb => web_res_index1.html.erb} (100%) rename app/templates/orbit_bootstrap/modules/web_resource/{index1.html.erb => web_res_index2.html.erb} (100%) diff --git a/app/templates/orbit_bootstrap/assets/javascripts/app.js b/app/templates/orbit_bootstrap/assets/javascripts/app.js index a9dd1ed..276189f 100644 --- a/app/templates/orbit_bootstrap/assets/javascripts/app.js +++ b/app/templates/orbit_bootstrap/assets/javascripts/app.js @@ -1,110 +1,106 @@ (function($) { "use strict" - - // Init functions + function init () { - // Announcement modules - var annc = { - truncation : function (el, maxLength) { + var doc = document; + + var orbit = { + // Cross browser add class function + addClass : function(el, className) { + if( el.classList ) { + el.classList.add(className); + } else { + el.className += ' ' + className; + } + }, + // Cross browser has class function + hasClass : function(el, cls) { + return (' ' + el.className + ' ').indexOf(' ' + cls + ' ') > -1; + }, + // Add class name to the menu item when its children items are more than eight + addMegaDropdownClass : function(el, len) { + for( var i = 0; i < el.length; i++ ) { + if( el[i].children.length > len ) { + orbit.addClass(el[i].parentNode, 'mega-dropdown'); + } + } + }, + // Append caret to menu item if it has dropdown + addCaret : function() { + var list = doc.querySelectorAll('.page_menu.level_2'); + for( var i = 0, len = list.length; i < len; i++ ) { + var node = doc.createElement('span'); + node.className = 'caret'; + list[i].parentNode.appendChild(node); + } + }, + // Add link and cursor class name on element that has data-link attribute + addLinkOnADBanner : function(els) { + $.each(els, function(i) { + if ($(this).data('link') !== "" && !$(this).hasClass('youtube')) { + $(this).on('click', function() { + var target = $(this).data('target'), + link = $(this).data('link'); + if (target === '_blank') { + window.open(link, target); + } else { + window.location.href = link; + } + }).addClass('cursor'); + } + }); + }, + // Announcement text truncation + truncation : function (el, len) { for( var i = 0; i < el.length; i ++ ) { if ( el[i].firstChild !== null ) { - if( el[i].firstChild.length > maxLength ) { - var newTitle = el[i].firstChild.nodeValue; - var newTitle = newTitle.substring(0, maxLength) + '...' + if( el[i].firstChild.length > len ) { + var newStr = el[i].firstChild.nodeValue, + newStr = newStr.substring(0, len) + '...' el .eq(i) - .text(newTitle); + .text(newStr); } } } - } - } + }, + // Sitemenu dropdown + sitemenuDropdown : function() { + var el = doc.querySelectorAll('.sitemenu__list.level-2'); + for( var i = 0, len = el.length; i < len; i++ ) { + if( el[i].hasChildNodes() ) { + var caret = doc.createElement('span'); + caret.className = 'sitemenu___dropdown-toggle fa fa-caret-down'; + caret.setAttribute('data-toggle', 'dropdown'); - function anncFix() { - var w$ = $('.w-announcement-4'); - if( w$.length ) { - annc.truncation(w$.find('.w-annc__subtitle'), 25); - } - } - - // Necessary for Responsive images - function bullEye() { - // $(".bullseye").bullseye({ - // fadeEffect: false - // }); - } - - // Adding class to submenu that has dropdown items - function submenuFix () { - var item$ = $('.submenu__item.level-1'); - var itemLen = item$.length; - var list$ = item$.find('.submenu__list.level-2'); - - for( var i=0; i div { - display: inline-block; - } - a { - display: inline-block; - margin-bottom: 4px; - padding: 5px 8px; - font-size: 0.8em; - color: $theme-gray; - border: 1px solid $theme-gray-light; - text-decoration: none; - &:hover { - color: $theme-color-main; - border-color: $theme-color-main; - background-color: $theme-gray-lighter; - } - } + .member-plugins { + margin-bottom: 20px; + a { + font-size: 0.8125rem; } } + } \ No newline at end of file diff --git a/app/templates/orbit_bootstrap/assets/stylesheets/template/template.scss b/app/templates/orbit_bootstrap/assets/stylesheets/template/template.scss index 320c950..da62bb5 100644 --- a/app/templates/orbit_bootstrap/assets/stylesheets/template/template.scss +++ b/app/templates/orbit_bootstrap/assets/stylesheets/template/template.scss @@ -1,5 +1,4 @@ // Base -@import url("http://fonts.googleapis.com/css?family=Droid+Sans:400,700"); @import "bootstrap/mixins"; @import "bootstrap/variables"; @import "base/mixins"; @@ -7,7 +6,7 @@ @import "base/unity"; @import "base/pagination"; @import "base/orbitbar-override"; -@import "base/genernal"; +@import "base/global"; // Layout @import "layout/header"; @@ -29,11 +28,3 @@ // Widget @import "widget/breadcrumb"; @import "widget/sitemenu"; - -html { - font-size: 100%; -} -body { - margin-top: 40px; // needed for Orbit bar - font-size: inherit; -} \ No newline at end of file diff --git a/app/templates/orbit_bootstrap/assets/stylesheets/template/widget/sitemenu.scss b/app/templates/orbit_bootstrap/assets/stylesheets/template/widget/sitemenu.scss index 02b965d..693db3f 100644 --- a/app/templates/orbit_bootstrap/assets/stylesheets/template/widget/sitemenu.scss +++ b/app/templates/orbit_bootstrap/assets/stylesheets/template/widget/sitemenu.scss @@ -1,86 +1,52 @@ -.submenu-wrap { - @include clearfix(); +.sitemenu-wrap { padding: 10px 0; - - .submenu__title { + @include clearfix; + .sitemenu__title { display: none; } - - .submenu__list { - list-style: none; - padding: 0; + .sitemenu__list { margin: 0; + padding: 0; + list-style: none; } - - .submenu__item.level-1 { + .sitemenu__item.level-1 { + font-size: 0.8125rem; position: relative; float: left; margin-right: 1%; margin-bottom: 12px; - } - - .submenu__link.level-1 { - float: left; + padding: 8px .8em; padding-bottom: 8px; - font-size: 13px; - font-size: 0.8125rem; - background: $theme-color-second; color: #fff; - padding: 8px 0.8em; - border-radius: 0.2em; - + border-radius: .2em; + background: $theme-color-second; &:hover { background: darken($theme-color-second, 10%); } } - - .submenu__item:hover .dropdown { - display: block; - } - - .touch .submenu__item .dropdown { - display: none !important; - } - - // Submenu dropdown - .submenu__list.dropdown { - display: none; - padding: 20px 0 0 0; - position: absolute; - left: 0; - top: 80%; - border-radius: 2px; - z-index: 200; - } - - - .submenu__list .dropdown:before { - content: ""; - border-style: solid; - border-width: 0px 7px 7px 7px; - border-color: transparent transparent $theme-color-main transparent; - position: absolute; - top: 15px; - left: 15px; - } - - .submenu__item.level-2 { - display: block; - padding: 4px 8px; - background: $theme-color-main; - font-size: 0.8125rem; - } - - .submenu__link.level-2 { + .sitemenu__link.level-1 { + margin-right: .25rem; color: #fff; - white-space: nowrap; } - - .submenu__list.hidden--item { - display: none; - - &:before { - display: none; + .sitemenu___dropdown-toggle { + font-size: 0.75rem; + padding: 2px .3125rem; + cursor: pointer; + } + // sitemenu dropdown + .sitemenu__list.dropdown-menu { + min-width: 100%; + margin-top: 4px; + border: none; + border-radius: .2em; + background: $theme-color-main; + } + .sitemenu__link.level-2 { + color: #fff; + font-size: 0.8125rem; + padding: 4px 0.625rem; + &:hover { + background: lighten($theme-color-second, 5%); } } -} +} \ No newline at end of file diff --git a/app/templates/orbit_bootstrap/home/index.html.erb b/app/templates/orbit_bootstrap/home/index.html.erb index d1102e4..086ef7f 100644 --- a/app/templates/orbit_bootstrap/home/index.html.erb +++ b/app/templates/orbit_bootstrap/home/index.html.erb @@ -3,7 +3,7 @@ <%= render_partial("head") %> - + <%= render_orbit_bar %> <%= render_header %>
diff --git a/app/templates/orbit_bootstrap/home/pagination.html.erb b/app/templates/orbit_bootstrap/home/pagination.html.erb index 96c2b2f..0c22683 100644 --- a/app/templates/orbit_bootstrap/home/pagination.html.erb +++ b/app/templates/orbit_bootstrap/home/pagination.html.erb @@ -1,3 +1,5 @@ - \ No newline at end of file + diff --git a/app/templates/orbit_bootstrap/modules/ad_banner/_ad_banner_widget1.html.erb b/app/templates/orbit_bootstrap/modules/ad_banner/_ad_banner_widget1.html.erb index f1c354c..31c154f 100644 --- a/app/templates/orbit_bootstrap/modules/ad_banner/_ad_banner_widget1.html.erb +++ b/app/templates/orbit_bootstrap/modules/ad_banner/_ad_banner_widget1.html.erb @@ -1,4 +1,4 @@ -
+
    + + diff --git a/app/templates/orbit_bootstrap/modules/ad_banner/_ad_banner_widget2.html.erb b/app/templates/orbit_bootstrap/modules/ad_banner/_ad_banner_widget2.html.erb new file mode 100644 index 0000000..842ebc3 --- /dev/null +++ b/app/templates/orbit_bootstrap/modules/ad_banner/_ad_banner_widget2.html.erb @@ -0,0 +1,18 @@ +
    +
    + {{html}} +
    +
      +
      + diff --git a/app/templates/orbit_bootstrap/modules/ad_banner/_ad_banner_widget2_video.html.erb b/app/templates/orbit_bootstrap/modules/ad_banner/_ad_banner_widget2_video.html.erb index 6b77a90..22c4aa5 100644 --- a/app/templates/orbit_bootstrap/modules/ad_banner/_ad_banner_widget2_video.html.erb +++ b/app/templates/orbit_bootstrap/modules/ad_banner/_ad_banner_widget2_video.html.erb @@ -1,4 +1,4 @@ -
      +
      \ No newline at end of file diff --git a/app/templates/orbit_bootstrap/modules/archive/_archive_widget1.html.erb b/app/templates/orbit_bootstrap/modules/archive/_archive_widget1.html.erb index 761b3e1..e5bfe75 100644 --- a/app/templates/orbit_bootstrap/modules/archive/_archive_widget1.html.erb +++ b/app/templates/orbit_bootstrap/modules/archive/_archive_widget1.html.erb @@ -1,4 +1,4 @@ -
      +

      {{widget-title}}

      • diff --git a/app/templates/orbit_bootstrap/modules/archive/archive_index1.html.erb b/app/templates/orbit_bootstrap/modules/archive/archive_index1.html.erb index d7fafa8..b66ea44 100644 --- a/app/templates/orbit_bootstrap/modules/archive/archive_index1.html.erb +++ b/app/templates/orbit_bootstrap/modules/archive/archive_index1.html.erb @@ -1,4 +1,4 @@ -
        +

        {{page-title}}

        • diff --git a/app/templates/orbit_bootstrap/modules/archive/archive_index2.html.erb b/app/templates/orbit_bootstrap/modules/archive/archive_index2.html.erb index b54a794..be5c2ca 100644 --- a/app/templates/orbit_bootstrap/modules/archive/archive_index2.html.erb +++ b/app/templates/orbit_bootstrap/modules/archive/archive_index2.html.erb @@ -6,6 +6,7 @@

          + diff --git a/app/templates/orbit_bootstrap/modules/archive/show.html.erb b/app/templates/orbit_bootstrap/modules/archive/show.html.erb index 11a8c05..12085b7 100644 --- a/app/templates/orbit_bootstrap/modules/archive/show.html.erb +++ b/app/templates/orbit_bootstrap/modules/archive/show.html.erb @@ -1,7 +1,7 @@
          -

          +

          {{title}} -

          +

          diff --git a/app/templates/orbit_bootstrap/modules/faq/_widget.html.erb b/app/templates/orbit_bootstrap/modules/faq/_faq_widget1.html.erb similarity index 100% rename from app/templates/orbit_bootstrap/modules/faq/_widget.html.erb rename to app/templates/orbit_bootstrap/modules/faq/_faq_widget1.html.erb diff --git a/app/templates/orbit_bootstrap/modules/faq/_widget1.html.erb b/app/templates/orbit_bootstrap/modules/faq/_faq_widget2.html.erb similarity index 100% rename from app/templates/orbit_bootstrap/modules/faq/_widget1.html.erb rename to app/templates/orbit_bootstrap/modules/faq/_faq_widget2.html.erb diff --git a/app/templates/orbit_bootstrap/modules/faq/index.html.erb b/app/templates/orbit_bootstrap/modules/faq/faq_index.html1.erb similarity index 100% rename from app/templates/orbit_bootstrap/modules/faq/index.html.erb rename to app/templates/orbit_bootstrap/modules/faq/faq_index.html1.erb diff --git a/app/templates/orbit_bootstrap/modules/faq/index1.html.erb b/app/templates/orbit_bootstrap/modules/faq/faq_index2.html.erb similarity index 100% rename from app/templates/orbit_bootstrap/modules/faq/index1.html.erb rename to app/templates/orbit_bootstrap/modules/faq/faq_index2.html.erb diff --git a/app/templates/orbit_bootstrap/modules/faq/show.html.erb b/app/templates/orbit_bootstrap/modules/faq/show.html.erb index e003463..5bee8fe 100644 --- a/app/templates/orbit_bootstrap/modules/faq/show.html.erb +++ b/app/templates/orbit_bootstrap/modules/faq/show.html.erb @@ -1,6 +1,6 @@
          -

          {{question}}

          +

          {{question}}

          diff --git a/app/templates/orbit_bootstrap/modules/gallery/_widget.html.erb b/app/templates/orbit_bootstrap/modules/gallery/_gallery_widget1.html.erb similarity index 100% rename from app/templates/orbit_bootstrap/modules/gallery/_widget.html.erb rename to app/templates/orbit_bootstrap/modules/gallery/_gallery_widget1.html.erb diff --git a/app/templates/orbit_bootstrap/modules/gallery/_widget1.html.erb b/app/templates/orbit_bootstrap/modules/gallery/_gallery_widget2.html.erb similarity index 93% rename from app/templates/orbit_bootstrap/modules/gallery/_widget1.html.erb rename to app/templates/orbit_bootstrap/modules/gallery/_gallery_widget2.html.erb index 54ed0c8..6a7fbe7 100644 --- a/app/templates/orbit_bootstrap/modules/gallery/_widget1.html.erb +++ b/app/templates/orbit_bootstrap/modules/gallery/_gallery_widget2.html.erb @@ -1,4 +1,4 @@ -