Commit be3b210f062b4a1e4e324bbabf7965090e43838c
1 parent
6c114d19
Exists in
master
and in
9 other branches
Add abstract plugin to federate networks via OpenGraph
Showing
43 changed files
with
1557 additions
and
2 deletions
Show diff stats
app/models/article.rb
@@ -8,7 +8,8 @@ class Article < ActiveRecord::Base | @@ -8,7 +8,8 @@ class Article < ActiveRecord::Base | ||
8 | :accept_comments, :feed, :published, :source, :source_name, | 8 | :accept_comments, :feed, :published, :source, :source_name, |
9 | :highlighted, :notify_comments, :display_hits, :slug, | 9 | :highlighted, :notify_comments, :display_hits, :slug, |
10 | :external_feed_builder, :display_versions, :external_link, | 10 | :external_feed_builder, :display_versions, :external_link, |
11 | - :image_builder, :show_to_followers | 11 | + :image_builder, :show_to_followers, |
12 | + :author | ||
12 | 13 | ||
13 | acts_as_having_image | 14 | acts_as_having_image |
14 | 15 |
app/models/uploaded_file.rb
lib/tasks/plugins_tests.rake
@@ -169,7 +169,7 @@ def test_sequence(plugins, tasks) | @@ -169,7 +169,7 @@ def test_sequence(plugins, tasks) | ||
169 | failed[plugin] << task | 169 | failed[plugin] << task |
170 | end | 170 | end |
171 | end | 171 | end |
172 | - disable_plugins(plugin) | 172 | + disable_plugins |
173 | end | 173 | end |
174 | fail_flag = false | 174 | fail_flag = false |
175 | failed.each do |plugin, tasks| | 175 | failed.each do |plugin, tasks| |
plugins/open_graph/controllers/myprofile/open_graph_plugin/myprofile_controller.rb
0 → 100644
@@ -0,0 +1,47 @@ | @@ -0,0 +1,47 @@ | ||
1 | +class OpenGraphPlugin::MyprofileController < MyProfileController | ||
2 | + | ||
3 | + protect 'edit_profile', :profile | ||
4 | + before_filter :set_context | ||
5 | + | ||
6 | + def enterprise_search | ||
7 | + scope = environment.enterprises.enabled.public | ||
8 | + profile_search scope | ||
9 | + end | ||
10 | + def community_search | ||
11 | + scope = environment.communities.public | ||
12 | + profile_search scope | ||
13 | + end | ||
14 | + def friend_search | ||
15 | + scope = profile.friends | ||
16 | + profile_search scope | ||
17 | + end | ||
18 | + | ||
19 | + def track_config | ||
20 | + profile.update_attributes! params[:profile_data] | ||
21 | + render partial: 'track_form', locals: {context: context, reload: true} | ||
22 | + end | ||
23 | + | ||
24 | + protected | ||
25 | + | ||
26 | + def profile_search scope | ||
27 | + @query = params[:query] | ||
28 | + @profiles = scope.limit(10).order('name ASC'). | ||
29 | + where(['name ILIKE ? OR name ILIKE ? OR identifier LIKE ?', "#{@query}%", "% #{@query}%", "#{@query}%"]) | ||
30 | + render partial: 'profile_search', locals: {profiles: @profiles} | ||
31 | + end | ||
32 | + | ||
33 | + def context | ||
34 | + :open_graph | ||
35 | + end | ||
36 | + | ||
37 | + def set_context | ||
38 | + OpenGraphPlugin.context = self.context | ||
39 | + end | ||
40 | + | ||
41 | + def default_url_options | ||
42 | + # avoid rails' use_relative_controller! | ||
43 | + {use_route: '/'} | ||
44 | + end | ||
45 | + | ||
46 | +end | ||
47 | + |
plugins/open_graph/db/migrate/20141031130250_create_open_graph_plugin_tracks.rb
0 → 100644
@@ -0,0 +1,36 @@ | @@ -0,0 +1,36 @@ | ||
1 | +class CreateOpenGraphPluginTracks < ActiveRecord::Migration | ||
2 | + def up | ||
3 | + create_table :open_graph_plugin_tracks do |t| | ||
4 | + t.string :type | ||
5 | + t.string :context | ||
6 | + t.boolean :enabled, default: true | ||
7 | + | ||
8 | + t.integer :tracker_id | ||
9 | + | ||
10 | + t.integer :actor_id | ||
11 | + | ||
12 | + t.string :action | ||
13 | + | ||
14 | + t.string :object_type | ||
15 | + t.text :object_data_url | ||
16 | + t.integer :object_data_id | ||
17 | + t.string :object_data_type | ||
18 | + | ||
19 | + t.timestamps | ||
20 | + end | ||
21 | + | ||
22 | + add_index :open_graph_plugin_tracks, [:type] | ||
23 | + add_index :open_graph_plugin_tracks, [:context] | ||
24 | + add_index :open_graph_plugin_tracks, [:type, :context] | ||
25 | + add_index :open_graph_plugin_tracks, [:actor_id] | ||
26 | + add_index :open_graph_plugin_tracks, [:action] | ||
27 | + add_index :open_graph_plugin_tracks, [:object_type] | ||
28 | + add_index :open_graph_plugin_tracks, [:enabled] | ||
29 | + add_index :open_graph_plugin_tracks, [:object_data_url] | ||
30 | + add_index :open_graph_plugin_tracks, [:object_data_id, :object_data_type], name: 'index_open_graph_plugin_tracks_object_data_id_type' | ||
31 | + end | ||
32 | + | ||
33 | + def down | ||
34 | + drop_table :open_graph_plugin_tracks | ||
35 | + end | ||
36 | +end |
@@ -0,0 +1,15 @@ | @@ -0,0 +1,15 @@ | ||
1 | +require_dependency 'article' | ||
2 | + | ||
3 | +class Article | ||
4 | + | ||
5 | + after_update :open_graph_scrape | ||
6 | + | ||
7 | + protected | ||
8 | + | ||
9 | + def open_graph_scrape | ||
10 | + activity = OpenGraphPlugin::Activity.where(object_data_id: self.id, object_data_type: self.class.base_class.name).first | ||
11 | + activity.scrape if activity | ||
12 | + end | ||
13 | + handle_asynchronously :open_graph_scrape | ||
14 | + | ||
15 | +end |
@@ -0,0 +1,59 @@ | @@ -0,0 +1,59 @@ | ||
1 | +require_dependency 'profile' | ||
2 | +# hate to wrte this, but without Noosfero::Plugin::Settings is loaded instead | ||
3 | +require 'open_graph_plugin/settings' | ||
4 | + | ||
5 | +# attr_accessible must be defined on subclasses | ||
6 | +Profile.descendants.each do |subclass| | ||
7 | + subclass.class_eval do | ||
8 | + attr_accessible :open_graph_settings | ||
9 | + | ||
10 | + OpenGraphPlugin::TrackConfig::Types.each do |track, klass| | ||
11 | + klass = "OpenGraphPlugin::#{klass}".constantize | ||
12 | + attributes = "#{klass.association}_attributes" | ||
13 | + profile_ids = "open_graph_#{track}_profiles_ids" | ||
14 | + | ||
15 | + attr_accessible attributes | ||
16 | + attr_accessible profile_ids | ||
17 | + end | ||
18 | + end | ||
19 | +end | ||
20 | + | ||
21 | +class Profile | ||
22 | + | ||
23 | + def open_graph_settings attrs = {} | ||
24 | + @open_graph_settings ||= OpenGraphPlugin::Settings.new self, attrs | ||
25 | + attrs.each{ |a, v| @open_graph_settings.send "#{a}=", v } | ||
26 | + @open_graph_settings | ||
27 | + end | ||
28 | + alias_method :open_graph_settings=, :open_graph_settings | ||
29 | + | ||
30 | + has_many :open_graph_tracks, class_name: 'OpenGraphPlugin::Track', source: :tracker_id, foreign_key: :tracker_id | ||
31 | + | ||
32 | + has_many :open_graph_activities, class_name: 'OpenGraphPlugin::Activity', source: :tracker_id, foreign_key: :tracker_id | ||
33 | + | ||
34 | + has_many :open_graph_track_configs, class_name: 'OpenGraphPlugin::TrackConfig', source: :tracker_id, foreign_key: :tracker_id | ||
35 | + OpenGraphPlugin::TrackConfig::Types.each do |track, klass| | ||
36 | + klass = "OpenGraphPlugin::#{klass}".constantize | ||
37 | + association = klass.association | ||
38 | + profile_ids = "open_graph_#{track}_profiles_ids" | ||
39 | + | ||
40 | + has_many association, class_name: klass.name, foreign_key: :tracker_id | ||
41 | + accepts_nested_attributes_for association, allow_destroy: true, reject_if: :open_graph_reject_empty_object_type | ||
42 | + | ||
43 | + define_method "#{profile_ids}=" do |ids| | ||
44 | + cids = self.send(association).order('created_at ASC').map(&:object_data_id) | ||
45 | + nids = if ids.is_a? Array then ids else ids.split ',' end | ||
46 | + nids = nids.map(&:to_i) | ||
47 | + Profile.where(id: nids-cids).each{ |profile| self.send(association).create! type: klass.name, object_data: profile } | ||
48 | + self.send(association).each{ |c| c.destroy unless c.object_data_id.in? nids } | ||
49 | + end | ||
50 | + | ||
51 | + end | ||
52 | + | ||
53 | + define_method :open_graph_reject_empty_object_type do |attributes| | ||
54 | + exists = attributes[:id].present? | ||
55 | + empty = attributes[:object_type].empty? | ||
56 | + attributes.merge! _destroy: 1 if exists and empty | ||
57 | + return (!exists and empty) | ||
58 | + end | ||
59 | +end |
@@ -0,0 +1,19 @@ | @@ -0,0 +1,19 @@ | ||
1 | +require_dependency 'profile_activity' | ||
2 | + | ||
3 | +class ProfileActivity | ||
4 | + | ||
5 | + # update happens with grouped ActionTracker | ||
6 | + after_save :open_graph_publish | ||
7 | + | ||
8 | + def open_graph_publish | ||
9 | + # Scrap not yet supported | ||
10 | + if self.activity.is_a? ActionTracker::Record | ||
11 | + verb = self.activity.verb.to_sym | ||
12 | + return unless object = self.activity.target | ||
13 | + return unless stories = OpenGraphPlugin::Stories::TrackerStories[verb] | ||
14 | + OpenGraphPlugin::Stories.publish object, stories | ||
15 | + end | ||
16 | + end | ||
17 | + | ||
18 | +end | ||
19 | + |
@@ -0,0 +1,21 @@ | @@ -0,0 +1,21 @@ | ||
1 | +module OpenGraphPlugin | ||
2 | + | ||
3 | + extend Noosfero::Plugin::ParentMethods | ||
4 | + | ||
5 | + def self.plugin_name | ||
6 | + I18n.t 'open_graph_plugin.lib.plugin.name' | ||
7 | + end | ||
8 | + | ||
9 | + def self.plugin_description | ||
10 | + I18n.t 'open_graph_plugin.lib.plugin.description' | ||
11 | + end | ||
12 | + | ||
13 | + def self.context | ||
14 | + Thread.current[:open_graph_context] || :open_graph | ||
15 | + end | ||
16 | + def self.context= value | ||
17 | + Thread.current[:open_graph_context] = value | ||
18 | + end | ||
19 | + | ||
20 | +end | ||
21 | + |
plugins/open_graph/lib/open_graph_plugin/attach_stories.rb
0 → 100644
@@ -0,0 +1,44 @@ | @@ -0,0 +1,44 @@ | ||
1 | +require_dependency 'open_graph_plugin/stories' | ||
2 | + | ||
3 | +# This is used when ActionTracker is not compartible with the way | ||
4 | +module OpenGraphPlugin::AttachStories | ||
5 | + | ||
6 | + module ClassMethods | ||
7 | + | ||
8 | + def open_graph_attach_stories options={} | ||
9 | + if stories = Array(options[:only]) | ||
10 | + callbacks = {} | ||
11 | + stories.each do |story| | ||
12 | + defs = OpenGraphPlugin::Stories::Definitions[story] | ||
13 | + Array(defs[:on]).each do |on| | ||
14 | + callbacks[on] ||= [] | ||
15 | + callbacks[on] << story | ||
16 | + end | ||
17 | + end | ||
18 | + else | ||
19 | + klass = self.name | ||
20 | + callbacks = OpenGraphPlugin::Stories::ModelStories[klass.to_sym] | ||
21 | + return if callbacks.blank? | ||
22 | + end | ||
23 | + | ||
24 | + callbacks.each do |on, stories| | ||
25 | + # subclasses may override this, but the callback is called only once | ||
26 | + method = "open_graph_publish_after_#{on}" | ||
27 | + | ||
28 | + self.send "after_#{on}", method | ||
29 | + # buggy with rails 3.2 | ||
30 | + #self.send "after_commit", method, on: on | ||
31 | + | ||
32 | + define_method method do | ||
33 | + OpenGraphPlugin::Stories.publish self, stories | ||
34 | + end | ||
35 | + end | ||
36 | + end | ||
37 | + | ||
38 | + end | ||
39 | + | ||
40 | + module InstanceMethods | ||
41 | + | ||
42 | + end | ||
43 | + | ||
44 | +end |
plugins/open_graph/lib/open_graph_plugin/display_helper.rb
0 → 100644
@@ -0,0 +1,166 @@ | @@ -0,0 +1,166 @@ | ||
1 | + | ||
2 | +class OpenGraphPlugin::Publisher | ||
3 | + | ||
4 | + attr_accessor :actions | ||
5 | + attr_accessor :objects | ||
6 | + | ||
7 | + def self.default | ||
8 | + @default ||= self.new | ||
9 | + end | ||
10 | + | ||
11 | + def initialize attributes = {} | ||
12 | + # defaults | ||
13 | + self.actions = OpenGraphPlugin::Stories::DefaultActions | ||
14 | + self.objects = OpenGraphPlugin::Stories::DefaultObjects | ||
15 | + | ||
16 | + attributes.each do |attr, value| | ||
17 | + self.send "#{attr}=", value | ||
18 | + end | ||
19 | + end | ||
20 | + | ||
21 | + def publish actor, story_defs, object_data_url | ||
22 | + raise 'abstract method called' | ||
23 | + end | ||
24 | + | ||
25 | + def publish_stories object_data, actor, stories | ||
26 | + stories.each do |story| | ||
27 | + begin | ||
28 | + self.publish_story object_data, actor, story | ||
29 | + rescue => e | ||
30 | + ExceptionNotifier.notify_exception e | ||
31 | + end | ||
32 | + end | ||
33 | + end | ||
34 | + | ||
35 | + def update_delay | ||
36 | + 1.day | ||
37 | + end | ||
38 | + | ||
39 | + # only publish recent objects to avoid multiple publications | ||
40 | + def recent_publish? actor, object_type, object_data_url | ||
41 | + activity_params = {actor_id: actor.id, object_type: object_type, object_data_url: object_data_url} | ||
42 | + activity = OpenGraphPlugin::Activity.where(activity_params).first | ||
43 | + activity.present? and activity.created_at <= self.update_delay.from_now | ||
44 | + end | ||
45 | + | ||
46 | + def publish_story object_data, actor, story | ||
47 | + OpenGraphPlugin.context = self.context | ||
48 | + defs = OpenGraphPlugin::Stories::Definitions[story] | ||
49 | + passive = defs[:passive] | ||
50 | + | ||
51 | + print_debug "open_graph: publish_story #{story}" if debug? actor | ||
52 | + match_criteria = if (ret = self.call defs[:criteria], object_data, actor).nil? then true else ret end | ||
53 | + return unless match_criteria | ||
54 | + print_debug "open_graph: #{story} match criteria" if debug? actor | ||
55 | + match_condition = if (ret = self.call defs[:publish_if], object_data, actor).nil? then true else ret end | ||
56 | + return unless match_condition | ||
57 | + print_debug "open_graph: #{story} match publish_if" if debug? actor | ||
58 | + | ||
59 | + actors = self.story_trackers defs, actor, object_data | ||
60 | + return if actors.blank? | ||
61 | + print_debug "open_graph: #{story} has enabled trackers" if debug? actor | ||
62 | + | ||
63 | + if publish = defs[:publish] | ||
64 | + begin | ||
65 | + instance_exec actor, object_data, &publish | ||
66 | + rescue => e | ||
67 | + print_debug "open_graph: can't publish story: #{e.message}" if debug? actor | ||
68 | + ExceptionNotifier.notify_exception e | ||
69 | + end | ||
70 | + else | ||
71 | + # force profile identifier for custom domains and fixed host. see og_url_for | ||
72 | + object_profile = self.call(story_defs[:object_profile], object_data) || object_data.profile rescue nil | ||
73 | + extra_params = if object_profile then {profile: object_profile.identifier} else {} end | ||
74 | + | ||
75 | + custom_object_data_url = self.call defs[:object_data_url], object_data, actor | ||
76 | + object_data_url = if passive then self.passive_url_for object_data, custom_object_data_url, defs, extra_params else self.url_for object_data, custom_object_data_url, extra_params end | ||
77 | + | ||
78 | + actors.each do |actor| | ||
79 | + print_debug "open_graph: start publishing" if debug? actor | ||
80 | + begin | ||
81 | + self.publish actor, defs, object_data_url | ||
82 | + rescue => e | ||
83 | + print_debug "open_graph: can't publish story: #{e.message}" if debug? actor | ||
84 | + ExceptionNotifier.notify_exception e | ||
85 | + end | ||
86 | + end | ||
87 | + end | ||
88 | + end | ||
89 | + | ||
90 | + def story_trackers story_defs, actor, object_data | ||
91 | + passive = story_defs[:passive] | ||
92 | + trackers = [] | ||
93 | + | ||
94 | + track_configs = Array(story_defs[:track_config]).compact.map(&:constantize) | ||
95 | + return if track_configs.empty? | ||
96 | + print_debug "open_graph: using configs: #{track_configs.map(&:name).inspect}" if debug? actor | ||
97 | + | ||
98 | + if passive | ||
99 | + object_profile = self.call(story_defs[:object_profile], object_data) || object_data.profile rescue nil | ||
100 | + return unless object_profile | ||
101 | + | ||
102 | + track_configs.each do |c| | ||
103 | + trackers.concat c.trackers_to_profile(object_profile) | ||
104 | + end.flatten | ||
105 | + | ||
106 | + trackers.select! do |t| | ||
107 | + track_configs.any?{ |c| c.enabled? self.context, t } | ||
108 | + end | ||
109 | + else #active | ||
110 | + object_actor = self.call(story_defs[:object_actor], object_data) || object_data.profile rescue nil | ||
111 | + return unless object_actor and object_actor.person? | ||
112 | + custom_actor = self.call(story_defs[:custom_actor], object_data) | ||
113 | + actor = custom_actor if custom_actor | ||
114 | + | ||
115 | + match_track = track_configs.any? do |c| | ||
116 | + c.enabled?(self.context, actor) and | ||
117 | + actor.send("open_graph_#{c.track_name}_track_configs").where(object_type: story_defs[:object_type]).first | ||
118 | + end | ||
119 | + trackers << actor if match_track | ||
120 | + end | ||
121 | + | ||
122 | + trackers | ||
123 | + end | ||
124 | + | ||
125 | + protected | ||
126 | + | ||
127 | + include MetadataPlugin::UrlHelper | ||
128 | + | ||
129 | + def register_publish attributes | ||
130 | + OpenGraphPlugin::Activity.create! attributes | ||
131 | + end | ||
132 | + | ||
133 | + # Call don't ask: move to a og_url method inside object | ||
134 | + def url_for object, custom_url=nil, extra_params={} | ||
135 | + return custom_url if custom_url.is_a? String | ||
136 | + url = custom_url || if object.is_a? Profile then og_profile_url object else object.url end | ||
137 | + # for profile when custom domain is used | ||
138 | + url.merge! profile: object.profile.identifier if object.respond_to? :profile | ||
139 | + url.merge! extra_params | ||
140 | + self.og_url_for url | ||
141 | + end | ||
142 | + | ||
143 | + def passive_url_for object, custom_url, story_defs, extra_params={} | ||
144 | + object_type = story_defs[:object_type] | ||
145 | + extra_params.merge! og_type: MetadataPlugin.og_types[object_type] | ||
146 | + self.url_for object, custom_url, extra_params | ||
147 | + end | ||
148 | + | ||
149 | + def call p, *args | ||
150 | + p and instance_exec *args, &p | ||
151 | + end | ||
152 | + | ||
153 | + def context | ||
154 | + :open_graph | ||
155 | + end | ||
156 | + | ||
157 | + def print_debug msg | ||
158 | + puts msg | ||
159 | + Delayed::Worker.logger.debug msg | ||
160 | + end | ||
161 | + def debug? actor=nil | ||
162 | + !Rails.env.production? | ||
163 | + end | ||
164 | + | ||
165 | +end | ||
166 | + |
@@ -0,0 +1,14 @@ | @@ -0,0 +1,14 @@ | ||
1 | +class OpenGraphPlugin::Settings < Noosfero::Plugin::Settings | ||
2 | + | ||
3 | + def self.new base, attrs = {} | ||
4 | + super base, self.parents.first, attrs | ||
5 | + end | ||
6 | + | ||
7 | + OpenGraphPlugin::TrackConfig::Types.each do |track, klass| | ||
8 | + define_method "#{track}_track_enabled=" do |value| | ||
9 | + super ActiveRecord::ConnectionAdapters::Column.value_to_boolean(value) | ||
10 | + end | ||
11 | + end | ||
12 | + | ||
13 | +end | ||
14 | + |
@@ -0,0 +1,302 @@ | @@ -0,0 +1,302 @@ | ||
1 | + | ||
2 | +class OpenGraphPlugin::Stories | ||
3 | + | ||
4 | + class_attribute :publishers | ||
5 | + self.publishers = [] | ||
6 | + | ||
7 | + def self.register_publisher publisher | ||
8 | + self.publishers << publisher | ||
9 | + end | ||
10 | + | ||
11 | + def self.publish record, stories | ||
12 | + actor = User.current.person rescue nil | ||
13 | + return unless actor | ||
14 | + | ||
15 | + self.publishers.each do |publisher| | ||
16 | + publisher = publisher.delay unless Rails.env.development? or Rails.env.test? | ||
17 | + publisher.publish_stories record, actor, stories | ||
18 | + end | ||
19 | + end | ||
20 | + | ||
21 | + Definitions = { | ||
22 | + # needed a patch on UploadedFile: def notifiable?; true; end | ||
23 | + add_a_document: { | ||
24 | + action_tracker_verb: :create_article, | ||
25 | + track_config: 'OpenGraphPlugin::ActivityTrackConfig', | ||
26 | + action: :add, | ||
27 | + object_type: :uploaded_file, | ||
28 | + models: :UploadedFile, | ||
29 | + on: :create, | ||
30 | + criteria: proc do |article, actor| | ||
31 | + article.is_a? UploadedFile | ||
32 | + end, | ||
33 | + publish_if: proc do |uploaded_file, actor| | ||
34 | + # done in add_an_image | ||
35 | + next false if uploaded_file.image? | ||
36 | + uploaded_file.published? | ||
37 | + end, | ||
38 | + object_data_url: proc do |uploaded_file, actor| | ||
39 | + uploaded_file.url.merge view: true | ||
40 | + end, | ||
41 | + }, | ||
42 | + add_an_image: { | ||
43 | + # :upload_image verb can't be used as it uses the parent Gallery as target | ||
44 | + # hooked via open_graph_attach_stories | ||
45 | + action_tracker_verb: nil, | ||
46 | + track_config: 'OpenGraphPlugin::ActivityTrackConfig', | ||
47 | + action: :add, | ||
48 | + object_type: :gallery_image, | ||
49 | + models: :UploadedFile, | ||
50 | + on: :create, | ||
51 | + criteria: proc do |article, actor| | ||
52 | + article.is_a? UploadedFile | ||
53 | + end, | ||
54 | + publish_if: proc do |uploaded_file, actor| | ||
55 | + uploaded_file.image? and uploaded_file.parent.is_a? Gallery | ||
56 | + end, | ||
57 | + object_data_url: proc do |uploaded_file, actor| | ||
58 | + uploaded_file.url.merge view: true | ||
59 | + end, | ||
60 | + }, | ||
61 | + create_an_article: { | ||
62 | + action_tracker_verb: :create_article, | ||
63 | + track_config: 'OpenGraphPlugin::ActivityTrackConfig', | ||
64 | + action: :create, | ||
65 | + object_type: :blog_post, | ||
66 | + models: :Article, | ||
67 | + on: :create, | ||
68 | + criteria: proc do |article, actor| | ||
69 | + article.parent.is_a? Blog | ||
70 | + end, | ||
71 | + publish_if: proc do |article, actor| | ||
72 | + article.published? | ||
73 | + end, | ||
74 | + }, | ||
75 | + create_an_event: { | ||
76 | + action_tracker_verb: :create_article, | ||
77 | + track_config: 'OpenGraphPlugin::ActivityTrackConfig', | ||
78 | + action: :create, | ||
79 | + object_type: :event, | ||
80 | + models: :Event, | ||
81 | + on: :create, | ||
82 | + criteria: proc do |article, actor| | ||
83 | + article.is_a? Event | ||
84 | + end, | ||
85 | + publish_if: proc do |event, actor| | ||
86 | + event.published? | ||
87 | + end, | ||
88 | + }, | ||
89 | + start_a_discussion: { | ||
90 | + action_tracker_verb: :create_article, | ||
91 | + track_config: 'OpenGraphPlugin::ActivityTrackConfig', | ||
92 | + action: :start, | ||
93 | + object_type: :forum, | ||
94 | + models: :Article, | ||
95 | + on: :create, | ||
96 | + criteria: proc do |article, actor| | ||
97 | + article.parent.is_a? Forum | ||
98 | + end, | ||
99 | + publish_if: proc do |article, actor| | ||
100 | + article.published? | ||
101 | + end, | ||
102 | + object_data_url: proc do |article, actor| | ||
103 | + url = article.url | ||
104 | + if og_type = MetadataPlugin::og_types[:forum] | ||
105 | + url[:og_type] = og_type | ||
106 | + end | ||
107 | + url | ||
108 | + end, | ||
109 | + }, | ||
110 | + | ||
111 | + # these a published as passive to give focus to the enterprise | ||
112 | +=begin | ||
113 | + add_a_sse_product: { | ||
114 | + action_tracker_verb: :create_product, | ||
115 | + track_config: 'OpenGraphPlugin::ActivityTrackConfig', | ||
116 | + action: :announce_new, | ||
117 | + models: :Product, | ||
118 | + on: :create, | ||
119 | + object_type: :product, | ||
120 | + publish_if: proc do |product, actor| | ||
121 | + product.profile.public? | ||
122 | + end, | ||
123 | + }, | ||
124 | + update_a_sse_product: { | ||
125 | + action_tracker_verb: :update_product, | ||
126 | + track_config: 'OpenGraphPlugin::ActivityTrackConfig', | ||
127 | + action: :announce_update, | ||
128 | + object_type: :product, | ||
129 | + models: :Product, | ||
130 | + on: :update, | ||
131 | + publish_if: proc do |product, actor| | ||
132 | + product.profile.public? | ||
133 | + end, | ||
134 | + }, | ||
135 | +=end | ||
136 | + | ||
137 | + favorite_a_sse_initiative: { | ||
138 | + action_tracker_verb: :favorite_enterprise, | ||
139 | + track_config: 'OpenGraphPlugin::ActivityTrackConfig', | ||
140 | + action: :favorite, | ||
141 | + object_type: :favorite_enterprise, | ||
142 | + models: :FavoriteEnterprisePerson, | ||
143 | + on: :create, | ||
144 | + object_actor: proc do |favorite_enterprise_person| | ||
145 | + favorite_enterprise_person.person | ||
146 | + end, | ||
147 | + object_profile: proc do |favorite_enterprise_person| | ||
148 | + favorite_enterprise_person.enterprise | ||
149 | + end, | ||
150 | + object_data_url: proc do |favorite_enterprise_person, actor| | ||
151 | + self.og_profile_url favorite_enterprise_person.enterprise | ||
152 | + end, | ||
153 | + }, | ||
154 | + | ||
155 | +=begin | ||
156 | + comment_a_discussion: { | ||
157 | + action_tracker_verb: nil, | ||
158 | + action: :comment, | ||
159 | + object_type: :forum, | ||
160 | + models: :Comment, | ||
161 | + on: :create, | ||
162 | + criteria: proc do |comment, actor| | ||
163 | + source, parent = comment.source, comment.source.parent | ||
164 | + source.is_a? Article and parent.is_a? Forum | ||
165 | + end, | ||
166 | + publish_if: proc do |comment, actor| | ||
167 | + comment.source.parent.published? | ||
168 | + end, | ||
169 | + }, | ||
170 | + comment_an_article: { | ||
171 | + action_tracker_verb: nil, | ||
172 | + action: :comment, | ||
173 | + object_type: :blog_post, | ||
174 | + models: :Comment, | ||
175 | + on: :create, | ||
176 | + criteria: proc do |comment, actor| | ||
177 | + source, parent = comment.source, comment.source.parent | ||
178 | + source.is_a? Article and parent.is_a? Blog | ||
179 | + end, | ||
180 | + publish_if: proc do |comment, actor| | ||
181 | + comment.source.parent.published? | ||
182 | + end, | ||
183 | + }, | ||
184 | +=end | ||
185 | + | ||
186 | + make_friendship_with: { | ||
187 | + action_tracker_verb: :new_friendship, | ||
188 | + track_config: 'OpenGraphPlugin::ActivityTrackConfig', | ||
189 | + action: :make_friendship, | ||
190 | + object_type: :friend, | ||
191 | + models: :Friendship, | ||
192 | + on: :create, | ||
193 | + custom_actor: proc do |friendship| | ||
194 | + friendship.person | ||
195 | + end, | ||
196 | + object_actor: proc do |friendship| | ||
197 | + friendship.person | ||
198 | + end, | ||
199 | + object_profile: proc do |friendship| | ||
200 | + friendship.friend | ||
201 | + end, | ||
202 | + object_data_url: proc do |friendship, actor| | ||
203 | + self.og_profile_url friendship.friend | ||
204 | + end, | ||
205 | + }, | ||
206 | + | ||
207 | + # PASSIVE STORIES | ||
208 | + announce_news_from_a_sse_initiative: { | ||
209 | + action_tracker_verb: :create_article, | ||
210 | + track_config: 'OpenGraphPlugin::EnterpriseTrackConfig', | ||
211 | + action: :announce_news, | ||
212 | + object_type: :enterprise, | ||
213 | + passive: true, | ||
214 | + models: :Article, | ||
215 | + on: :create, | ||
216 | + criteria: proc do |article, actor| | ||
217 | + article.profile.enterprise? | ||
218 | + end, | ||
219 | + publish_if: proc do |article, actor| | ||
220 | + article.published? | ||
221 | + end, | ||
222 | + }, | ||
223 | + announce_a_new_sse_product: { | ||
224 | + action_tracker_verb: :create_product, | ||
225 | + track_config: 'OpenGraphPlugin::EnterpriseTrackConfig', | ||
226 | + action: :announce_new, | ||
227 | + object_type: :product, | ||
228 | + passive: true, | ||
229 | + models: :Product, | ||
230 | + on: :create, | ||
231 | + criteria: proc do |product, actor| | ||
232 | + product.profile.enterprise? | ||
233 | + end, | ||
234 | + }, | ||
235 | + announce_an_update_of_sse_product: { | ||
236 | + action_tracker_verb: :update_product, | ||
237 | + track_config: 'OpenGraphPlugin::EnterpriseTrackConfig', | ||
238 | + action: :announce_update, | ||
239 | + object_type: :product, | ||
240 | + passive: true, | ||
241 | + models: :Product, | ||
242 | + on: :update, | ||
243 | + criteria: proc do |product, actor| | ||
244 | + product.profile.enterprise? | ||
245 | + end, | ||
246 | + }, | ||
247 | + | ||
248 | + announce_news_from_a_community: { | ||
249 | + action_tracker_verb: :create_article, | ||
250 | + track_config: 'OpenGraphPlugin::CommunityTrackConfig', | ||
251 | + action: :announce_news, | ||
252 | + object_type: :community, | ||
253 | + passive: true, | ||
254 | + models: :Article, | ||
255 | + on: :create, | ||
256 | + criteria: proc do |article, actor| | ||
257 | + article.profile.community? | ||
258 | + end, | ||
259 | + publish_if: proc do |article, actor| | ||
260 | + article.published? | ||
261 | + end, | ||
262 | + }, | ||
263 | + | ||
264 | + } | ||
265 | + | ||
266 | + ValidObjectList = Definitions.map{ |story, data| data[:object_type] }.uniq | ||
267 | + ValidActionList = Definitions.map{ |story, data| data[:action] }.uniq | ||
268 | + | ||
269 | + # TODO make this verification work | ||
270 | + #raise "Each active story must use a unique object_type for configuration to work" if ValidObjectList.size < Definitions.size | ||
271 | + | ||
272 | + DefaultActions = ValidActionList.inject({}){ |h, a| h[a] = a; h } | ||
273 | + DefaultObjects = ValidObjectList.inject({}){ |h, o| h[o] = o; h } | ||
274 | + | ||
275 | + TrackerStories = {}; Definitions.each do |story, data| | ||
276 | + Array(data[:action_tracker_verb]).each do |verb| | ||
277 | + next unless verb | ||
278 | + TrackerStories[verb] ||= [] | ||
279 | + TrackerStories[verb] << story | ||
280 | + end | ||
281 | + end | ||
282 | + | ||
283 | + TrackConfigStories = {}; Definitions.each do |story, data| | ||
284 | + Array(data[:track_config]).each do |track_config| | ||
285 | + next unless track_config | ||
286 | + TrackConfigStories[track_config] ||= [] | ||
287 | + TrackConfigStories[track_config] << [story, data] | ||
288 | + end | ||
289 | + end | ||
290 | + | ||
291 | + ModelStories = {}; Definitions.each do |story, data| | ||
292 | + Array(data[:models]).each do |model| | ||
293 | + ModelStories[model] ||= {} | ||
294 | + Array(data[:on]).each do |on| | ||
295 | + ModelStories[model][on] ||= [] | ||
296 | + ModelStories[model][on] << story | ||
297 | + end | ||
298 | + end | ||
299 | + end | ||
300 | + | ||
301 | +end | ||
302 | + |
@@ -0,0 +1,43 @@ | @@ -0,0 +1,43 @@ | ||
1 | + | ||
2 | +"en-US": &en-US | ||
3 | + | ||
4 | + open_graph_plugin: | ||
5 | + lib: | ||
6 | + plugin: | ||
7 | + name: 'OpenGraph' | ||
8 | + description: 'OpenGraph' | ||
9 | + views: | ||
10 | + track: | ||
11 | + config: | ||
12 | + activity: | ||
13 | + configure: 'Configure' | ||
14 | + label: "My activities: new photos on my albuns, blogs's posts and other contents" | ||
15 | + objects: | ||
16 | + blog_post: "Blogs' posts" | ||
17 | + event: 'Creation of events' | ||
18 | + favorite_enterprise: 'Quando eu favoritar um empreendimento' | ||
19 | + forum: "Forum's topic posted" | ||
20 | + friend: 'New friendships' | ||
21 | + gallery_image: 'New images on my albuns' | ||
22 | + uploaded_file: 'Files sent' | ||
23 | + enterprise: | ||
24 | + memberships: "Enterprises that I'm a member of" | ||
25 | + favorites: "My favorite enterprises" | ||
26 | + see_all: 'See enterprises' | ||
27 | + label: "News from enterprises that I am a member and my favorites" | ||
28 | + search_placeholder: "type to find enterprises" | ||
29 | + favorites_how_to: | ||
30 | + title: "How to add favorite Solidarity Economy initiatives" | ||
31 | + body: "To add favorite Solidarity Economy initiatives, you should visit its page in Cirandas and click on button %{favorite_button} which is located below its logo, normally on the left side." | ||
32 | + community: | ||
33 | + label: "News from selected communities" | ||
34 | + search_placeholder: "type to find communities" | ||
35 | + friend: | ||
36 | + label: "News from friends" | ||
37 | + search_placeholder: "type to find friends" | ||
38 | + | ||
39 | +'en_US': | ||
40 | + <<: *en-US | ||
41 | +'en': | ||
42 | + <<: *en-US | ||
43 | + |
@@ -0,0 +1,40 @@ | @@ -0,0 +1,40 @@ | ||
1 | + | ||
2 | +"pt-BR": &pt-BR | ||
3 | + | ||
4 | + open_graph_plugin: | ||
5 | + lib: | ||
6 | + plugin: | ||
7 | + name: 'OpenGraph' | ||
8 | + description: 'OpenGraph' | ||
9 | + views: | ||
10 | + track: | ||
11 | + config: | ||
12 | + activity: | ||
13 | + configure: 'Configurar' | ||
14 | + label: 'Publicar minhas atividades do cirandas no meu mural do facebook' | ||
15 | + objects: | ||
16 | + blog_post: 'Quando eu criar um conteúdo ou artigo' | ||
17 | + event: 'Quando eu adicionar eventos' | ||
18 | + forum: 'Quando eu criar novos tópicos de fórum' | ||
19 | + friend: 'Quando eu fizer amizades' | ||
20 | + gallery_image: 'Quando eu adicionar imagens nos meus albuns' | ||
21 | + uploaded_file: 'Quando eu enviar novos documentos' | ||
22 | + favorite_enterprise: 'Quando eu favoritar um empreendimento' | ||
23 | + enterprise: | ||
24 | + memberships: "Empreendimentos dos quais faço parte" | ||
25 | + favorites: "Meus empreendimentos favoritos" | ||
26 | + see_all: 'Ver empreendimentos' | ||
27 | + label: "Publicar as novidades dos meus empreendimentos favoritos e daqueles que faço parte" | ||
28 | + search_placeholder: "busque o empreendimento" | ||
29 | + favorites_how_to: | ||
30 | + title: "Como adicionar empreendimentos favoritos" | ||
31 | + body: "Para adicionar empreendimentos favoritos, basta você visitar a página do empreendimento desejado e clicar no botão %{favorite_button} que fica abaixo da logo do empreendimento, geralmente à esquerda." | ||
32 | + community: | ||
33 | + label: "Publicar novidades das seguintes comunidades" | ||
34 | + search_placeholder: "escolha a comunidade" | ||
35 | + | ||
36 | +'pt_BR': | ||
37 | + <<: *pt-BR | ||
38 | +'pt': | ||
39 | + <<: *pt-BR | ||
40 | + |
plugins/open_graph/models/open_graph_plugin/activity_track_config.rb
0 → 100644
@@ -0,0 +1,22 @@ | @@ -0,0 +1,22 @@ | ||
1 | +class OpenGraphPlugin::ActivityTrackConfig < OpenGraphPlugin::TrackConfig | ||
2 | + | ||
3 | + # workaround for STI bug | ||
4 | + self.table_name = :open_graph_plugin_tracks | ||
5 | + | ||
6 | + self.track_name = :activity | ||
7 | + | ||
8 | + Objects = OpenGraphPlugin::Stories::TrackConfigStories[self.name].map do |story, data| | ||
9 | + data[:object_type].to_s | ||
10 | + end.uniq | ||
11 | + | ||
12 | + def self.objects | ||
13 | + Objects | ||
14 | + end | ||
15 | + | ||
16 | + validates_uniqueness_of :object_type, scope: [:tracker_id] | ||
17 | + validates_inclusion_of :object_type, in: self.objects | ||
18 | + | ||
19 | + protected | ||
20 | + | ||
21 | +end | ||
22 | + |
plugins/open_graph/models/open_graph_plugin/community_track_config.rb
0 → 100644
plugins/open_graph/models/open_graph_plugin/enterprise_track_config.rb
0 → 100644
@@ -0,0 +1,20 @@ | @@ -0,0 +1,20 @@ | ||
1 | +class OpenGraphPlugin::EnterpriseTrackConfig < OpenGraphPlugin::TrackConfig | ||
2 | + | ||
3 | + # workaround for STI bug | ||
4 | + self.table_name = :open_graph_plugin_tracks | ||
5 | + | ||
6 | + self.track_name = :enterprise | ||
7 | + | ||
8 | + self.static_trackers = true | ||
9 | + | ||
10 | + def self.trackers_to_profile enterprise | ||
11 | + trackers = enterprise.members.to_set | ||
12 | + trackers.merge enterprise.fans if enterprise.respond_to? :fans | ||
13 | + trackers.to_a | ||
14 | + end | ||
15 | + | ||
16 | + def self.profile_track_objects profile | ||
17 | + (profile.enterprises.public.enabled + profile.favorite_enterprises.public.enabled).uniq | ||
18 | + end | ||
19 | + | ||
20 | +end |
plugins/open_graph/models/open_graph_plugin/friend_track_config.rb
0 → 100644
@@ -0,0 +1,28 @@ | @@ -0,0 +1,28 @@ | ||
1 | +class OpenGraphPlugin::Track < ActiveRecord::Base | ||
2 | + | ||
3 | + attr_accessible :type, :context, :tracker_id, :tracker, :actor_id, :action, | ||
4 | + :object_type, :object_data, :object_data_id, :object_data_type, :object_data_url | ||
5 | + | ||
6 | + belongs_to :tracker, class_name: 'Profile' | ||
7 | + belongs_to :actor, class_name: 'Profile' | ||
8 | + belongs_to :object_data, polymorphic: true | ||
9 | + | ||
10 | + validates_presence_of :context | ||
11 | + before_validation :set_context | ||
12 | + | ||
13 | + def self.objects | ||
14 | + [] | ||
15 | + end | ||
16 | + | ||
17 | + def self.association | ||
18 | + @association ||= "open_graph_#{self.name.demodulize.pluralize.underscore}".to_sym | ||
19 | + end | ||
20 | + | ||
21 | + protected | ||
22 | + | ||
23 | + def set_context | ||
24 | + self.context = OpenGraphPlugin.context | ||
25 | + end | ||
26 | + | ||
27 | +end | ||
28 | + |
plugins/open_graph/models/open_graph_plugin/track_config.rb
0 → 100644
@@ -0,0 +1,49 @@ | @@ -0,0 +1,49 @@ | ||
1 | +class OpenGraphPlugin::TrackConfig < OpenGraphPlugin::Track | ||
2 | + | ||
3 | + Types = { | ||
4 | + activity: 'ActivityTrackConfig', | ||
5 | + enterprise: 'EnterpriseTrackConfig', | ||
6 | + community: 'CommunityTrackConfig', | ||
7 | + # TODO: not yet implemented | ||
8 | + #friend: 'FriendTrackConfig', | ||
9 | + } | ||
10 | + | ||
11 | + # define on subclasses (required) | ||
12 | + class_attribute :track_name | ||
13 | + def self.track_enabled_field | ||
14 | + "#{self.track_name}_track_enabled" | ||
15 | + end | ||
16 | + | ||
17 | + # true if do not depend on records (e.g. EnterpriseTrackConfig depends on friends) | ||
18 | + # redefine on subclasses | ||
19 | + class_attribute :static_trackers | ||
20 | + self.static_trackers = false | ||
21 | + | ||
22 | + def self.enabled? context, actor | ||
23 | + settings = actor.send "#{context}_settings" | ||
24 | + settings.send "#{self.track_name}_track_enabled" | ||
25 | + end | ||
26 | + | ||
27 | + scope :tracks_to_profile, lambda { |profile, exclude_actor=nil| | ||
28 | + scope = where object_data_id: profile.id, object_data_type: profile.class.base_class | ||
29 | + scope = scope.where context: OpenGraphPlugin.context | ||
30 | + scope = scope.includes :tracker | ||
31 | + scope = scope.where ['tracker_id <> ?', exclude_actor.id] if exclude_actor | ||
32 | + scope | ||
33 | + } | ||
34 | + | ||
35 | + # redefine on subclasses | ||
36 | + def self.trackers_to_profile profile | ||
37 | + tracks = self.tracks_to_profile profile | ||
38 | + tracks = tracks.where type: self | ||
39 | + tracks.map(&:tracker) | ||
40 | + end | ||
41 | + | ||
42 | + def self.profile_tracks profile | ||
43 | + profile.send self.association | ||
44 | + end | ||
45 | + def self.profile_track_objects profile | ||
46 | + self.profile_tracks(profile).map(&:object_data).compact | ||
47 | + end | ||
48 | + | ||
49 | +end |
@@ -0,0 +1,181 @@ | @@ -0,0 +1,181 @@ | ||
1 | +open_graph = { | ||
2 | + | ||
3 | + track: { | ||
4 | + | ||
5 | + config: { | ||
6 | + | ||
7 | + view: { | ||
8 | + form: null, | ||
9 | + }, | ||
10 | + | ||
11 | + init: function(reload) { | ||
12 | + this.view.form = $('#track-form form') | ||
13 | + this.view.form.find('.panel-heading').each(function(i, context) { | ||
14 | + open_graph.track.config.headingToggle(context) | ||
15 | + }) | ||
16 | + }, | ||
17 | + | ||
18 | + submit: function() { | ||
19 | + loading_overlay.show($('#track-config')) | ||
20 | + open_graph.track.config.view.form.ajaxSubmit({ | ||
21 | + success: function(data) { | ||
22 | + data = $(data) | ||
23 | + // needs update to get ids from accepts_nested_attributes_for | ||
24 | + $('#track-activity').html(data.find('#track-activity').html()) | ||
25 | + loading_overlay.hide($('#track-config')) | ||
26 | + }, | ||
27 | + }) | ||
28 | + return false; | ||
29 | + }, | ||
30 | + | ||
31 | + // trigged on init state and on subcheckboxes change | ||
32 | + headingToggle: function(context, open) { | ||
33 | + var panel = $(context).parents('.panel') | ||
34 | + var panelHeading = panel.find('.panel-heading') | ||
35 | + var panelBody = panel.find('.panel-body') | ||
36 | + var parentCheckbox = panel.find('.config-check') | ||
37 | + var configButton = panel.find('.config-button') | ||
38 | + var input = panel.find('.track-config-toggle') | ||
39 | + var openWas = input.val() == 'true' | ||
40 | + if (open === undefined) | ||
41 | + open = input.val() == 'true' && (panelHeading.hasClass('enable-on-empty') || this.numberChecked(context) > 0) | ||
42 | + // open is defined, that is an user action | ||
43 | + else { | ||
44 | + if (open) { | ||
45 | + if (panelHeading.hasClass('open-on-enable')) | ||
46 | + panelBody.collapse('show') | ||
47 | + } else | ||
48 | + panelBody.collapse('hide') | ||
49 | + } | ||
50 | + | ||
51 | + configButton.toggle(open) | ||
52 | + parentCheckbox.toggleClass('fa-toggle-on', open) | ||
53 | + parentCheckbox.toggleClass('fa-toggle-off', !open) | ||
54 | + input.prop('value', open) | ||
55 | + if (openWas != open) | ||
56 | + open_graph.track.config.submit() | ||
57 | + }, | ||
58 | + | ||
59 | + // the event of change | ||
60 | + toggleEvent: function(context, event) { | ||
61 | + var panel = $(context).parents('.panel') | ||
62 | + var panelBody = panel.find('.panel-body') | ||
63 | + var checkboxes = panelBody.find('input[type=checkbox]') | ||
64 | + var open = panel.find('.track-config-toggle').val() == 'true' | ||
65 | + open = !open; | ||
66 | + | ||
67 | + checkboxes.prop('checked', open) | ||
68 | + | ||
69 | + this.headingToggle(context, open) | ||
70 | + return false; | ||
71 | + }, | ||
72 | + | ||
73 | + open: function(context) { | ||
74 | + var panel = $(context).parents('.panel') | ||
75 | + var panelBody = panel.find('.panel-body') | ||
76 | + panelBody.collapse('show') | ||
77 | + }, | ||
78 | + | ||
79 | + toggleObjectType: function(checkbox) { | ||
80 | + checkbox = $(checkbox) | ||
81 | + | ||
82 | + this.headingToggle(checkbox) | ||
83 | + | ||
84 | + checkbox.siblings("input[name*='[_destroy]']").val(!checkbox.is(':checked')) | ||
85 | + open_graph.track.config.submit() | ||
86 | + }, | ||
87 | + | ||
88 | + numberChecked: function(context) { | ||
89 | + var panel = $(context).parents('.panel') | ||
90 | + var panelBody = panel.find('.panel-body') | ||
91 | + var checkboxes = panel.find('.panel-body input[type=checkbox]') | ||
92 | + var profilesInput = panel.find('.panel-body .select-profiles') | ||
93 | + | ||
94 | + var nObjects = checkboxes.filter(':checked').length | ||
95 | + var nProfiles = profilesInput.length ? profilesInput.tokenfield('getTokens').length : 0; | ||
96 | + var nChecked = nObjects + nProfiles; | ||
97 | + var nTotal = checkboxes.length + nProfiles | ||
98 | + | ||
99 | + return nChecked | ||
100 | + }, | ||
101 | + | ||
102 | + enterprise: { | ||
103 | + see_all: function(context) { | ||
104 | + var panel = $(context).parents('.panel') | ||
105 | + var panelBody = panel.find('.panel-body') | ||
106 | + noosfero.modal.html(panelBody.html()) | ||
107 | + }, | ||
108 | + }, | ||
109 | + | ||
110 | + initAutocomplete: function(track, url, items) { | ||
111 | + var selector = '#select-'+track | ||
112 | + var input = $(selector) | ||
113 | + var tokenField = open_graph.autocomplete.init(url, selector, items) | ||
114 | + | ||
115 | + input.change(open_graph.track.config.submit) | ||
116 | + tokenField | ||
117 | + .on('tokenfield:createdtoken tokenfield:removedtoken', function() { | ||
118 | + open_graph.track.config.headingToggle(this) | ||
119 | + }).on('tokenfield:createtoken tokenfield:removetoken', function(event) { | ||
120 | + input.val() | ||
121 | + }).on('tokenfield:createtoken', function(event) { | ||
122 | + var existingTokens = $(this).tokenfield('getTokens') | ||
123 | + $.each(existingTokens, function(index, token) { | ||
124 | + if (token.value === event.attrs.value) | ||
125 | + event.preventDefault() | ||
126 | + }) | ||
127 | + }) | ||
128 | + | ||
129 | + return tokenField; | ||
130 | + }, | ||
131 | + | ||
132 | + }, | ||
133 | + }, | ||
134 | + | ||
135 | + autocomplete: { | ||
136 | + bloodhoundOptions: { | ||
137 | + datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'), | ||
138 | + queryTokenizer: Bloodhound.tokenizers.whitespace, | ||
139 | + ajax: { | ||
140 | + beforeSend: function() { | ||
141 | + input.addClass('small-loading') | ||
142 | + }, | ||
143 | + complete: function() { | ||
144 | + input.removeClass('small-loading') | ||
145 | + }, | ||
146 | + }, | ||
147 | + }, | ||
148 | + tokenfieldOptions: { | ||
149 | + | ||
150 | + }, | ||
151 | + typeaheadOptions: { | ||
152 | + minLength: 1, | ||
153 | + highlight: true, | ||
154 | + }, | ||
155 | + | ||
156 | + init: function(url, selector, data, options) { | ||
157 | + options = options || {} | ||
158 | + var bloodhoundOptions = $.extend({}, this.bloodhoundOptions, options.bloodhound || {}); | ||
159 | + var typeaheadOptions = $.extend({}, this.typeaheadOptions, options.typeahead || {}); | ||
160 | + var tokenfieldOptions = $.extend({}, this.tokenfieldOptions, options.tokenfield || {}); | ||
161 | + | ||
162 | + var input = $(selector) | ||
163 | + bloodhoundOptions.remote = { | ||
164 | + url: url, | ||
165 | + replace: function(url, uriEncodedQuery) { | ||
166 | + return $.param.querystring(url, {query:uriEncodedQuery}); | ||
167 | + }, | ||
168 | + } | ||
169 | + var engine = new Bloodhound(bloodhoundOptions) | ||
170 | + engine.initialize() | ||
171 | + | ||
172 | + tokenfieldOptions.typeahead = [typeaheadOptions, { displayKey: 'label', source: engine.ttAdapter() }] | ||
173 | + | ||
174 | + var tokenField = input.tokenfield(tokenfieldOptions) | ||
175 | + input.tokenfield('setTokens', data) | ||
176 | + | ||
177 | + return input | ||
178 | + }, | ||
179 | + }, | ||
180 | +} | ||
181 | + |
@@ -0,0 +1,66 @@ | @@ -0,0 +1,66 @@ | ||
1 | +#track-form { | ||
2 | + | ||
3 | + .panel-heading { | ||
4 | + a, a:visited { | ||
5 | + color: #fff; | ||
6 | + display: block; | ||
7 | + text-decoration: none; | ||
8 | + } | ||
9 | + a:hover { | ||
10 | + text-decoration: underline; | ||
11 | + } | ||
12 | + a.btn { | ||
13 | + display: inline-block; | ||
14 | + text-decoration: none; | ||
15 | + } | ||
16 | + } | ||
17 | + | ||
18 | + // always use one line to fit placeholder | ||
19 | + .tokenfield { | ||
20 | + | ||
21 | + .twitter-typeahead { | ||
22 | + width: 100%; | ||
23 | + display: block; | ||
24 | + | ||
25 | + .tt-input { | ||
26 | + width: 100% !important; | ||
27 | + } | ||
28 | + } | ||
29 | + } | ||
30 | + | ||
31 | + #track-config { | ||
32 | + .panel-heading { | ||
33 | + padding-left: 36px; | ||
34 | + } | ||
35 | + span.config-check { | ||
36 | + font-weight: bold; | ||
37 | + margin-left: -26px; | ||
38 | + margin-right: 4px; | ||
39 | + } | ||
40 | + span.config-check.fa-toggle-off { | ||
41 | + color: #99f; | ||
42 | + } | ||
43 | + .activity-config, .sse-config, .community-config { | ||
44 | + float:right; | ||
45 | + } | ||
46 | + .activity-label, .sse-label, .community-label { | ||
47 | + margin-right: 90px; | ||
48 | + } | ||
49 | + } | ||
50 | +} | ||
51 | + | ||
52 | +// shown inside a popin | ||
53 | +.open-graph-enterprises-modal { | ||
54 | + overflow: hidden; | ||
55 | + | ||
56 | + h1 { | ||
57 | + font-size: 22px; | ||
58 | + } | ||
59 | + #open-graph-favorite-enterprises-how-to { | ||
60 | + clear:both; | ||
61 | + padding-top: 1px; | ||
62 | + } | ||
63 | + p { | ||
64 | + text-align:justify; | ||
65 | + } | ||
66 | +} |
plugins/open_graph/test/functional/open_graph_graph/my_profile_controller_test.rb
0 → 100644
@@ -0,0 +1,54 @@ | @@ -0,0 +1,54 @@ | ||
1 | +require 'test_helper' | ||
2 | +require 'open_graph_plugin/myprofile_controller' | ||
3 | + | ||
4 | +# Re-raise errors caught by the controller. | ||
5 | +class OpenGraphPlugin::MyprofileController; def rescue_action(e) raise e end; end | ||
6 | + | ||
7 | +class OpenGraphPlugin::MyprofileControllerTest < ActionController::TestCase | ||
8 | + | ||
9 | + def setup | ||
10 | + @controller = OpenGraphPlugin::MyprofileController.new | ||
11 | + @request = ActionController::TestRequest.new | ||
12 | + @response = ActionController::TestResponse.new | ||
13 | + @actor = create_user.person | ||
14 | + end | ||
15 | + | ||
16 | + should "save selected activities" do | ||
17 | + login_as @actor.identifier | ||
18 | + @myenterprise = @actor.environment.enterprises.create! name: 'mycoop', identifier: 'mycoop' | ||
19 | + @myenterprise.add_member @actor | ||
20 | + @enterprise = @actor.environment.enterprises.create! name: 'coop', identifier: 'coop' | ||
21 | + @enterprise.fans << @actor | ||
22 | + | ||
23 | + post :track_config, profile: @actor.identifier, profile_data: { | ||
24 | + open_graph_settings: { | ||
25 | + activity_track_enabled: "true", | ||
26 | + enterprise_track_enabled: "true", | ||
27 | + community_track_enabled: "false", | ||
28 | + }, | ||
29 | + open_graph_activity_track_configs_attributes: { | ||
30 | + 0 => { | ||
31 | + tracker_id: @actor.id, | ||
32 | + object_type: 'blog_post', | ||
33 | + }, | ||
34 | + }, | ||
35 | + | ||
36 | + # ignored, enterprise uses static tracking | ||
37 | + open_graph_enterprise_profiles_ids: [@enterprise.id], | ||
38 | + } | ||
39 | + @actor.reload | ||
40 | + | ||
41 | + assert_equal true, @actor.open_graph_settings.activity_track_enabled | ||
42 | + assert_equal true, @actor.open_graph_settings.enterprise_track_enabled | ||
43 | + assert_equal false, @actor.open_graph_settings.community_track_enabled | ||
44 | + | ||
45 | + assert_equal 1, @actor.open_graph_activity_track_configs.count | ||
46 | + assert_equal 'blog_post', @actor.open_graph_activity_track_configs.first.object_type | ||
47 | + assert_equal @actor.id, @actor.open_graph_activity_track_configs.first.tracker_id | ||
48 | + | ||
49 | + assert_equal [@actor], OpenGraphPlugin::EnterpriseTrackConfig.trackers_to_profile(@enterprise) | ||
50 | + assert_equal [@actor], OpenGraphPlugin::EnterpriseTrackConfig.trackers_to_profile(@myenterprise) | ||
51 | + | ||
52 | + end | ||
53 | + | ||
54 | +end |
plugins/open_graph/test/unit/open_graph_graph/publisher_test.rb
0 → 100644
@@ -0,0 +1,111 @@ | @@ -0,0 +1,111 @@ | ||
1 | +require "test_helper" | ||
2 | + | ||
3 | +class OpenGraphPlugin::PublisherTest < ActiveSupport::TestCase | ||
4 | + | ||
5 | + def setup | ||
6 | + @actor = create_user.person | ||
7 | + User.current = @actor.user | ||
8 | + @stories = OpenGraphPlugin::Stories::Definitions | ||
9 | + @publisher = OpenGraphPlugin::Publisher.new | ||
10 | + OpenGraphPlugin::Stories.stubs(:publishers).returns([@publisher]) | ||
11 | + @publisher.stubs(:context).returns(:open_graph) | ||
12 | + @publisher.stubs(:og_domain).returns('noosfero.net') | ||
13 | + end | ||
14 | + | ||
15 | + should "publish only tracked stuff" do | ||
16 | + @other_actor = create_user.person | ||
17 | + | ||
18 | + @myenterprise = @actor.environment.enterprises.create! name: 'mycoop', identifier: 'mycoop' | ||
19 | + @myenterprise.add_member @actor | ||
20 | + @enterprise = @actor.environment.enterprises.create! name: 'coop', identifier: 'coop' | ||
21 | + # the original domain from open_graph should be used | ||
22 | + @enterprise.domains.create! name: 'customdomain.com' | ||
23 | + | ||
24 | + @community = @actor.environment.communities.create! name: 'comm', identifier: 'comm', closed: false | ||
25 | + | ||
26 | + @actor.update_attributes!({ | ||
27 | + open_graph_settings: { | ||
28 | + activity_track_enabled: "true", | ||
29 | + enterprise_track_enabled: "true", | ||
30 | + community_track_enabled: "true", | ||
31 | + }, | ||
32 | + open_graph_activity_track_configs_attributes: { | ||
33 | + 0 => { tracker_id: @actor.id, object_type: 'blog_post', }, | ||
34 | + 1 => { tracker_id: @actor.id, object_type: 'gallery_image', }, | ||
35 | + 2 => { tracker_id: @actor.id, object_type: 'uploaded_file', }, | ||
36 | + 3 => { tracker_id: @actor.id, object_type: 'event', }, | ||
37 | + 4 => { tracker_id: @actor.id, object_type: 'forum', }, | ||
38 | + 5 => { tracker_id: @actor.id, object_type: 'friend', }, | ||
39 | + 6 => { tracker_id: @actor.id, object_type: 'favorite_enterprise', }, | ||
40 | + }, | ||
41 | + open_graph_enterprise_profiles_ids: "#{@enterprise.id}", | ||
42 | + open_graph_community_profiles_ids: "#{@community.id}", | ||
43 | + }) | ||
44 | + @other_actor.update_attributes! open_graph_settings: { activity_track_enabled: "true", }, | ||
45 | + open_graph_activity_track_configs_attributes: { 0 => { tracker_id: @other_actor.id, object_type: 'friend', }, } | ||
46 | + | ||
47 | + # active | ||
48 | + User.current = @actor.user | ||
49 | + | ||
50 | + blog = Blog.create! profile: @actor, name: 'blog' | ||
51 | + blog_post = TinyMceArticle.new profile: User.current.person, parent: blog, name: 'blah', author: User.current.person | ||
52 | + @publisher.expects(:publish).with(User.current.person, @stories[:create_an_article], @publisher.send(:url_for, blog_post)) | ||
53 | + blog_post.save! | ||
54 | + | ||
55 | + gallery = Gallery.create! name: 'gallery', profile: User.current.person | ||
56 | + image = UploadedFile.new uploaded_data: fixture_file_upload('/files/rails.png', 'image/png'), parent: gallery, profile: User.current.person | ||
57 | + @publisher.expects(:publish).with(User.current.person, @stories[:add_an_image], @publisher.send(:url_for, image, image.url.merge(view: true))) | ||
58 | + image.save! | ||
59 | + | ||
60 | + document = UploadedFile.new uploaded_data: fixture_file_upload('/files/doctest.en.xhtml', 'text/html'), profile: User.current.person | ||
61 | + @publisher.expects(:publish).with(User.current.person, @stories[:add_a_document], @publisher.send(:url_for, document, document.url.merge(view: true))) | ||
62 | + document.save! | ||
63 | + | ||
64 | + event = Event.new name: 'event', profile: User.current.person | ||
65 | + @publisher.expects(:publish).with(User.current.person, @stories[:create_an_event], @publisher.send(:url_for, event)) | ||
66 | + event.save! | ||
67 | + | ||
68 | + forum = Forum.create! name: 'forum', profile: User.current.person | ||
69 | + topic = TinyMceArticle.new profile: User.current.person, parent: forum, name: 'blah2', author: User.current.person | ||
70 | + @publisher.expects(:publish).with(User.current.person, @stories[:start_a_discussion], @publisher.send(:url_for, topic, topic.url.merge(og_type: MetadataPlugin.og_types[:forum]))) | ||
71 | + topic.save! | ||
72 | + | ||
73 | + @publisher.expects(:publish).with(@actor, @stories[:make_friendship_with], @publisher.send(:url_for, @other_actor)).twice | ||
74 | + @publisher.expects(:publish).with(@other_actor, @stories[:make_friendship_with], @publisher.send(:url_for, @actor)).twice | ||
75 | + AddFriend.create!(person: @actor, friend: @other_actor).finish | ||
76 | + Friendship.remove_friendship @actor, @other_actor | ||
77 | + # friend verb is groupable | ||
78 | + AddFriend.create!(person: @actor, friend: @other_actor).finish | ||
79 | + | ||
80 | + @publisher.expects(:publish).with(User.current.person, @stories[:favorite_a_sse_initiative], @publisher.send(:url_for, @enterprise)) | ||
81 | + @enterprise.fans << User.current.person | ||
82 | + | ||
83 | + # active but published as passive | ||
84 | + User.current = @actor.user | ||
85 | + | ||
86 | + blog_post = TinyMceArticle.new profile: @enterprise, parent: @enterprise.blog, name: 'blah', author: User.current.person | ||
87 | + story = @stories[:announce_news_from_a_sse_initiative] | ||
88 | + @publisher.expects(:publish).with(User.current.person, story, @publisher.send(:passive_url_for, blog_post, nil, story)) | ||
89 | + blog_post.save! | ||
90 | + | ||
91 | + # passive | ||
92 | + User.current = @other_actor.user | ||
93 | + | ||
94 | + # fan | ||
95 | + blog_post = TinyMceArticle.new profile: @enterprise, parent: @enterprise.blog, name: 'blah2', author: User.current.person | ||
96 | + story = @stories[:announce_news_from_a_sse_initiative] | ||
97 | + @publisher.expects(:publish).with(@actor, story, 'http://noosfero.net/coop/blog/blah2') | ||
98 | + blog_post.save! | ||
99 | + # member | ||
100 | + blog_post = TinyMceArticle.new profile: @myenterprise, parent: @myenterprise.blog, name: 'blah2', author: User.current.person | ||
101 | + story = @stories[:announce_news_from_a_sse_initiative] | ||
102 | + @publisher.expects(:publish).with(@actor, story, 'http://noosfero.net/mycoop/blog/blah2') | ||
103 | + blog_post.save! | ||
104 | + | ||
105 | + blog_post = TinyMceArticle.new profile: @community, parent: @community.blog, name: 'blah', author: User.current.person | ||
106 | + story = @stories[:announce_news_from_a_community] | ||
107 | + @publisher.expects(:publish).with(@actor, story, 'http://noosfero.net/comm/blog/blah') | ||
108 | + blog_post.save! | ||
109 | + end | ||
110 | + | ||
111 | +end |
plugins/open_graph/views/open_graph_plugin/myprofile/_ac_profile.html.erb
0 → 100644
plugins/open_graph/views/open_graph_plugin/myprofile/_heading.html.erb
0 → 100644
@@ -0,0 +1,5 @@ | @@ -0,0 +1,5 @@ | ||
1 | +<span class='config-check fa'></span> | ||
2 | +<%= f.fields_for "#{context}_settings" do |ff| %> | ||
3 | + <%= ff.hidden_field klass.track_enabled_field, value: profile.send("#{context}_settings").send(klass.track_enabled_field), class: 'track-config-toggle' %> | ||
4 | +<% end %> | ||
5 | +<%= t("open_graph_plugin.views.track.config.#{track}.label") %> |
plugins/open_graph/views/open_graph_plugin/myprofile/_profile_search.jsonify
0 → 100644
plugins/open_graph/views/open_graph_plugin/myprofile/_track_activity.html.erb
0 → 100644
@@ -0,0 +1,12 @@ | @@ -0,0 +1,12 @@ | ||
1 | +<div class="panel-heading"> | ||
2 | + <%= button_to_function 'menu-ctrl-panel', t('open_graph_plugin.views.track.config.activity.configure'), "", | ||
3 | + class: 'activity-config config-button', option: 'success', size: 'xs', 'data-target' => "#track-#{track}", 'data-toggle' => 'collapse', 'aria-controls' => 'collapseTwo' %> | ||
4 | + <a href="#" onclick='return open_graph.track.config.toggleEvent(this, event)' class='activity-label'> | ||
5 | + <%= render 'heading', f: f, track: track, context: context, klass: klass %> | ||
6 | + </a> | ||
7 | +</div> | ||
8 | + | ||
9 | +<div id="track-<%=track%>" class="panel-body collapse"> | ||
10 | + <%= render 'track_objects', f: f, track: track, objects: klass.objects, klass: klass, context: context %> | ||
11 | +</div> | ||
12 | + |
plugins/open_graph/views/open_graph_plugin/myprofile/_track_community.html.erb
0 → 100644
@@ -0,0 +1,12 @@ | @@ -0,0 +1,12 @@ | ||
1 | +<div class="panel-heading open-on-enable"> | ||
2 | + <%= button_to_function 'menu-ctrl-panel', t('open_graph_plugin.views.track.config.activity.configure'), "", | ||
3 | + class: 'community-config config-button', option: 'success', size: 'xs', 'data-target' => "#track-#{track}", 'data-toggle' => 'collapse', 'aria-controls' => 'collapseTwo' %> | ||
4 | + <a href="#track-<%=track%>" onclick='open_graph.track.config.toggleEvent(this, event)', class='community-label'> | ||
5 | + <%= render 'heading', f: f, track: track, context: context, klass: klass %> | ||
6 | + </a> | ||
7 | +</div> | ||
8 | + | ||
9 | +<div id="track-<%=track%>" class="panel-body collapse"> | ||
10 | + <%= render 'track_objects', f: f, track: track, objects: klass.objects, klass: klass, context: context %> | ||
11 | + <%= render 'track_profiles', f: f, track: track, context: context, klass: klass %> | ||
12 | +</div> |
plugins/open_graph/views/open_graph_plugin/myprofile/_track_enterprise.html.erb
0 → 100644
@@ -0,0 +1,44 @@ | @@ -0,0 +1,44 @@ | ||
1 | +<div class="panel-heading enable-on-empty"> | ||
2 | + <%= button_to_function 'menu-ctrl-panel', t('open_graph_plugin.views.track.config.enterprise.see_all'), 'open_graph.track.config.enterprise.see_all(this)', | ||
3 | + class: 'sse-config config-button', option: 'success', size: 'xs' %> | ||
4 | + <a href="#" onclick='return open_graph.track.config.toggleEvent(this, event)' style='sse-label'> | ||
5 | + <%= render 'heading', f: f, track: track, context: context, klass: klass %> | ||
6 | + </a> | ||
7 | +</div> | ||
8 | + | ||
9 | +<div id="track-<%=track%>" class="panel-body collapse" style="display: none"> | ||
10 | + <% if user.enterprises.present? %> | ||
11 | + <div id="enterprises-memberships" class="open-graph-enterprises-modal"> | ||
12 | + <h1> | ||
13 | + <%= t('open_graph_plugin.views.track.config.enterprise.memberships') %> | ||
14 | + </h1> | ||
15 | + <div class="open-graph-enterprises-list"> | ||
16 | + <% user.enterprises.public.enabled.each do |enterprise| %> | ||
17 | + <%= profile_image_link enterprise, :portrait, :div %> | ||
18 | + <% end %> | ||
19 | + </div> | ||
20 | + </div> | ||
21 | + <% end %> | ||
22 | + | ||
23 | + <div id="favorite-enterprises" class="open-graph-enterprises-modal"> | ||
24 | + <h1> | ||
25 | + <%= t('open_graph_plugin.views.track.config.enterprise.favorites') %> | ||
26 | + </h1> | ||
27 | + <% if user.favorite_enterprises.present? %> | ||
28 | + <div class="open-graph-enterprises-list"> | ||
29 | + <% user.favorite_enterprises.public.enabled.each do |enterprise| %> | ||
30 | + <%= profile_image_link enterprise, :portrait, :div %> | ||
31 | + <% end %> | ||
32 | + </div> | ||
33 | + <% end %> | ||
34 | + <div id='open-graph-favorite-enterprises-how-to'> | ||
35 | + <h1> | ||
36 | + <%= t('open_graph_plugin.views.track.config.enterprise.favorites_how_to.title') %> | ||
37 | + </h1> | ||
38 | + <p> | ||
39 | + <%= t 'open_graph_plugin.views.track.config.enterprise.favorites_how_to.body', favorite_button: button_to_function(:love, _('Add as favorite'), '', :title => _('Add enterprise as favorite'), :option => 'success') %> | ||
40 | + </p> | ||
41 | + </div> | ||
42 | + </div> | ||
43 | +</div> | ||
44 | + |
plugins/open_graph/views/open_graph_plugin/myprofile/_track_form.html.erb
0 → 100644
@@ -0,0 +1,22 @@ | @@ -0,0 +1,22 @@ | ||
1 | +<% | ||
2 | + reload ||= false | ||
3 | +%> | ||
4 | +<%= javascript_tag do %> | ||
5 | + open_graph.track.config.reload = <%= reload.to_json %> | ||
6 | +<% end %> | ||
7 | + | ||
8 | +<%= form_for profile, as: :profile_data, remote: true, url: {action: :track_config}, | ||
9 | + html: {id: 'track-config', onsubmit: 'return open_graph.track.config.submit()'} do |f| %> | ||
10 | + | ||
11 | + <div class="panel-group" role="tablist" aria-multiselectable="true"> | ||
12 | + <% OpenGraphPlugin::TrackConfig::Types.each do |track, klass| %> | ||
13 | + <div class="panel panel-primary"> | ||
14 | + <%= render "track_#{track}", f: f, track: track, klass: "OpenGraphPlugin::#{klass}".constantize, context: context %> | ||
15 | + </div> | ||
16 | + <% end %> | ||
17 | + </div> | ||
18 | +<% end %> | ||
19 | + | ||
20 | +<%= javascript_tag do %> | ||
21 | + open_graph.track.config.init() | ||
22 | +<% end %> |
plugins/open_graph/views/open_graph_plugin/myprofile/_track_friend.html.erb
0 → 100644
@@ -0,0 +1,10 @@ | @@ -0,0 +1,10 @@ | ||
1 | +<div class="panel-heading"> | ||
2 | + <a href="#track-<%=track%>" data-toggle="collapse" aria-controls="collapseTwo" onclick='open_graph.track.config.toggleEvent(this, event)'> | ||
3 | + <%= render 'heading', f: f, track: track, context: context, klass: klass %> | ||
4 | + </a> | ||
5 | +</div> | ||
6 | + | ||
7 | +<div id="track-<%=track%>" class="panel-body collapse"> | ||
8 | + <%= render 'track_objects', f: f, track: track, objects: klass.objects, klass: klass, context: context %> | ||
9 | + <%= render 'track_profiles', f: f, track: track, context: context, klass: klass %> | ||
10 | +</div> |
plugins/open_graph/views/open_graph_plugin/myprofile/_track_objects.html.erb
0 → 100644
@@ -0,0 +1,17 @@ | @@ -0,0 +1,17 @@ | ||
1 | +<% | ||
2 | + tracks = profile.send klass.association | ||
3 | +%> | ||
4 | + | ||
5 | +<% objects.each do |object| %> | ||
6 | + <div id="object-<%= object %>" class="tracked-object"> | ||
7 | + <% track_record = tracks.find{ |t| t.object_type == object } || profile.send(klass.association).build %> | ||
8 | + <%= f.fields_for klass.association, track_record do |ff| %> | ||
9 | + <%= ff.hidden_field :id %> | ||
10 | + <%= ff.hidden_field :tracker_id %> | ||
11 | + <%= ff.check_box :object_type, {onchange: 'open_graph.track.config.toggleObjectType(this)'}, object, '' %> | ||
12 | + <%= ff.label :object_type, t("open_graph_plugin.views.track.config.#{track}.objects.#{object}") %> | ||
13 | + <%= ff.hidden_field :_destroy %> | ||
14 | + <% end %> | ||
15 | + </div> | ||
16 | +<% end %> | ||
17 | + |
plugins/open_graph/views/open_graph_plugin/myprofile/_track_profiles.html.erb
0 → 100644
@@ -0,0 +1,19 @@ | @@ -0,0 +1,19 @@ | ||
1 | +<% | ||
2 | + static = klass.static_trackers | ||
3 | + profiles = klass.profile_track_objects profile | ||
4 | +%> | ||
5 | +<%= text_field_tag "#{f.object_name}[open_graph_#{track}_profiles_ids]", '', id: "select-#{track}", class: 'select-profiles', | ||
6 | + placeholder: (t("open_graph_plugin.views.track.config.#{track}.search_placeholder") unless static), | ||
7 | + disabled: ("disabled" if static) %> | ||
8 | + | ||
9 | +<%= javascript_tag do %> | ||
10 | + $(document).ready(function () { | ||
11 | + var input = open_graph.track.config.initAutocomplete(<%=track.to_json%>, | ||
12 | + <%= url_for(action: "#{track}_search").to_json %>, | ||
13 | + <%= profiles.map{ |p| {value: p.id, label: render('ac_profile', profile: p), } }.to_json %> | ||
14 | + ) | ||
15 | + <% if static %> | ||
16 | + input.tokenfield('readonly') | ||
17 | + <% end %> | ||
18 | + }) | ||
19 | +<% end %> |