From 3d6c55305d2a8c65f2cd55fef2b545280202b745 Mon Sep 17 00:00:00 2001 From: Braulio Bhavamitra Date: Sat, 15 Aug 2015 15:03:47 -0300 Subject: [PATCH] Add site_tour plugin from gitlab.com/noosfero-plugins/site_tour --- plugins/site_tour/controllers/public/site_tour_plugin_public_controller.rb | 11 +++++++++++ plugins/site_tour/controllers/site_tour_plugin_admin_controller.rb | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ plugins/site_tour/lib/ext/person.rb | 5 +++++ plugins/site_tour/lib/site_tour_plugin.rb | 44 ++++++++++++++++++++++++++++++++++++++++++++ plugins/site_tour/lib/site_tour_plugin/site_tour_helper.rb | 14 ++++++++++++++ plugins/site_tour/lib/site_tour_plugin/tour_block.rb | 29 +++++++++++++++++++++++++++++ plugins/site_tour/po/pt/site_tour.po | 119 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ plugins/site_tour/po/site_tour.pot | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ plugins/site_tour/public/edit_tour_block.css | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ plugins/site_tour/public/edit_tour_block.js | 18 ++++++++++++++++++ plugins/site_tour/public/intro.min.js | 33 +++++++++++++++++++++++++++++++++ plugins/site_tour/public/introjs.min.css | 1 + plugins/site_tour/public/main.js | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ plugins/site_tour/public/style.css | 1 + plugins/site_tour/public/tour/en/tour.js.dist | 6 ++++++ plugins/site_tour/test/functional/site_tour_plugin_admin_controller_test.rb | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ plugins/site_tour/test/functional/site_tour_plugin_public_controller_test.rb | 30 ++++++++++++++++++++++++++++++ plugins/site_tour/test/test_helper.rb | 1 + plugins/site_tour/test/unit/site_tour_helper_test.rb | 17 +++++++++++++++++ plugins/site_tour/test/unit/site_tour_plugin_test.rb | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ plugins/site_tour/test/unit/tour_block_test.rb | 41 +++++++++++++++++++++++++++++++++++++++++ plugins/site_tour/views/blocks/tour.html.erb | 11 +++++++++++ plugins/site_tour/views/box_organizer/site_tour_plugin/_tour_block.html.erb | 44 ++++++++++++++++++++++++++++++++++++++++++++ plugins/site_tour/views/box_organizer/site_tour_plugin/_tour_block_group_item.html.erb | 19 +++++++++++++++++++ plugins/site_tour/views/box_organizer/site_tour_plugin/_tour_block_item.html.erb | 16 ++++++++++++++++ plugins/site_tour/views/environment_design/site_tour_plugin | 1 + plugins/site_tour/views/profile_design/site_tour_plugin | 1 + plugins/site_tour/views/site_tour_plugin_admin/index.html.erb | 13 +++++++++++++ plugins/site_tour/views/tour_actions.html.erb | 22 ++++++++++++++++++++++ 29 files changed, 971 insertions(+), 0 deletions(-) create mode 100644 plugins/site_tour/controllers/public/site_tour_plugin_public_controller.rb create mode 100644 plugins/site_tour/controllers/site_tour_plugin_admin_controller.rb create mode 100644 plugins/site_tour/lib/ext/person.rb create mode 100644 plugins/site_tour/lib/site_tour_plugin.rb create mode 100644 plugins/site_tour/lib/site_tour_plugin/site_tour_helper.rb create mode 100644 plugins/site_tour/lib/site_tour_plugin/tour_block.rb create mode 100644 plugins/site_tour/po/pt/site_tour.po create mode 100644 plugins/site_tour/po/site_tour.pot create mode 100644 plugins/site_tour/public/edit_tour_block.css create mode 100644 plugins/site_tour/public/edit_tour_block.js create mode 100644 plugins/site_tour/public/intro.min.js create mode 100644 plugins/site_tour/public/introjs.min.css create mode 100644 plugins/site_tour/public/main.js create mode 120000 plugins/site_tour/public/style.css create mode 100644 plugins/site_tour/public/tour/en/tour.js.dist create mode 100644 plugins/site_tour/test/functional/site_tour_plugin_admin_controller_test.rb create mode 100644 plugins/site_tour/test/functional/site_tour_plugin_public_controller_test.rb create mode 100644 plugins/site_tour/test/test_helper.rb create mode 100644 plugins/site_tour/test/unit/site_tour_helper_test.rb create mode 100644 plugins/site_tour/test/unit/site_tour_plugin_test.rb create mode 100644 plugins/site_tour/test/unit/tour_block_test.rb create mode 100644 plugins/site_tour/views/blocks/tour.html.erb create mode 100644 plugins/site_tour/views/box_organizer/site_tour_plugin/_tour_block.html.erb create mode 100644 plugins/site_tour/views/box_organizer/site_tour_plugin/_tour_block_group_item.html.erb create mode 100644 plugins/site_tour/views/box_organizer/site_tour_plugin/_tour_block_item.html.erb create mode 120000 plugins/site_tour/views/environment_design/site_tour_plugin create mode 120000 plugins/site_tour/views/profile_design/site_tour_plugin create mode 100644 plugins/site_tour/views/site_tour_plugin_admin/index.html.erb create mode 100644 plugins/site_tour/views/tour_actions.html.erb diff --git a/plugins/site_tour/controllers/public/site_tour_plugin_public_controller.rb b/plugins/site_tour/controllers/public/site_tour_plugin_public_controller.rb new file mode 100644 index 0000000..1265b8f --- /dev/null +++ b/plugins/site_tour/controllers/public/site_tour_plugin_public_controller.rb @@ -0,0 +1,11 @@ +class SiteTourPluginPublicController < PublicController + + before_filter :login_required + + def mark_action + user.site_tour_plugin_actions += [params[:action_name]].flatten + user.site_tour_plugin_actions.uniq! + render :json => {:ok => user.save} + end + +end diff --git a/plugins/site_tour/controllers/site_tour_plugin_admin_controller.rb b/plugins/site_tour/controllers/site_tour_plugin_admin_controller.rb new file mode 100644 index 0000000..c8fe557 --- /dev/null +++ b/plugins/site_tour/controllers/site_tour_plugin_admin_controller.rb @@ -0,0 +1,50 @@ +require 'csv' + +class SiteTourPluginAdminController < PluginAdminController + + no_design_blocks + + def index + settings = params[:settings] + settings ||= {} + + @settings = Noosfero::Plugin::Settings.new(environment, SiteTourPlugin, settings) + @settings.actions_csv = convert_to_csv(@settings.actions) + @settings.group_triggers_csv = convert_to_csv(@settings.group_triggers) + + if request.post? + @settings.actions = convert_actions_from_csv(settings[:actions_csv]) + @settings.settings.delete(:actions_csv) + + @settings.group_triggers = convert_group_triggers_from_csv(settings[:group_triggers_csv]) + @settings.settings.delete(:group_triggers_csv) + + @settings.save! + session[:notice] = 'Settings succefully saved.' + redirect_to :action => 'index' + end + end + + protected + + def convert_to_csv(actions) + CSV.generate do |csv| + (actions||[]).each { |action| csv << action.values } + end + end + + def convert_actions_from_csv(actions_csv) + return [] if actions_csv.blank? + CSV.parse(actions_csv).map do |action| + {:language => action[0], :group_name => action[1], :selector => action[2], :description => action[3]} + end + end + + def convert_group_triggers_from_csv(group_triggers_csv) + return [] if group_triggers_csv.blank? + CSV.parse(group_triggers_csv).map do |group| + {:group_name => group[0], :selector => group[1], :event => group[2]} + end + end + +end diff --git a/plugins/site_tour/lib/ext/person.rb b/plugins/site_tour/lib/ext/person.rb new file mode 100644 index 0000000..a6af042 --- /dev/null +++ b/plugins/site_tour/lib/ext/person.rb @@ -0,0 +1,5 @@ +class Person + + settings_items :site_tour_plugin_actions, :type => Array, :default => [] + +end diff --git a/plugins/site_tour/lib/site_tour_plugin.rb b/plugins/site_tour/lib/site_tour_plugin.rb new file mode 100644 index 0000000..4003d3d --- /dev/null +++ b/plugins/site_tour/lib/site_tour_plugin.rb @@ -0,0 +1,44 @@ +class SiteTourPlugin < Noosfero::Plugin + + def self.plugin_name + 'SiteTourPlugin' + end + + def self.plugin_description + _("A site tour to show users how to use the application.") + end + + def stylesheet? + true + end + + def js_files + ['intro.min.js', 'main.js'] + end + + def user_data_extras + proc do + logged_in? ? {:site_tour_plugin_actions => user.site_tour_plugin_actions}:{} + end + end + + def body_ending + proc do + tour_file = "/plugins/site_tour/tour/#{language}/tour.js" + js_file = File.exists?(Rails.root.join("public#{tour_file}").to_s) ? tour_file : "" + settings = Noosfero::Plugin::Settings.new(environment, SiteTourPlugin) + actions = (settings.actions||[]).select {|action| action[:language] == language} + + render(:file => 'tour_actions', :locals => { :actions => actions, :group_triggers => settings.group_triggers, :js_file => js_file}) + end + end + + def self.extra_blocks + { SiteTourPlugin::TourBlock => {} } + end + + def self.actions_csv_default_setting + 'en,tour_plugin,.site-tour-plugin_tour-block .tour-button,"Click to start tour!"' + end + +end diff --git a/plugins/site_tour/lib/site_tour_plugin/site_tour_helper.rb b/plugins/site_tour/lib/site_tour_plugin/site_tour_helper.rb new file mode 100644 index 0000000..f18e900 --- /dev/null +++ b/plugins/site_tour/lib/site_tour_plugin/site_tour_helper.rb @@ -0,0 +1,14 @@ +module SiteTourPlugin::SiteTourHelper + + def parse_tour_description(description) + p = profile rescue nil + if !p.nil? && description.present? + description.gsub('{profile.identifier}', p.identifier). + gsub('{profile.name}', p.name). + gsub('{profile.url}', url_for(p.url)) + else + description + end + end + +end diff --git a/plugins/site_tour/lib/site_tour_plugin/tour_block.rb b/plugins/site_tour/lib/site_tour_plugin/tour_block.rb new file mode 100644 index 0000000..65db701 --- /dev/null +++ b/plugins/site_tour/lib/site_tour_plugin/tour_block.rb @@ -0,0 +1,29 @@ +class SiteTourPlugin::TourBlock < Block + + settings_items :actions, :type => Array, :default => [{:group_name => 'tour_plugin', :selector => '.site-tour-plugin_tour-block .tour-button', :description => _('Click to start tour!')}] + settings_items :group_triggers, :type => Array, :default => [] + settings_items :display_button, :type => :boolean, :default => true + + attr_accessible :actions, :display_button, :group_triggers + + before_save do |block| + block.actions.reject! {|i| i[:group_name].blank? && i[:selector].blank? && i[:description].blank?} + block.group_triggers.reject! {|i| i[:group_name].blank? && i[:selector].blank?} + end + + def self.description + _('Site Tour Block') + end + + def help + _('Configure a step-by-step tour.') + end + + def content(args={}) + block = self + proc do + render :file => 'blocks/tour', :locals => {:block => block} + end + end + +end diff --git a/plugins/site_tour/po/pt/site_tour.po b/plugins/site_tour/po/pt/site_tour.po new file mode 100644 index 0000000..94ad2e3 --- /dev/null +++ b/plugins/site_tour/po/pt/site_tour.po @@ -0,0 +1,119 @@ +msgid "" +msgstr "" +"Project-Id-Version: 1.2~rc1-2843-g999a037\n" +"POT-Creation-Date: 2015-08-06 08:53-0300\n" +"PO-Revision-Date: 2015-02-03 17:27-0300\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" + +#: plugins/site_tour/lib/site_tour_plugin.rb:8 +msgid "A site tour to show users how to use the application." +msgstr "Um plugin para apresentar aos usuários um tour da aplicação" + +#: plugins/site_tour/lib/site_tour_plugin/tour_block.rb:3 +msgid "Click to start tour!" +msgstr "Clique para iniciar o tour!" + +#: plugins/site_tour/lib/site_tour_plugin/tour_block.rb:15 +msgid "Site Tour Block" +msgstr "Bloco para Site Tour" + +#: plugins/site_tour/lib/site_tour_plugin/tour_block.rb:19 +msgid "Configure a step-by-step tour." +msgstr "Configure o passo a passo do tour." + +#: plugins/site_tour/views/box_organizer/site_tour_plugin/_tour_block_item.html.erb:13 +#: plugins/site_tour/views/box_organizer/site_tour_plugin/_tour_block_group_item.html.erb:15 +msgid "Delete" +msgstr "Apagar" + +#: plugins/site_tour/views/box_organizer/site_tour_plugin/_tour_block.html.erb:4 +msgid "Display help button" +msgstr "Mostrar o botão de ajuda" + +#: plugins/site_tour/views/box_organizer/site_tour_plugin/_tour_block.html.erb:8 +msgid "Tooltip Actions" +msgstr "Ações do Tooltip" + +#: plugins/site_tour/views/box_organizer/site_tour_plugin/_tour_block.html.erb:9 +msgid "" +"Special fields for description: {profile.name}, {profile.identifier}, " +"{profile.url}." +msgstr "" +"Campos especiais para a descrição: {profile.name}, {profile.identifier}, " +"{profile.url}" + +#: plugins/site_tour/views/box_organizer/site_tour_plugin/_tour_block.html.erb:11 +#: plugins/site_tour/views/box_organizer/site_tour_plugin/_tour_block.html.erb:29 +msgid "Group Name" +msgstr "Nome do Grupo" + +#: plugins/site_tour/views/box_organizer/site_tour_plugin/_tour_block.html.erb:12 +#: plugins/site_tour/views/box_organizer/site_tour_plugin/_tour_block.html.erb:30 +msgid "Selector" +msgstr "Seletor" + +#: plugins/site_tour/views/box_organizer/site_tour_plugin/_tour_block.html.erb:13 +msgid "Description" +msgstr "Descrição" + +#: plugins/site_tour/views/box_organizer/site_tour_plugin/_tour_block.html.erb:23 +msgid "New Tooltip" +msgstr "Novo Tooltip" + +#: plugins/site_tour/views/box_organizer/site_tour_plugin/_tour_block.html.erb:27 +msgid "Group Triggers" +msgstr "Gatilhos dos Grupos" + +#: plugins/site_tour/views/box_organizer/site_tour_plugin/_tour_block.html.erb:31 +msgid "Event" +msgstr "Evento" + +#: plugins/site_tour/views/box_organizer/site_tour_plugin/_tour_block.html.erb:41 +msgid "New Group Trigger" +msgstr "Novo Gatilho de Grupo" + +#: plugins/site_tour/views/blocks/tour.html.erb:4 +msgid "Help" +msgstr "Ajuda" + +#: plugins/site_tour/views/tour_actions.html.erb:16 +msgid "Next" +msgstr "Próximo" + +#: plugins/site_tour/views/tour_actions.html.erb:17 +msgid "Back" +msgstr "Anterior" + +#: plugins/site_tour/views/tour_actions.html.erb:18 +msgid "Skip" +msgstr "Pular" + +#: plugins/site_tour/views/tour_actions.html.erb:19 +msgid "Finish" +msgstr "Fim" + +#: plugins/site_tour/views/site_tour_plugin_admin/index.html.erb:1 +msgid "Site Tour Settings" +msgstr "Configurações do Site Tour" + +#: plugins/site_tour/views/site_tour_plugin_admin/index.html.erb:5 +msgid "Tooltips (CSV format: language, group name, selector, description)" +msgstr "Tooltips (Formato CSV: idioma, nome do grupo, seletor, descrição)" + +#: plugins/site_tour/views/site_tour_plugin_admin/index.html.erb:6 +msgid "" +"Group Triggers (CSV format: group name, selector, event (e.g. mouseenter, " +"click))" +msgstr "" +"Gatilhos dos grupos (Formato CSV: nome do grupo, seletor, evento (e.g. " +"mouseenter, click))" + +#: plugins/site_tour/views/site_tour_plugin_admin/index.html.erb:9 +msgid "Save" +msgstr "Salvar" diff --git a/plugins/site_tour/po/site_tour.pot b/plugins/site_tour/po/site_tour.pot new file mode 100644 index 0000000..a7b5034 --- /dev/null +++ b/plugins/site_tour/po/site_tour.pot @@ -0,0 +1,121 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: 1.2~rc1-2843-g999a037\n" +"POT-Creation-Date: 2015-08-06 08:53-0300\n" +"PO-Revision-Date: 2015-02-03 17:27-0300\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" + +#: plugins/site_tour/lib/site_tour_plugin.rb:8 +msgid "A site tour to show users how to use the application." +msgstr "" + +#: plugins/site_tour/lib/site_tour_plugin/tour_block.rb:3 +msgid "Click to start tour!" +msgstr "" + +#: plugins/site_tour/lib/site_tour_plugin/tour_block.rb:15 +msgid "Site Tour Block" +msgstr "" + +#: plugins/site_tour/lib/site_tour_plugin/tour_block.rb:19 +msgid "Configure a step-by-step tour." +msgstr "" + +#: plugins/site_tour/views/box_organizer/site_tour_plugin/_tour_block_item.html.erb:13 +#: plugins/site_tour/views/box_organizer/site_tour_plugin/_tour_block_group_item.html.erb:15 +msgid "Delete" +msgstr "" + +#: plugins/site_tour/views/box_organizer/site_tour_plugin/_tour_block.html.erb:4 +msgid "Display help button" +msgstr "" + +#: plugins/site_tour/views/box_organizer/site_tour_plugin/_tour_block.html.erb:8 +msgid "Tooltip Actions" +msgstr "" + +#: plugins/site_tour/views/box_organizer/site_tour_plugin/_tour_block.html.erb:9 +msgid "" +"Special fields for description: {profile.name}, {profile.identifier}, " +"{profile.url}." +msgstr "" + +#: plugins/site_tour/views/box_organizer/site_tour_plugin/_tour_block.html.erb:11 +#: plugins/site_tour/views/box_organizer/site_tour_plugin/_tour_block.html.erb:29 +msgid "Group Name" +msgstr "" + +#: plugins/site_tour/views/box_organizer/site_tour_plugin/_tour_block.html.erb:12 +#: plugins/site_tour/views/box_organizer/site_tour_plugin/_tour_block.html.erb:30 +msgid "Selector" +msgstr "" + +#: plugins/site_tour/views/box_organizer/site_tour_plugin/_tour_block.html.erb:13 +msgid "Description" +msgstr "" + +#: plugins/site_tour/views/box_organizer/site_tour_plugin/_tour_block.html.erb:23 +msgid "New Tooltip" +msgstr "" + +#: plugins/site_tour/views/box_organizer/site_tour_plugin/_tour_block.html.erb:27 +msgid "Group Triggers" +msgstr "" + +#: plugins/site_tour/views/box_organizer/site_tour_plugin/_tour_block.html.erb:31 +msgid "Event" +msgstr "" + +#: plugins/site_tour/views/box_organizer/site_tour_plugin/_tour_block.html.erb:41 +msgid "New Group Trigger" +msgstr "" + +#: plugins/site_tour/views/blocks/tour.html.erb:4 +msgid "Help" +msgstr "" + +#: plugins/site_tour/views/tour_actions.html.erb:16 +msgid "Next" +msgstr "" + +#: plugins/site_tour/views/tour_actions.html.erb:17 +msgid "Back" +msgstr "" + +#: plugins/site_tour/views/tour_actions.html.erb:18 +msgid "Skip" +msgstr "" + +#: plugins/site_tour/views/tour_actions.html.erb:19 +msgid "Finish" +msgstr "" + +#: plugins/site_tour/views/site_tour_plugin_admin/index.html.erb:1 +msgid "Site Tour Settings" +msgstr "" + +#: plugins/site_tour/views/site_tour_plugin_admin/index.html.erb:5 +msgid "Tooltips (CSV format: language, group name, selector, description)" +msgstr "" + +#: plugins/site_tour/views/site_tour_plugin_admin/index.html.erb:6 +msgid "" +"Group Triggers (CSV format: group name, selector, event (e.g. mouseenter, " +"click))" +msgstr "" + +#: plugins/site_tour/views/site_tour_plugin_admin/index.html.erb:9 +msgid "Save" +msgstr "" diff --git a/plugins/site_tour/public/edit_tour_block.css b/plugins/site_tour/public/edit_tour_block.css new file mode 100644 index 0000000..1b42fb7 --- /dev/null +++ b/plugins/site_tour/public/edit_tour_block.css @@ -0,0 +1,73 @@ +#edit-tour-block #tooltip-actions h3 { + margin-bottom: 5px; +} + +#edit-tour-block .special-attributes { + color: rgb(157, 157, 157); +} + +#edit-tour-block .list-items { + margin-bottom: 25px; +} + +#edit-tour-block .droppable-items { + padding-left: 0; + margin-top: -12px; +} + +#edit-tour-block .droppable-items li { + list-style-type: none; +} + +#edit-tour-block .item-row { + line-height: 25px; + margin-bottom: 5px; + padding: 0; + cursor: pointer; + width: 97%; +} + +#edit-tour-block .item-row:hover { + background: #ddd url(/images/drag-and-drop.png) no-repeat; + background-position: 98% 15px; +} + +#edit-tour-block .item-row li { + list-style-type: none; + display: inline; + margin-left: 5px; +} + +#edit-tour-block { + width: 620px; + position: relative; +} + +#edit-tour-block #new-template { + display: none; +} + +#edit-tour-block .list-header { + width: 98%; + padding: 0 1px 10px 10px; + margin-bottom: 5px; + cursor: pointer; +} + +#edit-tour-block .list-header li { + list-style-type: none; + display: inline; + font-weight: bold; + font-size: 12px; + text-align: center; +} + +#edit-tour-block .list-header .list-name { + margin-left: 20px; +} +#edit-tour-block .list-header .list-selector { + margin-left: 63px; +} +#edit-tour-block .list-header .list-description, #edit-tour-block .list-header .list-event { + margin-left: 68px; +} diff --git a/plugins/site_tour/public/edit_tour_block.js b/plugins/site_tour/public/edit_tour_block.js new file mode 100644 index 0000000..333e447 --- /dev/null +++ b/plugins/site_tour/public/edit_tour_block.js @@ -0,0 +1,18 @@ +jQuery(document).ready(function(){ + jQuery('#edit-tour-block').on('click', '.add-item', function() { + var container = jQuery(this).closest('.list-items'); + var new_action = container.find('#new-template>li').clone(); + new_action.show(); + container.find('.droppable-items').append(new_action); + }); + + jQuery('#edit-tour-block').on('click', '.delete-tour-block-item', function() { + jQuery(this).parent().parent().remove(); + return false; + }); + + jQuery("#edit-tour-block .droppable-items").sortable({ + revert: true, + axis: "y" + }); +}); diff --git a/plugins/site_tour/public/intro.min.js b/plugins/site_tour/public/intro.min.js new file mode 100644 index 0000000..d95cd0f --- /dev/null +++ b/plugins/site_tour/public/intro.min.js @@ -0,0 +1,33 @@ +(function(w,p){"object"===typeof exports?p(exports):"function"===typeof define&&define.amd?define(["exports"],p):p(w)})(this,function(w){function p(a){this._targetElement=a;this._options={nextLabel:"Next →",prevLabel:"← Back",skipLabel:"Skip",doneLabel:"Done",tooltipPosition:"bottom",tooltipClass:"",highlightClass:"",exitOnEsc:!0,exitOnOverlayClick:!0,showStepNumbers:!0,keyboardNavigation:!0,showButtons:!0,showBullets:!0,showProgress:!1,scrollToElement:!0,overlayOpacity:0.8,positionPrecedence:["bottom", +"top","right","left"],disableInteraction:!1}}function J(a){var b=[],c=this;if(this._options.steps)for(var d=[],e=0,d=this._options.steps.length;ed.length)return!1;e=0;for(f=d.length;eh.width||0>l.left+l.width/2-s?(q(f,"bottom"),q(f,"top")):(l.height+l.top+p>h.height&& +q(f,"bottom"),0>l.top-p&&q(f,"top"));l.width+l.left+s>h.width&&q(f,"right");0>l.left-s&&q(f,"left");0h.height&&(c.className="introjs-arrow left-bottom",b.style.top="-"+(f-e.height-20)+"px");c.className="introjs-arrow left"; +break;case "left":!0==this._options.showStepNumbers&&(b.style.top="15px");e.top+f>h.height?(b.style.top="-"+(f-e.height-20)+"px",c.className="introjs-arrow right-bottom"):c.className="introjs-arrow right";b.style.right=e.width+20+"px";break;case "floating":c.style.display="none";a=k(b);b.style.left="50%";b.style.top="50%";b.style.marginLeft="-"+a.width/2+"px";b.style.marginTop="-"+a.height/2+"px";"undefined"!=typeof d&&null!=d&&(d.style.left="-"+(a.width/2+18)+"px",d.style.top="-"+(a.height/2+18)+ +"px");break;case "bottom-right-aligned":c.className="introjs-arrow top-right";b.style.right="0px";b.style.bottom="-"+(k(b).height+10)+"px";break;case "bottom-middle-aligned":d=k(a);a=k(b);c.className="introjs-arrow top-middle";b.style.left=d.width/2-a.width/2+"px";b.style.bottom="-"+(a.height+10)+"px";break;default:b.style.bottom="-"+(k(b).height+10)+"px",b.style.left=k(a).width/2-k(b).width/2+"px",c.className="introjs-arrow top"}}}function q(a,b){-1 a.active").className="";d.querySelector('.introjs-bullets li > a[data-stepnumber="'+ +a.step+'"]').className="active";d.querySelector(".introjs-progress .introjs-progressbar").setAttribute("style","width:"+I.call(b)+"%;");s.style.opacity=1;f&&(f.style.opacity=1);-1===r.tabIndex?l.focus():r.focus()},350)}else{var q=document.createElement("div"),m=document.createElement("div"),c=document.createElement("div"),n=document.createElement("div"),w=document.createElement("div"),D=document.createElement("div"),E=document.createElement("div"),u=document.createElement("div");q.className=e;m.className= +"introjs-tooltipReferenceLayer";t.call(b,q);t.call(b,m);this._targetElement.appendChild(q);this._targetElement.appendChild(m);c.className="introjs-arrow";w.className="introjs-tooltiptext";w.innerHTML=a.intro;D.className="introjs-bullets";!1===this._options.showBullets&&(D.style.display="none");for(var q=document.createElement("ul"),e=0,B=this._introItems.length;en||"none"!==u)g.className+=" introjs-fixParent";g=g.parentNode}M(a.element)||!0!==this._options.scrollToElement||(n=a.element.getBoundingClientRect(),g=F().height,c=n.bottom-(n.bottom-n.top),n=n.bottom-g,0>c||a.element.clientHeight>g?window.scrollBy(0,c-30):window.scrollBy(0,n+100));"undefined"!== +typeof this._introAfterChangeCallback&&this._introAfterChangeCallback.call(this,a.element)}function v(a,b){var c="";a.currentStyle?c=a.currentStyle[b]:document.defaultView&&document.defaultView.getComputedStyle&&(c=document.defaultView.getComputedStyle(a,null).getPropertyValue(b));return c&&c.toLowerCase?c.toLowerCase():c}function F(){if(void 0!=window.innerWidth)return{width:window.innerWidth,height:window.innerHeight};var a=document.documentElement;return{width:a.clientWidth,height:a.clientHeight}} +function M(a){a=a.getBoundingClientRect();return 0<=a.top&&0<=a.left&&a.bottom+80<=window.innerHeight&&a.right<=window.innerWidth}function K(a){var b=document.createElement("div"),c="",d=this;b.className="introjs-overlay";if("body"===a.tagName.toLowerCase())c+="top: 0;bottom: 0; left: 0;right: 0;position: fixed;",b.setAttribute("style",c);else{var e=k(a);e&&(c+="width: "+e.width+"px; height:"+e.height+"px; top:"+e.top+"px;left: "+e.left+"px;",b.setAttribute("style",c))}a.appendChild(b);b.onclick= +function(){!0==d._options.exitOnOverlayClick&&(y.call(d,a),void 0!=d._introExitCallback&&d._introExitCallback.call(d))};setTimeout(function(){c+="opacity: "+d._options.overlayOpacity.toString()+";";b.setAttribute("style",c)},10);return!0}function k(a){var b={};b.width=a.offsetWidth;b.height=a.offsetHeight;for(var c=0,d=0;a&&!isNaN(a.offsetLeft)&&!isNaN(a.offsetTop);)c+=a.offsetLeft,d+=a.offsetTop,a=a.offsetParent;b.top=d;b.left=c;return b}function I(){return 100*(parseInt(this._currentStep+1,10)/ +this._introItems.length)}var B=function(a){if("object"===typeof a)return new p(a);if("string"===typeof a){if(a=document.querySelector(a))return new p(a);throw Error("There is no element with given selector.");}return new p(document.body)};B.version="1.0.0";B.fn=p.prototype={clone:function(){return new p(this)},setOption:function(a,b){this._options[a]=b;return this},setOptions:function(a){var b=this._options,c={},d;for(d in b)c[d]=b[d];for(d in a)c[d]=a[d];this._options=c;return this},start:function(){J.call(this, +this._targetElement);return this},goToStep:function(a){this._currentStep=a-2;"undefined"!==typeof this._introItems&&x.call(this);return this},nextStep:function(){x.call(this);return this},previousStep:function(){C.call(this);return this},exit:function(){y.call(this,this._targetElement);return this},refresh:function(){t.call(this,document.querySelector(".introjs-helperLayer"));t.call(this,document.querySelector(".introjs-tooltipReferenceLayer"));return this},onbeforechange:function(a){if("function"=== +typeof a)this._introBeforeChangeCallback=a;else throw Error("Provided callback for onbeforechange was not a function");return this},onchange:function(a){if("function"===typeof a)this._introChangeCallback=a;else throw Error("Provided callback for onchange was not a function.");return this},onafterchange:function(a){if("function"===typeof a)this._introAfterChangeCallback=a;else throw Error("Provided callback for onafterchange was not a function");return this},oncomplete:function(a){if("function"=== +typeof a)this._introCompleteCallback=a;else throw Error("Provided callback for oncomplete was not a function.");return this},onexit:function(a){if("function"===typeof a)this._introExitCallback=a;else throw Error("Provided callback for onexit was not a function.");return this}};return w.introJs=B}); diff --git a/plugins/site_tour/public/introjs.min.css b/plugins/site_tour/public/introjs.min.css new file mode 100644 index 0000000..94afec6 --- /dev/null +++ b/plugins/site_tour/public/introjs.min.css @@ -0,0 +1 @@ +.introjs-overlay{position:absolute;z-index:999999;background-color:#000;opacity:0;background:-moz-radial-gradient(center,ellipse cover,rgba(0,0,0,0.4) 0,rgba(0,0,0,0.9) 100%);background:-webkit-gradient(radial,center center,0px,center center,100%,color-stop(0%,rgba(0,0,0,0.4)),color-stop(100%,rgba(0,0,0,0.9)));background:-webkit-radial-gradient(center,ellipse cover,rgba(0,0,0,0.4) 0,rgba(0,0,0,0.9) 100%);background:-o-radial-gradient(center,ellipse cover,rgba(0,0,0,0.4) 0,rgba(0,0,0,0.9) 100%);background:-ms-radial-gradient(center,ellipse cover,rgba(0,0,0,0.4) 0,rgba(0,0,0,0.9) 100%);background:radial-gradient(center,ellipse cover,rgba(0,0,0,0.4) 0,rgba(0,0,0,0.9) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#66000000',endColorstr='#e6000000',GradientType=1);-ms-filter:"alpha(opacity=50)";filter:alpha(opacity=50);-webkit-transition:all .3s ease-out;-moz-transition:all .3s ease-out;-ms-transition:all .3s ease-out;-o-transition:all .3s ease-out;transition:all .3s ease-out}.introjs-fixParent{z-index:auto!important;opacity:1.0!important;position:absolute!important;-webkit-transform:none!important;-moz-transform:none!important;-ms-transform:none!important;-o-transform:none!important;transform:none!important}.introjs-showElement,tr.introjs-showElement>td,tr.introjs-showElement>th{z-index:9999999!important}.introjs-disableInteraction{z-index:99999999!important;position:absolute}.introjs-relativePosition,tr.introjs-showElement>td,tr.introjs-showElement>th{position:relative}.introjs-helperLayer{position:absolute;z-index:9999998;background-color:#FFF;background-color:rgba(255,255,255,.9);border:1px solid #777;border:1px solid rgba(0,0,0,.5);border-radius:4px;box-shadow:0 2px 15px rgba(0,0,0,.4);-webkit-transition:all .3s ease-out;-moz-transition:all .3s ease-out;-ms-transition:all .3s ease-out;-o-transition:all .3s ease-out;transition:all .3s ease-out}.introjs-tooltipReferenceLayer{position:absolute;z-index:10000000;background-color:transparent;-webkit-transition:all .3s ease-out;-moz-transition:all .3s ease-out;-ms-transition:all .3s ease-out;-o-transition:all .3s ease-out;transition:all .3s ease-out}.introjs-helperLayer *,.introjs-helperLayer *:before,.introjs-helperLayer *:after{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;-ms-box-sizing:content-box;-o-box-sizing:content-box;box-sizing:content-box}.introjs-helperNumberLayer{position:absolute;top:-16px;left:-16px;z-index:9999999999!important;padding:2px;font-family:Arial,verdana,tahoma;font-size:13px;font-weight:bold;color:white;text-align:center;text-shadow:1px 1px 1px rgba(0,0,0,.3);background:#ff3019;background:-webkit-linear-gradient(top,#ff3019 0,#cf0404 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0%,#ff3019),color-stop(100%,#cf0404));background:-moz-linear-gradient(top,#ff3019 0,#cf0404 100%);background:-ms-linear-gradient(top,#ff3019 0,#cf0404 100%);background:-o-linear-gradient(top,#ff3019 0,#cf0404 100%);background:linear-gradient(to bottom,#ff3019 0,#cf0404 100%);width:20px;height:20px;line-height:20px;border:3px solid white;border-radius:50%;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3019',endColorstr='#cf0404',GradientType=0);filter:progid:DXImageTransform.Microsoft.Shadow(direction=135,strength=2,color=ff0000);box-shadow:0 2px 5px rgba(0,0,0,.4)}.introjs-arrow{border:5px solid white;content:'';position:absolute}.introjs-arrow.top{top:-10px;border-top-color:transparent;border-right-color:transparent;border-bottom-color:white;border-left-color:transparent}.introjs-arrow.top-right{top:-10px;right:10px;border-top-color:transparent;border-right-color:transparent;border-bottom-color:white;border-left-color:transparent}.introjs-arrow.top-middle{top:-10px;left:50%;margin-left:-5px;border-top-color:transparent;border-right-color:transparent;border-bottom-color:white;border-left-color:transparent}.introjs-arrow.right{right:-10px;top:10px;border-top-color:transparent;border-right-color:transparent;border-bottom-color:transparent;border-left-color:white}.introjs-arrow.right-bottom{bottom:10px;right:-10px;border-top-color:transparent;border-right-color:transparent;border-bottom-color:transparent;border-left-color:white}.introjs-arrow.bottom{bottom:-10px;border-top-color:white;border-right-color:transparent;border-bottom-color:transparent;border-left-color:transparent}.introjs-arrow.left{left:-10px;top:10px;border-top-color:transparent;border-right-color:white;border-bottom-color:transparent;border-left-color:transparent}.introjs-arrow.left-bottom{left:-10px;bottom:10px;border-top-color:transparent;border-right-color:white;border-bottom-color:transparent;border-left-color:transparent}.introjs-tooltip{position:absolute;padding:10px;background-color:white;min-width:200px;max-width:300px;border-radius:3px;box-shadow:0 1px 10px rgba(0,0,0,.4);-webkit-transition:opacity .1s ease-out;-moz-transition:opacity .1s ease-out;-ms-transition:opacity .1s ease-out;-o-transition:opacity .1s ease-out;transition:opacity .1s ease-out}.introjs-tooltipbuttons{text-align:right;white-space:nowrap}.introjs-button{position:relative;overflow:visible;display:inline-block;padding:.3em .8em;border:1px solid #d4d4d4;margin:0;text-decoration:none;text-shadow:1px 1px 0 #fff;font:11px/normal sans-serif;color:#333;white-space:nowrap;cursor:pointer;outline:0;background-color:#ececec;background-image:-webkit-gradient(linear,0 0,0 100%,from(#f4f4f4),to(#ececec));background-image:-moz-linear-gradient(#f4f4f4,#ececec);background-image:-o-linear-gradient(#f4f4f4,#ececec);background-image:linear-gradient(#f4f4f4,#ececec);-webkit-background-clip:padding;-moz-background-clip:padding;-o-background-clip:padding-box;-webkit-border-radius:.2em;-moz-border-radius:.2em;border-radius:.2em;zoom:1;*display:inline;margin-top:10px}.introjs-button:hover{border-color:#bcbcbc;text-decoration:none;box-shadow:0 1px 1px #e3e3e3}.introjs-button:focus,.introjs-button:active{background-image:-webkit-gradient(linear,0 0,0 100%,from(#ececec),to(#f4f4f4));background-image:-moz-linear-gradient(#ececec,#f4f4f4);background-image:-o-linear-gradient(#ececec,#f4f4f4);background-image:linear-gradient(#ececec,#f4f4f4)}.introjs-button::-moz-focus-inner{padding:0;border:0}.introjs-skipbutton{margin-right:5px;color:#7a7a7a}.introjs-prevbutton{-webkit-border-radius:.2em 0 0 .2em;-moz-border-radius:.2em 0 0 .2em;border-radius:.2em 0 0 .2em;border-right:0}.introjs-nextbutton{-webkit-border-radius:0 .2em .2em 0;-moz-border-radius:0 .2em .2em 0;border-radius:0 .2em .2em 0}.introjs-disabled,.introjs-disabled:hover,.introjs-disabled:focus{color:#9a9a9a;border-color:#d4d4d4;box-shadow:none;cursor:default;background-color:#f4f4f4;background-image:none;text-decoration:none}.introjs-bullets{text-align:center}.introjs-bullets ul{clear:both;margin:15px auto 0;padding:0;display:inline-block}.introjs-bullets ul li{list-style:none;float:left;margin:0 2px}.introjs-bullets ul li a{display:block;width:6px;height:6px;background:#ccc;border-radius:10px;-moz-border-radius:10px;-webkit-border-radius:10px;text-decoration:none}.introjs-bullets ul li a:hover{background:#999}.introjs-bullets ul li a.active{background:#999}.introjs-progress{overflow:hidden;height:10px;margin:10px 0 5px 0;border-radius:4px;background-color:#ecf0f1}.introjs-progressbar{float:left;width:0;height:100%;font-size:10px;line-height:10px;text-align:center;background-color:#08c}.introjsFloatingElement{position:absolute;height:0;width:0;left:50%;top:50%} \ No newline at end of file diff --git a/plugins/site_tour/public/main.js b/plugins/site_tour/public/main.js new file mode 100644 index 0000000..8f84d4b --- /dev/null +++ b/plugins/site_tour/public/main.js @@ -0,0 +1,99 @@ +var siteTourPlugin = (function() { + + var actions = []; + var groupTriggers = []; + var userData = {}; + var intro; + var options = {}; + + function hasMark(name) { + return jQuery.cookie("_noosfero_.sitetour." + name) || + jQuery.inArray(name, userData.site_tour_plugin_actions)>=0; + } + + function mark(name) { + jQuery.cookie("_noosfero_.sitetour." + name, 1, {expires: 365}); + if(userData.login) { + jQuery.post('/plugin/site_tour/public/mark_action', {action_name: name}, function(data) { }); + } + } + + function clearAll() { + jQuery('.site-tour-plugin').removeAttr('data-intro data-intro-name data-step'); + } + + function configureIntro(force, actions) { + clearAll(); + for(var i=0; i {"actions_csv" => actions_csv} + @settings = Noosfero::Plugin::Settings.new(environment.reload, SiteTourPlugin) + assert_equal [{:language => 'en', :group_name => 'tour_plugin', :selector => '.tour-button', :description => 'Click'}], @settings.actions + end + + should 'parse csv and save group triggers array in plugin settings' do + group_triggers_csv = "tour_plugin,.tour-button,mouseenter" + post :index, :settings => {"group_triggers_csv" => group_triggers_csv} + @settings = Noosfero::Plugin::Settings.new(environment.reload, SiteTourPlugin) + assert_equal [{:group_name => 'tour_plugin', :selector => '.tour-button', :event => 'mouseenter'}], @settings.group_triggers + end + + should 'do not store actions_csv' do + actions_csv = "en,tour_plugin,.tour-button,Click" + post :index, :settings => {"actions_csv" => actions_csv} + @settings = Noosfero::Plugin::Settings.new(environment.reload, SiteTourPlugin) + assert_equal nil, @settings.settings[:actions_csv] + end + + should 'do not store group_triggers_csv' do + group_triggers_csv = "tour_plugin,.tour-button,click" + post :index, :settings => {"group_triggers_csv" => group_triggers_csv} + @settings = Noosfero::Plugin::Settings.new(environment.reload, SiteTourPlugin) + assert_equal nil, @settings.settings[:group_triggers_csv] + end + + should 'convert actions array to csv to enable user edition' do + @settings = Noosfero::Plugin::Settings.new(environment.reload, SiteTourPlugin) + @settings.actions = [{:language => 'en', :group_name => 'tour_plugin', :selector => '.tour-button', :description => 'Click'}] + @settings.save! + + get :index + assert_tag :tag => 'textarea', :attributes => {:class => 'actions-csv'}, :content => "\nen,tour_plugin,.tour-button,Click\n" + end + + should 'convert group_triggers array to csv to enable user edition' do + @settings = Noosfero::Plugin::Settings.new(environment.reload, SiteTourPlugin) + @settings.group_triggers = [{:group_name => 'tour_plugin', :selector => '.tour-button', :event => 'click'}] + @settings.save! + + get :index + assert_tag :tag => 'textarea', :attributes => {:class => 'groups-csv'}, :content => "\ntour_plugin,.tour-button,click\n" + end + +end diff --git a/plugins/site_tour/test/functional/site_tour_plugin_public_controller_test.rb b/plugins/site_tour/test/functional/site_tour_plugin_public_controller_test.rb new file mode 100644 index 0000000..416d4e2 --- /dev/null +++ b/plugins/site_tour/test/functional/site_tour_plugin_public_controller_test.rb @@ -0,0 +1,30 @@ +require File.dirname(__FILE__) + '/../test_helper' + +class SiteTourPluginPublicControllerTest < ActionController::TestCase + + def setup + @person = create_user('testuser').person + end + + attr_accessor :person + + should 'not be able to mark an action if is not logged in' do + xhr :post, :mark_action, :action_name => 'test' + assert_response 401 + end + + should 'be able to mark one action' do + login_as(person.identifier) + xhr :post, :mark_action, :action_name => 'test' + assert_equal({'ok' => true}, ActiveSupport::JSON.decode(response.body)) + assert_equal ['test'], person.reload.site_tour_plugin_actions + end + + should 'be able to mark multiple actions' do + login_as(person.identifier) + xhr :post, :mark_action, :action_name => ['test1', 'test2'] + assert_equal({'ok' => true}, ActiveSupport::JSON.decode(response.body)) + assert_equal ['test1', 'test2'], person.reload.site_tour_plugin_actions + end + +end diff --git a/plugins/site_tour/test/test_helper.rb b/plugins/site_tour/test/test_helper.rb new file mode 100644 index 0000000..cca1fd3 --- /dev/null +++ b/plugins/site_tour/test/test_helper.rb @@ -0,0 +1 @@ +require File.dirname(__FILE__) + '/../../../test/test_helper' diff --git a/plugins/site_tour/test/unit/site_tour_helper_test.rb b/plugins/site_tour/test/unit/site_tour_helper_test.rb new file mode 100644 index 0000000..fcca9d7 --- /dev/null +++ b/plugins/site_tour/test/unit/site_tour_helper_test.rb @@ -0,0 +1,17 @@ +require File.dirname(__FILE__) + '/../test_helper' + +class SiteTourHelperTest < ActionView::TestCase + + include SiteTourPlugin::SiteTourHelper + + should 'parse tooltip description' do + assert_equal 'test', parse_tour_description("test") + end + + should 'replace profile attributes in tooltip description' do + profile = fast_create(Profile) + expects(:profile).returns(profile).at_least_once + assert_equal "name #{profile.name}, identifier #{profile.identifier}, url #{url_for profile.url}", parse_tour_description("name {profile.name}, identifier {profile.identifier}, url {profile.url}") + end + +end diff --git a/plugins/site_tour/test/unit/site_tour_plugin_test.rb b/plugins/site_tour/test/unit/site_tour_plugin_test.rb new file mode 100644 index 0000000..cefd3bf --- /dev/null +++ b/plugins/site_tour/test/unit/site_tour_plugin_test.rb @@ -0,0 +1,73 @@ +require File.dirname(__FILE__) + '/../test_helper' + +class SiteTourPluginTest < ActionView::TestCase + + def setup + @plugin = SiteTourPlugin.new + end + + attr_accessor :plugin + + should 'include site tour plugin actions in user data for logged in users' do + expects(:logged_in?).returns(true) + person = create_user('testuser').person + person.site_tour_plugin_actions = ['login', 'navigation'] + expects(:user).returns(person) + + assert_equal({:site_tour_plugin_actions => ['login', 'navigation']}, instance_eval(&plugin.user_data_extras)) + end + + should 'return empty hash when user is not logged in' do + expects(:logged_in?).returns(false) + assert_equal({}, instance_eval(&plugin.user_data_extras)) + end + + should 'include javascript related to tour instructions if file exists' do + file = '/plugins/site_tour/tour/pt/tour.js' + expects(:language).returns('pt') + File.expects(:exists?).with(Rails.root.join("public#{file}").to_s).returns(true) + expects(:environment).returns(Environment.default) + assert_tag_in_string instance_exec(&plugin.body_ending), :tag => 'script' + end + + should 'not include javascript file that not exists' do + file = '/plugins/site_tour/tour/pt/tour.js' + expects(:language).returns('pt') + File.expects(:exists?).with(Rails.root.join("public#{file}").to_s).returns(false) + expects(:environment).returns(Environment.default) + assert_no_tag_in_string instance_exec(&plugin.body_ending), :tag => "script" + end + + should 'render javascript tag with tooltip actions and group triggers' do + expects(:language).returns('en').at_least_once + + settings = Noosfero::Plugin::Settings.new(Environment.default, SiteTourPlugin) + settings.actions = [{:language => 'en', :group_name => 'test', :selector => 'body', :description => 'Test'}] + settings.group_triggers = [{:group_name => 'test', :selector => 'body', :event => 'click'}] + settings.save! + + expects(:environment).returns(Environment.default) + body_ending = instance_exec(&plugin.body_ending) + assert_match /siteTourPlugin\.add\('test', 'body', 'Test', 1\);/, body_ending + assert_match /siteTourPlugin\.addGroupTrigger\('test', 'body', 'click'\);/, body_ending + end + + should 'start each tooltip group with the correct step order' do + expects(:language).returns('en').at_least_once + + settings = Noosfero::Plugin::Settings.new(Environment.default, SiteTourPlugin) + settings.actions = [ + {:language => 'en', :group_name => 'test_a', :selector => 'body', :description => 'Test A1'}, + {:language => 'en', :group_name => 'test_a', :selector => 'body', :description => 'Test A2'}, + {:language => 'en', :group_name => 'test_b', :selector => 'body', :description => 'Test B1'}, + ] + settings.save! + + expects(:environment).returns(Environment.default) + body_ending = instance_exec(&plugin.body_ending) + assert_match /siteTourPlugin\.add\('test_a', 'body', 'Test A1', 1\);/, body_ending + assert_match /siteTourPlugin\.add\('test_a', 'body', 'Test A2', 2\);/, body_ending + assert_match /siteTourPlugin\.add\('test_b', 'body', 'Test B1', 3\);/, body_ending + end + +end diff --git a/plugins/site_tour/test/unit/tour_block_test.rb b/plugins/site_tour/test/unit/tour_block_test.rb new file mode 100644 index 0000000..46e9dbb --- /dev/null +++ b/plugins/site_tour/test/unit/tour_block_test.rb @@ -0,0 +1,41 @@ +require File.dirname(__FILE__) + '/../test_helper' + +class TrackListBlockTest < ActionView::TestCase + + ActionView::Base.send :include, ApplicationHelper + + def setup + @block = fast_create(SiteTourPlugin::TourBlock) + end + + attr_accessor :block + + should 'do not save empty actions' do + block.actions = [{:group_name => '', :selector => nil, :description => ' '}] + block.save! + assert_equal [], block.actions + end + + should 'render script tag in visualization mode' do + controller.expects(:boxes_editor?).returns(false) + assert_tag_in_string instance_eval(&block.content), :tag => 'script' + end + + should 'do not render script tag when editing' do + controller.expects(:boxes_editor?).returns(true) + controller.expects(:uses_design_blocks?).returns(true) + assert_no_tag_in_string instance_eval(&block.content), :tag => 'script' + end + + should 'display help button' do + controller.expects(:boxes_editor?).returns(false) + assert_tag_in_string instance_eval(&block.content), :tag => 'a', :attributes => {:class => 'button icon-help with-text tour-button'} + end + + should 'do not display help button when display_button is false' do + block.display_button = false + controller.expects(:boxes_editor?).returns(false) + assert_no_tag_in_string instance_eval(&block.content), :tag => 'a', :attributes => {:class => 'button icon-help with-text tour-button'} + end + +end diff --git a/plugins/site_tour/views/blocks/tour.html.erb b/plugins/site_tour/views/blocks/tour.html.erb new file mode 100644 index 0000000..1b7088b --- /dev/null +++ b/plugins/site_tour/views/blocks/tour.html.erb @@ -0,0 +1,11 @@ +<%= block_title(block.title) %> + +<% if block.display_button %> + <%= button :help, _('Help'), '#', :class => 'tour-button', :onclick => 'siteTourPlugin.force();' %> +<% end %> + +<% edit_mode = controller.send(:boxes_editor?) && controller.send(:uses_design_blocks?) %> + +<% unless edit_mode %> + <%= render :file => 'tour_actions', :locals => {:actions => block.actions, :group_triggers => block.group_triggers} %> +<% end %> diff --git a/plugins/site_tour/views/box_organizer/site_tour_plugin/_tour_block.html.erb b/plugins/site_tour/views/box_organizer/site_tour_plugin/_tour_block.html.erb new file mode 100644 index 0000000..36b2090 --- /dev/null +++ b/plugins/site_tour/views/box_organizer/site_tour_plugin/_tour_block.html.erb @@ -0,0 +1,44 @@ +<%= javascript_include_tag '/plugins/site_tour/edit_tour_block.js' %> +<%= stylesheet_link_tag '/plugins/site_tour/edit_tour_block.css' %> + +<%= labelled_form_field check_box(:block, :display_button) + _('Display help button'), '' %> + +
+
+

<%= _('Tooltip Actions') %>

+
<%= _('Special fields for description: {profile.name}, {profile.identifier}, {profile.url}.') %>
+
    +
  • <%= _('Group Name') %>
  • +
  • <%= _('Selector') %>
  • +
  • <%= _('Description') %>
  • +
+
    + <% for action in @block.actions do %> + <%= render :partial => 'box_organizer/site_tour_plugin/tour_block_item', :locals => {:action => action} %> + <% end %> +
+
+ <%= render :partial => 'box_organizer/site_tour_plugin/tour_block_item', :locals => {:action => {} } %> +
+ <%= link_to_function(_('New Tooltip'), :class => 'add-item button icon-add with-text') %> +
+ +
+

<%= _('Group Triggers') %>

+
    +
  • <%= _('Group Name') %>
  • +
  • <%= _('Selector') %>
  • +
  • <%= _('Event') %>
  • +
+
    + <% for group in @block.group_triggers do %> + <%= render :partial => 'box_organizer/site_tour_plugin/tour_block_group_item', :locals => {:group => group} %> + <% end %> +
+
+ <%= render :partial => 'box_organizer/site_tour_plugin/tour_block_group_item', :locals => {:group => {} } %> +
+ <%= link_to_function(_('New Group Trigger'), :class => 'add-item button icon-add with-text') %> +
+ +
diff --git a/plugins/site_tour/views/box_organizer/site_tour_plugin/_tour_block_group_item.html.erb b/plugins/site_tour/views/box_organizer/site_tour_plugin/_tour_block_group_item.html.erb new file mode 100644 index 0000000..e1f1dea --- /dev/null +++ b/plugins/site_tour/views/box_organizer/site_tour_plugin/_tour_block_group_item.html.erb @@ -0,0 +1,19 @@ +
  • +
      +
    • + <%= text_field_tag 'block[group_triggers][][group_name]', group[:group_name], :class => 'group-name', :maxlength => 20 %> +
    • +
    • + <%= text_field_tag 'block[group_triggers][][selector]', group[:selector], :class => 'selector' %> +
    • +
    • + <%= select_tag 'block[group_triggers][][event]', + options_for_select(['mouseenter', 'mouseleave', 'mouseover', 'mouseout', 'click', 'change', 'select', 'keydown', 'keyup', 'keypress', 'focus', 'blur', 'submit', 'drag', 'drop'], group[:event]), + :class => 'description' %> +
    • +
    • + <%= button_without_text(:delete, _('Delete'), "#" , :class=>"delete-tour-block-item") %> +
    • +
    +
  • + diff --git a/plugins/site_tour/views/box_organizer/site_tour_plugin/_tour_block_item.html.erb b/plugins/site_tour/views/box_organizer/site_tour_plugin/_tour_block_item.html.erb new file mode 100644 index 0000000..41cac8d --- /dev/null +++ b/plugins/site_tour/views/box_organizer/site_tour_plugin/_tour_block_item.html.erb @@ -0,0 +1,16 @@ +
  • +
      +
    • + <%= text_field_tag 'block[actions][][group_name]', action[:group_name], :class => 'group-name', :maxlength => 20 %> +
    • +
    • + <%= text_field_tag 'block[actions][][selector]', action[:selector], :class => 'selector' %> +
    • +
    • + <%= text_field_tag 'block[actions][][description]', action[:description], :class => 'description' %> +
    • +
    • + <%= button_without_text(:delete, _('Delete'), "#" , :class=>"delete-tour-block-item") %> +
    • +
    +
  • diff --git a/plugins/site_tour/views/environment_design/site_tour_plugin b/plugins/site_tour/views/environment_design/site_tour_plugin new file mode 120000 index 0000000..5dcaba9 --- /dev/null +++ b/plugins/site_tour/views/environment_design/site_tour_plugin @@ -0,0 +1 @@ +../box_organizer/site_tour_plugin \ No newline at end of file diff --git a/plugins/site_tour/views/profile_design/site_tour_plugin b/plugins/site_tour/views/profile_design/site_tour_plugin new file mode 120000 index 0000000..5dcaba9 --- /dev/null +++ b/plugins/site_tour/views/profile_design/site_tour_plugin @@ -0,0 +1 @@ +../box_organizer/site_tour_plugin \ No newline at end of file diff --git a/plugins/site_tour/views/site_tour_plugin_admin/index.html.erb b/plugins/site_tour/views/site_tour_plugin_admin/index.html.erb new file mode 100644 index 0000000..bba26a5 --- /dev/null +++ b/plugins/site_tour/views/site_tour_plugin_admin/index.html.erb @@ -0,0 +1,13 @@ +

    <%= _('Site Tour Settings')%>

    + +<%= form_for(:settings) do |f| %> + + <%= labelled_form_field _('Tooltips (CSV format: language, group name, selector, description)'), f.text_area(:actions_csv, :style => 'width: 100%', :class => 'actions-csv') %> + <%= labelled_form_field _('Group Triggers (CSV format: group name, selector, event (e.g. mouseenter, click))'), f.text_area(:group_triggers_csv, :style => 'width: 100%', :class => 'groups-csv', :rows => 7) %> + + <% button_bar do %> + <%= submit_button(:save, _('Save'), :cancel => {:controller => 'plugins', :action => 'index'}) %> + <% end %> + +<% end %> + diff --git a/plugins/site_tour/views/tour_actions.html.erb b/plugins/site_tour/views/tour_actions.html.erb new file mode 100644 index 0000000..f2e8371 --- /dev/null +++ b/plugins/site_tour/views/tour_actions.html.erb @@ -0,0 +1,22 @@ +<% extend SiteTourPlugin::SiteTourHelper %> +<% js_file = defined?(:js_file) ? js_file : nil %> +<%= javascript_include_tag(js_file) if js_file.present? %> + +<% if actions.present? %> + +<% end %> -- libgit2 0.21.2