Skip to content

Commit

Permalink
Merging in crm_tags code
Browse files Browse the repository at this point in the history
  • Loading branch information
Ben Tillman committed Nov 15, 2011
1 parent 92bb02d commit cb74d3c
Show file tree
Hide file tree
Showing 31 changed files with 818 additions and 15 deletions.
36 changes: 31 additions & 5 deletions app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,15 @@ def timeline(asset)
(asset.comments + asset.emails).sort { |x, y| y.created_at <=> x.created_at }
end

# Controller instance method that responds to /controlled/tagged/tag request.
# It stores given tag as current query and redirect to index to display all
# records tagged with the tag.
#----------------------------------------------------------------------------
def tagged
self.send(:current_query=, "#" << params[:id]) unless params[:id].blank?
redirect_to :action => "index"
end

private
#----------------------------------------------------------------------------
def set_context
Expand Down Expand Up @@ -228,7 +237,7 @@ def respond_to_related_not_found(related, *types)
def get_list_of_records(klass, options = {})
items = klass.name.tableize
self.current_page = options[:page] if options[:page]
self.current_query = options[:query] if options[:query]
self.current_query, tags = parse_query_and_tags(context[:query])

records = {
:user => @current_user,
Expand All @@ -250,10 +259,11 @@ def get_list_of_records(klass, options = {})
filter = session[options[:filter]].to_s.split(',') if options[:filter]

scope = klass.my(records)
scope = scope.state(filter) unless filter.blank?
scope = scope.search(current_query) unless current_query.blank?
scope = scope.unscoped if wants.csv?
scope = scope.paginate(pages) if wants.html? || wants.js? || wants.xml?
scope = scope.state(filter) if filter.present?
scope = scope.search(current_query) if current_query.present?
scope = scope.tagged_with(tags, :on => :tags) if current_tags.present?
scope = scope.unscoped if wants.csv?
scope = scope.paginate(pages) if wants.html? || wants.js? || wants.xml?
scope
end

Expand All @@ -280,5 +290,21 @@ def current_query
@current_query = params[:query] || session["#{controller_name}_current_query".to_sym] || ""
end

# Somewhat simplistic parser that extracts query and hash-prefixed tags from
# the search string and returns them as two element array, for example:
#
# "#real Billy Bones #pirate" => [ "Billy Bones", "real, pirate" ]
#----------------------------------------------------------------------------
def parse_query_and_tags(search_string)
query, tags = [], []
search_string.scan(/[\w@\-\.'#]+/).each do |token|
if token.starts_with?("#")
tags << token[1 .. -1]
else
query << token
end
end
[ query.join(" "), tags.join(", ") ]
end
end

49 changes: 49 additions & 0 deletions app/helpers/tags_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# 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 TagsHelper

# Generate tag links for use on asset index pages.
#----------------------------------------------------------------------------
def tags_for_index(model)
model.tag_list.inject([]) do |arr, tag|
query = controller.send(:current_query) || ""
hashtag = "##{tag}"
if query.empty?
query = hashtag
elsif !query.include?(hashtag)
query += " #{hashtag}"
end
arr << link_to_function(tag, "crm.search_tagged('#{query}', '#{model.class.to_s.tableize}')", :title => tag)
end.join(" ")
end

# Generate tag links for the asset landing page (shown on a sidebar).
#----------------------------------------------------------------------------
def tags_for_show(model)
model.tag_list.inject([]) do |arr, tag|
arr << link_to(tag, url_for(:action => "tagged", :id => tag), :title => tag)
end.join(" ")
end

# Return asset tags to be built manually if the asset failed validation.
def unsaved_param_tags(asset)
params[asset][:tag_list].split(",").map {|x|
ActsAsTaggableOn::Tag.find_by_name(x.strip)
}.compact.uniq
end
end
1 change: 1 addition & 0 deletions app/models/core/account.rb
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ class Account < ActiveRecord::Base

uses_user_permissions
acts_as_commentable
acts_as_taggable_on :tags
is_paranoid
has_fields
exportable
Expand Down
1 change: 1 addition & 0 deletions app/models/core/campaign.rb
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ class Campaign < ActiveRecord::Base

uses_user_permissions
acts_as_commentable
acts_as_taggable_on :tags
is_paranoid
has_fields
exportable
Expand Down
1 change: 1 addition & 0 deletions app/models/core/contact.rb
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ class Contact < ActiveRecord::Base

uses_user_permissions
acts_as_commentable
acts_as_taggable_on :tags
is_paranoid
has_fields
exportable
Expand Down
1 change: 1 addition & 0 deletions app/models/core/lead.rb
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ class Lead < ActiveRecord::Base

uses_user_permissions
acts_as_commentable
acts_as_taggable_on :tags
is_paranoid
has_fields
exportable
Expand Down
1 change: 1 addition & 0 deletions app/models/core/opportunity.rb
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ class Opportunity < ActiveRecord::Base

uses_user_permissions
acts_as_commentable
acts_as_taggable_on :tags
is_paranoid
has_fields
exportable
Expand Down
11 changes: 11 additions & 0 deletions app/stylesheets/common.sass
Original file line number Diff line number Diff line change
Expand Up @@ -644,3 +644,14 @@ span.handle img
vertical-align: middle
margin-right: 5px

.tags, .list li dt .tags
a:link, a:visited
:background lightsteelblue
:color white
:font-weight normal
:padding 0px 6px 1px 6px
:-moz-border-radius 8px
:-webkit-border-radius 8px
a:hover
:background steelblue
:color yellow
6 changes: 5 additions & 1 deletion app/views/accounts/_account.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,15 @@
= t('pluralize.contact', account.contacts.count) << " | "
= t('pluralize.opportunity', account.opportunities.count)


- unless @current_user.preference[:accounts_outline] == "brief"
%dt
= stars_for(account) + " | "
= link_to(account.website, account.website.to_url) << " | " if account.website.present?
= link_to_email(account.email) << " | " if account.email.present?
= t(:phone_small) << ": " << (account.toll_free_phone || account.phone) if account.toll_free_phone? || account.phone?

- if account.tag_list.present?
%dt
.tags= tags_for_index(account)

= hook(:account_bottom, self, :account => account)
4 changes: 4 additions & 0 deletions app/views/accounts/_sidebar_show.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,8 @@
.caption #{t :background_info}
= auto_link(simple_format h(@account.background_info))

- if @account.tag_list.present?
%dt
.tags= tags_for_index(@account)

= hook(:show_account_sidebar_bottom, self, :account => @account)
3 changes: 2 additions & 1 deletion app/views/accounts/_top_section.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,6 @@
.label= t(:background_info) << ':'
= f.text_area :background_info, :style =>"width:500px", :rows => 3

= hook(:account_top_section_bottom, self, :f => f)
= render :partial => "/shared/tags", :locals => {:f => f, :span => 3}

= hook(:account_top_section_bottom, self, :f => f)
4 changes: 4 additions & 0 deletions app/views/campaigns/_campaign.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,8 @@
= render "campaigns/status", :campaign => campaign
- unless @current_user.preference[:campaigns_outline] == "brief"
= render "campaigns/metrics", :campaign => campaign
- if campaign.tag_list.present?
%dt
.tags= tags_for_index(campaign)

= hook(:campaign_bottom, self, :campaign => campaign)
10 changes: 7 additions & 3 deletions app/views/campaigns/_sidebar_show.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,19 @@
%tt #{t :budget}:

.caption #{t :campaign_targets}

-# Target Leads.
-#---------------------------------------------------------------------------
%li
%dt= @campaign.target_leads || t(:n_a)
%tt #{t :leads}:

-# Target Conversion Ratio.
-#---------------------------------------------------------------------------
%li
%dt= number_to_percentage(@campaign.target_conversion, :precision => 1) || t(:n_a)
%tt #{t :conversion}:

-# Target Opportunities: calculated based on target number of leads and
-# expected conversion ratio.
-#---------------------------------------------------------------------------
Expand Down Expand Up @@ -82,4 +82,8 @@
.caption #{t :background_info}
= auto_link(simple_format h(@campaign.background_info))

- if @campaign.tag_list.present?
%dt
.tags= tags_for_index(@campaign)

= hook(:show_campaign_sidebar_bottom, self, :campaign => @campaign)
2 changes: 2 additions & 0 deletions app/views/campaigns/_top_section.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,6 @@
.label= t(:background_info) << ':'
= f.text_area :background_info, :style =>"width:500px", :rows => 3

= render :partial => "/shared/tags", :locals => {:f => f, :span => 5}

= hook(:campaign_top_section_bottom, self, :f => f)
4 changes: 4 additions & 0 deletions app/views/contacts/_contact.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,8 @@
= "#{t :phone_small}: <b>".html_safe + h(contact.phone) << "</b> | ".html_safe if contact.phone.present?
= "#{t :mobile_small}: <b>".html_safe + h(contact.mobile) << "</b> | ".html_safe if contact.mobile.present?
= t(:added_ago, time_ago_in_words(contact.created_at))
- if contact.tag_list.present?
%dt
.tags= tags_for_index(contact)

= hook(:contact_bottom, self, :contact => contact)
4 changes: 4 additions & 0 deletions app/views/contacts/_sidebar_show.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,8 @@
.caption #{t :background_info}
= auto_link(simple_format h(@contact.background_info))

- if @contact.tag_list.present?
%dt
.tags= tags_for_index(@contact)

= hook(:show_contact_sidebar_bottom, self, :contact => @contact)
2 changes: 2 additions & 0 deletions app/views/contacts/_top_section.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,6 @@
.label= t(:background_info) << ':'
= f.text_area :background_info, :style =>"width:500px", :rows => 3

= render :partial => "/shared/tags", :locals => {:f => f, :span => 3}

= hook(:contact_top_section_bottom, self, :f => f)
5 changes: 3 additions & 2 deletions app/views/layouts/application.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,16 @@
%meta{ "http-equiv" => "Content-Type", :content => "text/html; charset=utf-8" }
%title Fat Free CRM
== <!-- #{controller.controller_name} : #{controller.action_name} -->
= stylesheet_link_tag "screen", "modalbox.css"
= stylesheet_link_tag "screen", 'modalbox.css', 'facebooklist.css'
= stylesheet_link_tag "print", :media => "print"
- unless tabless_layout?
= stylesheet_link_tag "calendar_date_select/default.css"
%style= content_for :styles
= javascript_include_tag :defaults, "modalbox.js", :cache => "cache/all"
= javascript_include_tag :defaults, 'modalbox.js', 'facebooklist.js', 'facebooklist.simulate.js', :cache => "cache/all"
- unless tabless_layout?
= javascript_include_tag "crm_classes.js", "calendar_date_select/calendar_date_select.js", "calendar_date_select/format_#{t(:calendar_date_select_format, :default => 'american')}.js", :cache => "cache/classes"

= hook(:javascript_includes, self)

<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon">
Expand Down
5 changes: 4 additions & 1 deletion app/views/leads/_lead.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,8 @@
= "#{t :phone_small}: " + lead.phone << " | " if lead.phone.present?
= "#{t :mobile_small}: " + lead.mobile << " | " if lead.mobile.present?
= t(:added_ago, time_ago_in_words(lead.created_at))
= hook(:lead_bottom, self, :lead => lead)
- if lead.tag_list.present?
%dt
.tags= tags_for_index(lead)

= hook(:lead_bottom, self, :lead => lead)
4 changes: 4 additions & 0 deletions app/views/leads/_sidebar_show.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,8 @@
.caption #{t :background_info}
= auto_link(simple_format h(@lead.background_info))

- if @lead.tag_list.present?
%dt
.tags= tags_for_index(@lead)

= hook(:show_lead_sidebar_bottom, self, :lead => @lead)
3 changes: 3 additions & 0 deletions app/views/leads/_top_section.html.haml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

= hook(:lead_top_section, self, :f => f) do
.section
%table
Expand All @@ -24,4 +25,6 @@
.label= t(:background_info) << ':'
= f.text_area :background_info, :style =>"width:500px", :rows => 3

= render :partial => "/shared/tags", :locals => {:f => f, :span => 3}

= hook(:lead_top_section_bottom, self, :f => f)
6 changes: 5 additions & 1 deletion app/views/opportunities/_opportunity.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
- unless won_or_lost
== #{number_to_currency(opportunity.amount || 0, :precision => 0)}
== #{opportunity.discount ? t(:discount_number, number_to_currency(opportunity.discount, :precision => 0)) : t(:no_discount)}
= t(:probability_number, (opportunity.probability || 0).to_s + '%') + " | "
= t(:probability_number, (opportunity.probability || 0).to_s + '%') + " | "
- if opportunity.closes_on
- if won_or_lost
- if opportunity.closes_on >= Date.today
Expand All @@ -38,4 +38,8 @@
%span.warn= t(:past_due, distance_of_time_in_words(opportunity.closes_on, Date.today))
- else
= t(:no_closing_date)
- if opportunity.tag_list.present?
%dt
.tags= tags_for_index(opportunity)

= hook(:opportunity_bottom, self, :opportunity => opportunity)
4 changes: 4 additions & 0 deletions app/views/opportunities/_sidebar_show.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,8 @@
.caption #{t :background_info}
= auto_link(simple_format h(@opportunity.background_info))

- if @opportunity.tag_list.present?
%dt
.tags= tags_for_index(@opportunity)

= hook(:show_opportunity_sidebar_bottom, self, :opportunity => @opportunity)
3 changes: 3 additions & 0 deletions app/views/opportunities/_top_section.html.haml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

= hook(:opportunity_top_section, self, :f => f) do
.section
%table
Expand Down Expand Up @@ -60,4 +61,6 @@
.label= t(:background_info) << ':'
= f.text_area :background_info, :style =>"width:500px", :rows => 3

= render :partial => "/shared/tags", :locals => {:f => f, :span => 3}

= hook(:opportunity_top_section_bottom, self, :f => f)
22 changes: 22 additions & 0 deletions app/views/shared/_tags.html.haml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
- asset = controller_name.singularize
- f.object.tags = unsaved_param_tags(asset) if params[asset] && params[asset][:tag_list]
%tr
%td{ :valign => :top, :colspan => span }
.label.req Tags: <small>(comma separated, letters and digits only)</small>
#taggings
#facebook-list
= f.text_field :tag_list, :id => "tag_list", :style => "width:500px", :autocomplete => "off"
#facebook-auto
.default Type the name of a tag you'd like to use. Use commas to separate multiple tags.
%ul.feed
- # Get tags from the object.
- f.object.tags.map{|t| t.name }.each do |tag|
%li{ :value => tag }= tag
:javascript
fbtaglist = new FacebookList('tag_list', 'facebook-auto',
{ newValues: true,
regexSearch: false,
separator: Event.KEY_COMMA });
var tagjson = #{ActsAsTaggableOn::Tag.all.map{|t| {"caption" => t.name, "value" => t.name} }.to_json}
tagjson.each(function(t){fbtaglist.autoFeed(t)});

1 change: 1 addition & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@
resources :plugins
end

get '/:controller/tagged/:id' => '#tagged'
end
end

Binary file added public/images/facebook-close.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit cb74d3c

Please sign in to comment.