| @@ -0,0 +1,62 @@ | ||
| // Chosen CSS Tweaks | ||
| //------------------------------------------------------------------------------ | ||
| .chzn-container | ||
| margin-top: 3px | ||
| margin-left: -1px | ||
|
|
||
| .chzn-container .chzn-results li | ||
| line-height: 15px | ||
| padding: 4px 7px 4px | ||
| border-bottom: none | ||
|
|
||
|
|
||
| // Multiselect | ||
| //------------------------------------------------------------------------------ | ||
| .chzn-container-multi .chzn-choices li | ||
| clear: none | ||
|
|
||
| .chzn-container-multi .chzn-choices .search-field input | ||
| height: auto | ||
|
|
||
|
|
||
| // Single select | ||
| //------------------------------------------------------------------------------ | ||
| .chzn-container-single .chzn-single | ||
| height: 21px | ||
| line-height: 21px | ||
|
|
||
| .chzn-container-single .chzn-single div b | ||
| background-position-y: -1px | ||
|
|
||
| .chzn-container-single .chzn-single abbr | ||
| top: 5px | ||
|
|
||
|
|
||
| // Basic styling for standard selects and other inputs | ||
| //------------------------------------------------------------------------------ | ||
| input | ||
| height: 17px | ||
| font-size: 13px | ||
|
|
||
| input[type=submit] | ||
| height: auto | ||
|
|
||
| select | ||
| height: 23px | ||
| color: #444 | ||
| background-color: #fff | ||
| background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eeeeee), color-stop(0.5, white)) | ||
| background-image: -webkit-linear-gradient(center bottom, #eeeeee 0%, white 50%) | ||
| background-image: -moz-linear-gradient(center bottom, #eeeeee 0%, white 50%) | ||
| background-image: -o-linear-gradient(top, #eeeeee 0%, white 50%) | ||
| background-image: -ms-linear-gradient(top, #eeeeee 0%, white 50%) | ||
| filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#eeeeee', endColorstr='#ffffff',GradientType=0 ) | ||
| background-image: linear-gradient(top, #eeeeee 0%, white 50%) | ||
| -webkit-border-radius: 4px | ||
| -moz-border-radius: 4px | ||
| border-radius: 4px | ||
| -moz-background-clip: padding | ||
| -webkit-background-clip: padding-box | ||
| background-clip: padding-box | ||
| border: 1px solid #aaa |
| @@ -0,0 +1,8 @@ | ||
| .field_group .list | ||
| padding-bottom: 30px | ||
|
|
||
| .fields .subtitle | ||
| cursor: move | ||
|
|
||
| .fields .title | ||
| margin-bottom: 12px |
| @@ -0,0 +1,3 @@ | ||
| // Place all the styles related to the Lists controller here. | ||
| // They will automatically be included in application.css. | ||
| // You can use Sass (SCSS) here: http://sass-lang.com/ |
| @@ -0,0 +1,131 @@ | ||
| # Fat Free CRM | ||
| # Copyright (C) 2008-2011 by Michael Dvorkin | ||
| # | ||
| # This program is free software: you can redistribute it and/or modify | ||
| # it under the terms of the GNU Affero General Public License as published by | ||
| # the Free Software Foundation, either version 3 of the License, or | ||
| # (at your option) any later version. | ||
| # | ||
| # This program is distributed in the hope that it will be useful, | ||
| # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| # GNU Affero General Public License for more details. | ||
| # | ||
| # You should have received a copy of the GNU Affero General Public License | ||
| # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| #------------------------------------------------------------------------------ | ||
|
|
||
| class Admin::TagsController < Admin::ApplicationController | ||
| before_filter "set_current_tab('admin/tags')", :only => [ :index, :show ] | ||
|
|
||
| # GET /admin/tags | ||
| # GET /admin/tags.xml HTML | ||
| #---------------------------------------------------------------------------- | ||
| def index | ||
| @tags = Tag.all | ||
|
|
||
| respond_to do |format| | ||
| format.html # index.html.haml | ||
| format.js # index.js.rjs | ||
| format.xml { render :xml => Tag.all } | ||
| format.xls { send_data @tags.to_xls, :type => :xls } | ||
| format.csv { send_data @tags.to_csv, :type => :csv } | ||
| format.rss { render "shared/index.rss.builder" } | ||
| format.atom { render "shared/index.atom.builder" } | ||
| end | ||
| end | ||
|
|
||
| # GET /admin/tags/new | ||
| # GET /admin/tags/new.xml AJAX | ||
| #---------------------------------------------------------------------------- | ||
| def new | ||
| @tag = Tag.new | ||
|
|
||
| respond_to do |format| | ||
| format.js # new.js.rjs | ||
| format.xml { render :xml => @tag } | ||
| end | ||
| end | ||
|
|
||
| # GET /admin/tags/1/edit AJAX | ||
| #---------------------------------------------------------------------------- | ||
| def edit | ||
| @tag = Tag.find(params[:id]) | ||
|
|
||
| if params[:previous].to_s =~ /(\d+)\z/ | ||
| @previous = Tag.find($1) | ||
| end | ||
|
|
||
| rescue ActiveRecord::RecordNotFound | ||
| @previous ||= $1.to_i | ||
| respond_to_not_found(:js) unless @tag | ||
| end | ||
|
|
||
| # POST /admin/tags | ||
| # POST /admin/tags.xml AJAX | ||
| #---------------------------------------------------------------------------- | ||
| def create | ||
| @tag = Tag.new(params[:tag]) | ||
|
|
||
| respond_to do |format| | ||
| if @tag.save | ||
| @tags = Tag.all | ||
| format.js # create.js.rjs | ||
| format.xml { render :xml => @tag, :status => :created, :location => @tag } | ||
| else | ||
| format.js # create.js.rjs | ||
| format.xml { render :xml => @tag.errors, :status => :unprocessable_entity } | ||
| end | ||
| end | ||
| end | ||
|
|
||
| # PUT /admin/tags/1 | ||
| # PUT /admin/tags/1.xml AJAX | ||
| #---------------------------------------------------------------------------- | ||
| def update | ||
| @tag = Tag.find(params[:id]) | ||
|
|
||
| respond_to do |format| | ||
| if @tag.update_attributes(params[:tag]) | ||
| format.js # update.js.rjs | ||
| format.xml { head :ok } | ||
| else | ||
| format.js # update.js.rjs | ||
| format.xml { render :xml => @tag.errors, :status => :unprocessable_entity } | ||
| end | ||
| end | ||
|
|
||
| rescue ActiveRecord::RecordNotFound | ||
| respond_to_not_found(:js, :xml) | ||
| end | ||
|
|
||
|
|
||
| # DELETE /admin/tags/1 | ||
| # DELETE /admin/tags/1.xml AJAX | ||
| #---------------------------------------------------------------------------- | ||
| def destroy | ||
| @tag = Tag.find(params[:id]) | ||
|
|
||
| respond_to do |format| | ||
| if @tag.destroy | ||
| format.js # destroy.js.rjs | ||
| format.xml { head :ok } | ||
| else | ||
| flash[:warning] = t(:msg_cant_delete_tag, @tag.name) | ||
| format.js # destroy.js.rjs | ||
| format.xml { render :xml => @tag.errors, :status => :unprocessable_entity } | ||
| end | ||
| end | ||
| end | ||
|
|
||
| # GET /admin/tags/1/confirm AJAX | ||
| #---------------------------------------------------------------------------- | ||
| def confirm | ||
| @tag = Tag.find(params[:id]) | ||
|
|
||
| rescue ActiveRecord::RecordNotFound | ||
| respond_to_not_found(:js, :xml) | ||
| end | ||
|
|
||
| end | ||
|
|
| @@ -0,0 +1,27 @@ | ||
| class ListsController < ApplicationController | ||
| respond_to :js | ||
|
|
||
| # POST /lists | ||
| #---------------------------------------------------------------------------- | ||
| def create | ||
| # Find any existing list with the same name (case insensitive) | ||
| if @list = List.find(:first, :conditions => ["lower(name) = ?", params[:list][:name].downcase]) | ||
| @list.update_attributes(params[:list]) | ||
| else | ||
| @list = List.create(params[:list]) | ||
| end | ||
| respond_with(@list) | ||
| end | ||
|
|
||
| # DELETE /lists/1 | ||
| #---------------------------------------------------------------------------- | ||
| def destroy | ||
| @list = List.find(params[:id]) | ||
| @list.destroy | ||
|
|
||
| respond_with(@list) | ||
|
|
||
| rescue ActiveRecord::RecordNotFound | ||
| respond_to_not_found(:html, :js, :json, :xml) | ||
| end | ||
| end |
| @@ -0,0 +1,22 @@ | ||
| # Fat Free CRM | ||
| # Copyright (C) 2008-2011 by Michael Dvorkin | ||
| # | ||
| # This program is free software: you can redistribute it and/or modify | ||
| # it under the terms of the GNU Affero General Public License as published by | ||
| # the Free Software Foundation, either version 3 of the License, or | ||
| # (at your option) any later version. | ||
| # | ||
| # This program is distributed in the hope that it will be useful, | ||
| # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| # GNU Affero General Public License for more details. | ||
| # | ||
| # You should have received a copy of the GNU Affero General Public License | ||
| # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| #------------------------------------------------------------------------------ | ||
|
|
||
| module Admin::TagsHelper | ||
| def link_to_confirm(tag) | ||
| link_to(t(:delete) + "?", confirm_admin_tag_path(tag), :method => :get, :remote => true) | ||
| end | ||
| end |
| @@ -0,0 +1,2 @@ | ||
| module ListsHelper | ||
| end |
| @@ -0,0 +1,8 @@ | ||
| class List < ActiveRecord::Base | ||
| validates_presence_of :name | ||
|
|
||
| # Parses the controller from the url | ||
| def controller | ||
| (url || "").sub(/^\//,'').split(/\/|\?/).first | ||
| end | ||
| end |
| @@ -1,2 +1,14 @@ | ||
| class Tag < ActsAsTaggableOn::Tag | ||
| before_destroy :no_associated_field_groups | ||
|
|
||
| # Don't allow a tag to be deleted if it is associated with a Field Group | ||
| def no_associated_field_groups | ||
| FieldGroup.find_all_by_tag_id(self).none? | ||
| end | ||
|
|
||
| # Returns a count of taggings per model klass | ||
| # e.g. {"Contact" => 3, "Account" => 1} | ||
| def model_tagging_counts | ||
| Tagging.where(:tag_id => id).count(:group => :taggable_type) | ||
| end | ||
| end |
| @@ -8,7 +8,7 @@ | ||
| %tr | ||
| %td | ||
| .label #{t :assigned_to}: | ||
| = user_select(:account) | ||
| %td= spacer | ||
| %td | ||
| .label #{t :category}: | ||
| @@ -0,0 +1,5 @@ | ||
| .confirm[@field_group, :confirm] | ||
| #{t :field_group_confirm_delete} | ||
| #{t :delete} <b>#{@field_group.name}</b>? | ||
| = link_to_confirm_delete(@field_group) << " : " | ||
| = link_to_function(t(:no_button), "crm.flick('#{dom_id(@field_group, :confirm)}', 'remove')") |
| @@ -0,0 +1,6 @@ | ||
| id = dom_id(@field_group, :confirm) | ||
| page << "if ($('#{id}')) {" | ||
| page.call "crm.flick", id, :remove | ||
| page << "} else {" | ||
| page.insert_html :top, dom_id(@field_group), :partial => "confirm" | ||
| page << "}" |
| @@ -0,0 +1,11 @@ | ||
| id = dom_id(@field_group) | ||
|
|
||
| if @field_group.destroyed? | ||
| page[id].visual_effect :blind_up, :duration => 0.25 | ||
| else | ||
| page.call "crm.flick", dom_id(@field_group, :confirm), :remove | ||
| page[id].visual_effect :shake, :duration => 0.25, :distance => 6 | ||
| page[:flash].replace_html flash[:warning] | ||
| page.call "crm.flash", :warning | ||
| flash[:warning] = nil | ||
| end |
| @@ -1 +1,11 @@ | ||
| id = dom_id(@field) | ||
|
|
||
| if @field.destroyed? | ||
| page[id].visual_effect :blind_up, :duration => 0.25 | ||
| else | ||
| page.call "crm.flick", dom_id(@field, :confirm), :remove | ||
| page[id].visual_effect :shake, :duration => 0.25, :distance => 6 | ||
| page[:flash].replace_html flash[:warning] | ||
| page.call "crm.flash", :warning | ||
| flash[:warning] = nil | ||
| end |
| @@ -0,0 +1,13 @@ | ||
| %li | ||
| %span.black | ||
| %strong= plugin.name | ||
| %tt | ||
| %dt{ :style => "padding: 2px 0px 0px 0px" } | ||
| = t(:author) + ":" | ||
| %strong= plugin.author | ||
| %br | ||
| = t(:version) + ":" | ||
| %strong= plugin.version | ||
| %br | ||
| = t(:description) + ":" | ||
| = plugin.description |
| @@ -1,3 +1,9 @@ | ||
| = styles_for :plugin | ||
|
|
||
| .title Plugins | ||
|
|
||
| .list#plugins | ||
| - if @plugins.any? | ||
| = render :partial => "admin/plugins/plugin", :collection => @plugins | ||
| - else | ||
| = render "shared/empty" |
| @@ -0,0 +1,5 @@ | ||
| .confirm[@tag, :confirm] | ||
| #{t :tag_with_taggings_confirm_delete, :value => Tagging.where(:tag_id => @tag).count} | ||
| #{t :delete} <b>#{@tag.name}</b>? | ||
| = link_to_confirm_delete(@tag) << " : " | ||
| = link_to_function(t(:no_button), "crm.flick('#{dom_id(@tag, :confirm)}', 'remove')") |
| @@ -0,0 +1,9 @@ | ||
| .remote | ||
| = form_for([:admin, @tag], :as => :tag, :html => one_submit_only(:tag).merge(:class => "edit_tag", :id => "edit_tag_#{@tag.id}"), :remote => true) do |f| | ||
| = link_to_close edit_admin_tag_path(@tag) | ||
| = f.error_messages | ||
| = render :partial => "top_section", :locals => { :f => f, :edit => true } | ||
| .buttonbar | ||
| = f.submit t(:save_tag), :id => :tag_submit | ||
| or | ||
| = link_to_cancel edit_admin_tag_path(@tag) |
| @@ -0,0 +1,10 @@ | ||
| - path = new_admin_tag_path | ||
|
|
||
| = form_for([:admin, @tag], :html => one_submit_only(:tag), :remote => true) do |f| | ||
| = link_to_close path | ||
| = f.error_messages | ||
| = render :partial => "top_section", :locals => { :f => f } | ||
| .buttonbar | ||
| = f.submit t(:create_tag), :id => :tag_submit | ||
| or | ||
| = link_to_cancel path |
| @@ -0,0 +1,29 @@ | ||
| - tag_field_groups = FieldGroup.find_all_by_tag_id(tag) | ||
| - model_tagging_counts = tag.model_tagging_counts | ||
|
|
||
| %li[tag]{ highlightable(dom_id(tag, :tools)) } | ||
| .tools{ invisible, :id => dom_id(tag, :tools) } | ||
| = link_to_edit(tag, :url => edit_admin_tag_path(tag)) << " |" | ||
| - if tag_field_groups.any? | ||
| %span{:style => "color: #777"} Delete | ||
| - else | ||
| - if model_tagging_counts.any? | ||
| = link_to_confirm(tag) | ||
| - else | ||
| = link_to_delete(tag) | ||
|
|
||
| %span.black= tag.name | ||
| %tt | ||
| - if model_tagging_counts.any? | ||
| = t(:tagged) + ":" | ||
| = model_tagging_counts.map {|k, c| t(pluralize(c, k.downcase)) }.join(", ") | ||
|
|
||
| - if tag_field_groups.any? | ||
| %dt{ :style => "padding: 2px 0px 0px 0px" } | ||
| = t(:field_group_tags) + ":" | ||
| - tag_field_groups.each_with_index do |field_group, i| | ||
| %strong= field_group.label_i18n | ||
| on | ||
| %strong= field_group.klass_name.pluralize | ||
| - if i < tag_field_groups.size - 1 | ||
| = "|" |
| @@ -0,0 +1,6 @@ | ||
| .section | ||
| %table | ||
| %tr | ||
| %td | ||
| .label.top.req= t(:name) + ":" | ||
| = f.text_field :name |
| @@ -0,0 +1,6 @@ | ||
| id = dom_id(@tag, :confirm) | ||
| page << "if ($('#{id}')) {" | ||
| page.call "crm.flick", id, :remove | ||
| page << "} else {" | ||
| page.insert_html :top, dom_id(@tag), :partial => "confirm" | ||
| page << "}" |
| @@ -0,0 +1,12 @@ | ||
| if @tag.valid? | ||
| page[:create_tag_arrow].replace_html "►" | ||
| page[:create_tag_title].replace_html t(:tags) | ||
| page.visual_effect :toggle_blind, :create_tag, :duration => 0.3, :afterFinish => 'function(effect) {effect.element.update("")}' | ||
| page.insert_html :top, :tags, :partial => "tag", :collection => [ @tag ] | ||
| page[dom_id(@tag)].visual_effect :highlight, :duration => 1.5 | ||
| page.call "crm.flick", :empty, :remove | ||
| else | ||
| page[:create_tag].replace_html :partial => "new" | ||
| page[:create_tag].visual_effect :shake, :duration => 0.25, :distance => 6 | ||
| page[:tag_name].focus | ||
| end |
| @@ -0,0 +1,11 @@ | ||
| id = dom_id(@tag) | ||
|
|
||
| if @tag.destroyed? | ||
| page[id].visual_effect :blind_up, :duration => 0.25 | ||
| else | ||
| page.call "crm.flick", dom_id(@tag, :confirm), :remove | ||
| page[id].visual_effect :shake, :duration => 0.25, :distance => 6 | ||
| page[:flash].replace_html flash[:warning] | ||
| page.call "crm.flash", :warning | ||
| flash[:warning] = nil | ||
| end |
| @@ -0,0 +1,21 @@ | ||
| id = dom_id(@tag) | ||
|
|
||
| if params[:cancel].true? # <----------------- Hide [Edit Tag] | ||
| page[id].replace :partial => "tag", :collection => [ @tag ] | ||
|
|
||
| else # <---------------------------------------- Show [Edit Tag] form. | ||
|
|
||
| if @previous # Hide open [Edit Tag] form if any. | ||
| if @previous.is_a?(Tag) # Previous tag still exists? | ||
| page[dom_id(@previous)].replace :partial => "tag", :collection => [ @previous ] | ||
| else | ||
| page.call "crm.flick", "tag_#{@previous}", :remove | ||
| end | ||
| end | ||
|
|
||
| page.call "crm.highlight_off", id # Disable onMouseOver for the list item. | ||
| page.call "crm.hide_form", :create_tag # Hide [Create Tag] form if any. | ||
| page[id].replace_html :partial => "edit" # Show [Edit Tag] form. | ||
| page[:tag_name].focus | ||
|
|
||
| end |
| @@ -0,0 +1,17 @@ | ||
| = styles_for :tag | ||
|
|
||
| .title_tools | ||
| = link_to_inline(:create_tag, new_admin_tag_path, :text => t(:create_tag)) | ||
|
|
||
| .title | ||
| %span#create_tag_title #{t :tags} | ||
| = image_tag("loading.gif", :size => "16x16", :id => "loading", :style => "display: none;") | ||
| .remote#create_tag{ hidden } | ||
|
|
||
| .list#tags | ||
| - if @tags.any? | ||
| = render :partial => "admin/tags/tag", :collection => @tags | ||
| - else | ||
| = render "shared/empty" | ||
|
|
||
| #export= render "shared/export" |
| @@ -0,0 +1,8 @@ | ||
| page.call "crm.flip_form", :create_tag | ||
|
|
||
| unless params[:cancel].true? | ||
| page[:create_tag].replace_html :partial => "new" | ||
| page.call "crm.set_title", :create_tag, t(:create_tag) | ||
| else | ||
| page.call "crm.set_title", :create_tag, t(:tags) | ||
| end |
| @@ -0,0 +1,10 @@ | ||
| id = dom_id(@tag) | ||
|
|
||
| if @tag.errors.empty? | ||
| page[id].replace :partial => "tag", :collection => [ @tag ] | ||
| page[id].visual_effect :highlight, :duration => 1.0 | ||
| else | ||
| page[id].replace_html :partial => "edit" | ||
| page[id].visual_effect :shake, :duration => 0.25, :distance => 6 | ||
| page[:tag_tagname].focus | ||
| end |
| @@ -1,5 +1,5 @@ | ||
| .confirm[@user, :confirm] | ||
| #{t :user_confirm_delete} | ||
| #{t :delete} <b>#{@user.full_name}</b>? | ||
| = link_to_confirm_delete(@user) << " : " | ||
| = link_to_function(t(:no_button), "crm.flick('#{dom_id(@user, :confirm)}', 'remove')") |
| @@ -1,4 +1,3 @@ | ||
| = styles_for :user | ||
|
|
||
| .title_tools | ||
| @@ -0,0 +1,12 @@ | ||
| = search_form_for search, :url => url_for(:action => :index), :html => {:method => :get, :class => "advanced_search"}, :remote => true do |f| | ||
| = link_to_close url_for(:action => :advanced_search) | ||
|
|
||
| = f.grouping_fields do |g| | ||
| = render 'grouping_fields', :f => g | ||
|
|
||
| %p | ||
| = link_to_add_fields t(:advanced_search_add_group), f, :grouping | ||
|
|
||
| %p | ||
| = hidden_field_tag :distinct, '1' | ||
| = f.submit t(:advanced_search_submit) |
| @@ -0,0 +1,14 @@ | ||
| .fields.condition{ "data-object-name" => f.object_name } | ||
| %p | ||
| = link_to_remove_fields t(:advanced_search_remove_condition), f | ||
|
|
||
| = f.attribute_fields do |a| | ||
| %span.fields{ "data-object-name" => f.object_name } | ||
| = a.attribute_select :associations => %w(account tags activities emails business_address billing_address) | ||
|
|
||
| = f.predicate_select({:only => [:cont, :not_cont, :blank, :present, :null, :not_null, :matches, :does_not_match, :eq, :not_eq, :lt, :gt], :compounds => false}, :class => "predicate") | ||
|
|
||
| = f.value_fields do |v| | ||
| %span.fields.value{ 'data-object-name' => f.object_name } | ||
| = v.text_field :value | ||
|
|
| @@ -0,0 +1,12 @@ | ||
| .fields{ 'data-object-name' => f.object_name } | ||
| %p | ||
| - key = (f.object_name =~ /[0]/) ? :advanced_search_group_first : :advanced_search_group_rest | ||
| = t(key, :combinator => f.combinator_select).html_safe | ||
|
|
||
| .filters | ||
| - f.object.build_condition unless f.object.conditions.any? | ||
| = f.condition_fields do |c| | ||
| = render 'condition_fields', :f => c | ||
|
|
||
| %p | ||
| = link_to_add_fields t(:advanced_search_add_condition), f, :condition |
| @@ -0,0 +1,3 @@ | ||
| %span.fields{ 'data-object-name' => f.object_name } | ||
| = f.sort_select | ||
| = button_to_remove_fields "remove", f |
| @@ -0,0 +1,9 @@ | ||
| page.call "crm.flick", :empty, :toggle | ||
| page.call "crm.flip_form", :advanced_search | ||
|
|
||
| if params[:cancel].true? | ||
| page.call "jQuery('.show_lists_save_form').hide" | ||
| else | ||
| page.call "jQuery('.show_lists_save_form').show" | ||
| page[:advanced_search].replace_html :partial => "advanced_search" | ||
| end |
| @@ -4,6 +4,4 @@ simple_fields_for(@asset) do |f| | ||
| :partial => 'fields/group', | ||
| :locals => {:f => f, :field_group => @field_group, :fields => @field_group.fields} | ||
| ) | ||
| end | ||
| @@ -7,4 +7,8 @@ | ||
| - begin | ||
| = render sidebar | ||
| - rescue MissingTemplate | ||
|
|
||
| - if Setting.advanced_search_enabled | ||
| = render "shared/lists" | ||
|
|
||
| = render "shared/recently" | ||
| @@ -26,7 +26,7 @@ | ||
| %td= spacer | ||
| %td | ||
| .label.req #{t :assigned_to}: | ||
| = user_select(:account) | ||
| = render "leads/opportunity" | ||
| = render "leads/convert_permissions" | ||
| .buttonbar | ||
| @@ -10,7 +10,7 @@ | ||
| %tr | ||
| %td | ||
| .label.top #{t :assigned_to}: | ||
| = user_select(:lead) | ||
| %td= spacer | ||
| %td | ||
| .label.top #{t :status}: | ||
| @@ -0,0 +1,9 @@ | ||
| if @list.valid? | ||
| page[:lists].replace :partial => "shared/lists" | ||
| page.call "jQuery('.show_lists_save_form').show" | ||
|
|
||
| else # Couldn't create the saved list -- validation failed. | ||
| page[:new_list].visual_effect :shake, :duration => 0.25, :distance => 6 | ||
| page[:list_name].focus | ||
| page[:save_list].enable | ||
| end |
| @@ -0,0 +1 @@ | ||
| page[dom_id(@list)].visual_effect "blind_up", :duration => 0.25 |
| @@ -1,7 +1,8 @@ | ||
| - assets = controller_name | ||
| - asset = assets.singularize | ||
| - new_asset_path = controller.class.to_s.include?("Admin") ? url_for([:new, :admin, asset]) : url_for([:new, asset]) | ||
| #empty | ||
| - if @current_query.blank? | ||
| == #{t(:could_not_find, t(assets.downcase))} #{link_to_inline(:"create_#{asset}", new_asset_path, :plain => true, :text => t(:create_a_new) << ' ' << t(asset + '_small'))}. | ||
| - else | ||
| == #{t(:could_not_find_matching, t(assets.downcase + '_small'))} <span class="cool"><b>#{h @current_query}</b></span>; #{t :please_retry} |
| @@ -0,0 +1,25 @@ | ||
| - @lists = List.all | ||
| - @list = List.new | ||
| .panel#lists | ||
| .caption #{t :lists} | ||
| %ul | ||
| - if @lists.none? | ||
| %div #{t :no_saved_lists} | ||
| - else | ||
| - @lists.sort.each_with_index do |list, i| | ||
| %li[list]{ :class => i < @lists.size - 1 ? "" : "last" } | ||
| %dt= link_to(truncate(list.name, :length => 25), list.url, :title => list.name) | ||
| %tt= link_to(image_tag("/assets/tab_icons/#{list.controller}_active.png", :"data-controller" => list.controller), url_for(list), :method => :delete, :confirm => 'Are you sure?', :remote => true, :class => "list_icon delete_on_hover") | ||
|
|
||
| .show_lists_save_form{ hidden_if(!params[:q]) } | ||
| = link_to(t(:make_current_view_list), '#') | ||
|
|
||
| .save_list{ hidden } | ||
| = simple_form_for(@list, :html => one_submit_only(:list), :remote => true) do |f| | ||
| = f.text_field :name | ||
| = image_tag("/assets/info_tiny.png", :title => t(:list_name_info), :class => "input_info") | ||
| = f.hidden_field :url | ||
| %br | ||
| = f.submit(t(:save), :id => "save_list", :style => "vertical-align: bottom;") | ||
| #{t :or} | ||
| = link_to(t(:cancel), '#', :class => "hide_lists_save_form") |
| @@ -17,7 +17,7 @@ | ||
| %td= spacer | ||
| %td | ||
| .label.req #{t :assign_to}: | ||
| = user_select(:task) | ||
| %td= spacer | ||
| %td | ||
| .label.req #{t :category}: | ||
| @@ -0,0 +1,10 @@ | ||
| class CreateLists < ActiveRecord::Migration | ||
| def change | ||
| create_table :lists do |t| | ||
| t.string :name | ||
| t.text :url | ||
|
|
||
| t.timestamps | ||
| end | ||
| end | ||
| end |
| @@ -0,0 +1,5 @@ | ||
| require 'spec_helper' | ||
|
|
||
| describe ListsController do | ||
|
|
||
| end |
| @@ -0,0 +1,5 @@ | ||
| Factory.define :list do |s| | ||
| s.name "Foo List" | ||
| s.url "/controller/action" | ||
| end | ||
|
|
| @@ -0,0 +1,15 @@ | ||
| require 'spec_helper' | ||
|
|
||
| # Specs in this file have access to a helper object that includes | ||
| # the ListsHelper. For example: | ||
| # | ||
| # describe ListsHelper do | ||
| # describe "string concat" do | ||
| # it "concats two strings with spaces" do | ||
| # helper.concat_strings("this","that").should == "this that" | ||
| # end | ||
| # end | ||
| # end | ||
| describe ListsHelper do | ||
| pending "add some examples to (or delete) #{__FILE__}" | ||
| end |
| @@ -0,0 +1,12 @@ | ||
| require 'spec_helper' | ||
|
|
||
| describe List do | ||
| it "should parse the controller from the url" do | ||
| ["/controller/action", "controller/action?utf8=%E2%9C%93"].each do |url| | ||
| list = Factory.build(:list, :url => url) | ||
| list.controller.should == "controller" | ||
| end | ||
| list = Factory.build(:list, :url => nil) | ||
| list.controller.should == nil | ||
| end | ||
| end |
| @@ -0,0 +1,64 @@ | ||
| /** | ||
| * Event.simulate(@element, eventName[, options]) -> Element | ||
| * | ||
| * - @element: element to fire event on | ||
| * - eventName: name of event to fire (only MouseEvents and HTMLEvents interfaces are supported) | ||
| * - options: optional object to fine-tune event properties - pointerX, pointerY, ctrlKey, etc. | ||
| * | ||
| * $('foo').simulate('click'); // => fires "click" event on an element with id=foo | ||
| * | ||
| **/ | ||
| (function(){ | ||
|
|
||
| var eventMatchers = { | ||
| 'HTMLEvents': /^(?:load|unload|abort|error|select|change|submit|reset|focus|blur|resize|scroll)$/, | ||
| 'MouseEvents': /^(?:click|mouse(?:down|up|over|move|out))$/ | ||
| } | ||
| var defaultOptions = { | ||
| pointerX: 0, | ||
| pointerY: 0, | ||
| button: 0, | ||
| ctrlKey: false, | ||
| altKey: false, | ||
| shiftKey: false, | ||
| metaKey: false, | ||
| bubbles: true, | ||
| cancelable: true | ||
| } | ||
|
|
||
| Event.simulate = function(element, eventName) { | ||
| var options = Object.extend(defaultOptions, arguments[2] || { }); | ||
| var oEvent, eventType = null; | ||
|
|
||
| element = $(element); | ||
|
|
||
| for (var name in eventMatchers) { | ||
| if (eventMatchers[name].test(eventName)) { eventType = name; break; } | ||
| } | ||
|
|
||
| if (!eventType) | ||
| throw new SyntaxError('Only HTMLEvents and MouseEvents interfaces are supported'); | ||
|
|
||
| if (document.createEvent) { | ||
| oEvent = document.createEvent(eventType); | ||
| if (eventType == 'HTMLEvents') { | ||
| oEvent.initEvent(eventName, options.bubbles, options.cancelable); | ||
| } | ||
| else { | ||
| oEvent.initMouseEvent(eventName, options.bubbles, options.cancelable, document.defaultView, | ||
| options.button, options.pointerX, options.pointerY, options.pointerX, options.pointerY, | ||
| options.ctrlKey, options.altKey, options.shiftKey, options.metaKey, options.button, element); | ||
| } | ||
| element.dispatchEvent(oEvent); | ||
| } | ||
| else { | ||
| options.clientX = options.pointerX; | ||
| options.clientY = options.pointerY; | ||
| oEvent = Object.extend(document.createEventObject(), options); | ||
| element.fireEvent('on' + eventName, oEvent); | ||
| } | ||
| return element; | ||
| } | ||
|
|
||
| Element.addMethods({ simulate: Event.simulate }); | ||
| })() |