Commit 17b51105dce70f1854f884ec698efdd0b1bd9892
1 parent
3f489bc4
Exists in
theme-brasil-digital-from-staging
and in
9 other branches
proposals_discussion: a plugin to promote a debate over ideas proposed by users
Showing
11 changed files
with
296 additions
and
0 deletions
Show diff stats
plugins/proposals_discussion/lib/proposals_discussion_plugin.rb
0 → 100644
@@ -0,0 +1,36 @@ | @@ -0,0 +1,36 @@ | ||
1 | +class ProposalsDiscussionPlugin < Noosfero::Plugin | ||
2 | + | ||
3 | + def self.plugin_name | ||
4 | + 'Discussion of Proposals' | ||
5 | + end | ||
6 | + | ||
7 | + def self.plugin_description | ||
8 | + _("Provide a structured way to promove a discussion over ideas proposed by users.") | ||
9 | + end | ||
10 | + | ||
11 | + def stylesheet? | ||
12 | + true | ||
13 | + end | ||
14 | + | ||
15 | + def content_types | ||
16 | + if context.respond_to?(:params) && context.params | ||
17 | + types = [] | ||
18 | + parent_id = context.params[:parent_id] | ||
19 | + parent = parent_id ? context.profile.articles.find(parent_id) : nil | ||
20 | + types << ProposalsDiscussionPlugin::Discussion unless parent | ||
21 | + types << ProposalsDiscussionPlugin::Proposal if parent.kind_of?(ProposalsDiscussionPlugin::Discussion) | ||
22 | + types | ||
23 | + else | ||
24 | + [ProposalsDiscussionPlugin::Discussion, ProposalsDiscussionPlugin::Proposal] | ||
25 | + end | ||
26 | + end | ||
27 | + | ||
28 | + def content_remove_new(page) | ||
29 | + page.kind_of?(ProposalsDiscussionPlugin::Discussion) || page.kind_of?(ProposalsDiscussionPlugin::Proposal) | ||
30 | + end | ||
31 | + | ||
32 | + def content_remove_upload(page) | ||
33 | + page.kind_of?(ProposalsDiscussionPlugin::Discussion) || page.kind_of?(ProposalsDiscussionPlugin::Proposal) | ||
34 | + end | ||
35 | + | ||
36 | +end |
plugins/proposals_discussion/lib/proposals_discussion_plugin/discussion.rb
0 → 100644
@@ -0,0 +1,18 @@ | @@ -0,0 +1,18 @@ | ||
1 | +class ProposalsDiscussionPlugin::Discussion < Folder | ||
2 | + | ||
3 | + def self.short_description | ||
4 | + _("Discussion") | ||
5 | + end | ||
6 | + | ||
7 | + def self.description | ||
8 | + _('Container for proposals.') | ||
9 | + end | ||
10 | + | ||
11 | + def to_html(options = {}) | ||
12 | + discussion = self | ||
13 | + proc do | ||
14 | + render :file => 'content_viewer/discussion', :locals => {:discussion => discussion} | ||
15 | + end | ||
16 | + end | ||
17 | + | ||
18 | +end |
plugins/proposals_discussion/lib/proposals_discussion_plugin/proposal.rb
0 → 100644
1.66 KB
@@ -0,0 +1,80 @@ | @@ -0,0 +1,80 @@ | ||
1 | +.proposal { | ||
2 | + background: rgb(236, 236, 236); | ||
3 | + width: 31%; | ||
4 | + min-width: 272px; | ||
5 | + display: inline-block; | ||
6 | + vertical-align: top; | ||
7 | + margin: 5px 13px 5px 0; | ||
8 | + box-shadow: 5px 5px 5px -2px #ddd; | ||
9 | +} | ||
10 | + | ||
11 | +.proposal:hover { | ||
12 | + background: rgb(223, 223, 223); | ||
13 | +} | ||
14 | + | ||
15 | +.proposal .title { | ||
16 | + background: rgba(0, 0, 0, 0.1); | ||
17 | + font-weight: bold; | ||
18 | + font-size: 15px; | ||
19 | +} | ||
20 | + | ||
21 | +#article .proposal a:visited, #article .proposal a { | ||
22 | + color: rgb(94, 94, 94); | ||
23 | + text-decoration: none; | ||
24 | + width: 100%; | ||
25 | + display: inline-block; | ||
26 | +} | ||
27 | + | ||
28 | +#article .proposal .title { | ||
29 | + padding: 0px 5px; | ||
30 | +} | ||
31 | + | ||
32 | +#article .proposal .title a { | ||
33 | + padding: 8px 0px; | ||
34 | +} | ||
35 | + | ||
36 | +.proposal .content { | ||
37 | + padding: 5px; | ||
38 | + color: rgb(83, 83, 83); | ||
39 | +} | ||
40 | + | ||
41 | +.proposal .abstract { | ||
42 | + padding-top: 8px; | ||
43 | +} | ||
44 | + | ||
45 | +.proposal .info { | ||
46 | + float: left; | ||
47 | +} | ||
48 | + | ||
49 | +.proposal .info .comments { | ||
50 | + background: url('/plugins/proposals_discussion/images/comments.gif') no-repeat left/15px; | ||
51 | + padding-left: 18px; | ||
52 | + display: inline; | ||
53 | + font-size: 10px; | ||
54 | + color: rgb(82, 82, 82); | ||
55 | + opacity: 0.6; | ||
56 | +} | ||
57 | + | ||
58 | +.proposal .actions { | ||
59 | + float: right; | ||
60 | +} | ||
61 | + | ||
62 | +.proposal .actions .vote-actions { | ||
63 | + position: static; | ||
64 | +} | ||
65 | + | ||
66 | +.proposal .actions .vote-actions .vote-action a { | ||
67 | + opacity: 0.6; | ||
68 | +} | ||
69 | + | ||
70 | +form .proposals-discussion-plugin textarea { | ||
71 | + width: 98%; | ||
72 | +} | ||
73 | + | ||
74 | +form .proposals-discussion-plugin .abstract textarea { | ||
75 | + height: 60px; | ||
76 | +} | ||
77 | + | ||
78 | +form .proposals-discussion-plugin .body textarea { | ||
79 | + height: 400px; | ||
80 | +} |
@@ -0,0 +1 @@ | @@ -0,0 +1 @@ | ||
1 | +require File.dirname(__FILE__) + '/../../../test/test_helper' |
@@ -0,0 +1,22 @@ | @@ -0,0 +1,22 @@ | ||
1 | +require File.dirname(__FILE__) + '/../test_helper' | ||
2 | + | ||
3 | +class ProposalsDiscussionPluginTest < ActiveSupport::TestCase | ||
4 | + | ||
5 | + def setup | ||
6 | + @profile = fast_create(Community) | ||
7 | + @proposal = ProposalsDiscussionPlugin::Proposal.new(:name => 'test', :profile => @profile) | ||
8 | + end | ||
9 | + | ||
10 | + attr_reader :profile, :proposal | ||
11 | + | ||
12 | + should 'save a proposal' do | ||
13 | + proposal.abstract = 'abstract' | ||
14 | + assert proposal.save | ||
15 | + end | ||
16 | + | ||
17 | + should 'do not save a proposal without abstract' do | ||
18 | + proposal.save | ||
19 | + assert proposal.errors['abstract'].present? | ||
20 | + end | ||
21 | + | ||
22 | +end |
plugins/proposals_discussion/test/unit/proposals_discussion_plugin_test.rb
0 → 100644
@@ -0,0 +1,70 @@ | @@ -0,0 +1,70 @@ | ||
1 | +require File.dirname(__FILE__) + '/../test_helper' | ||
2 | + | ||
3 | +class ProposalsDiscussionPluginTest < ActiveSupport::TestCase | ||
4 | + | ||
5 | + def setup | ||
6 | + @plugin = ProposalsDiscussionPlugin.new | ||
7 | + @profile = fast_create(Community) | ||
8 | + @params = {} | ||
9 | + @plugin.stubs(:context).returns(self) | ||
10 | + end | ||
11 | + | ||
12 | + attr_reader :plugin, :profile, :params | ||
13 | + | ||
14 | + should 'has stylesheet' do | ||
15 | + assert @plugin.stylesheet? | ||
16 | + end | ||
17 | + | ||
18 | + should 'return Discussion as a content type' do | ||
19 | + @params[:parent_id] = nil | ||
20 | + assert_includes plugin.content_types, ProposalsDiscussionPlugin::Discussion | ||
21 | + end | ||
22 | + | ||
23 | + should 'do not return Discussion as a content type if it has a parent' do | ||
24 | + parent = fast_create(Folder, :profile_id => @profile.id) | ||
25 | + @params[:parent_id] = parent.id | ||
26 | + assert_not_includes plugin.content_types, ProposalsDiscussionPlugin::Discussion | ||
27 | + end | ||
28 | + | ||
29 | + should 'return Proposal as a content type if parent is a Discussion' do | ||
30 | + parent = fast_create(ProposalsDiscussionPlugin::Discussion, :profile_id => @profile.id) | ||
31 | + @params[:parent_id] = parent.id | ||
32 | + assert_includes plugin.content_types, ProposalsDiscussionPlugin::Proposal | ||
33 | + end | ||
34 | + | ||
35 | + should 'do not return Proposal as a content type if parent is nil' do | ||
36 | + @params[:parent_id] = nil | ||
37 | + assert_not_includes plugin.content_types, ProposalsDiscussionPlugin::Proposal | ||
38 | + end | ||
39 | + | ||
40 | + should 'remove new button from content page for a discussion' do | ||
41 | + page = fast_create(ProposalsDiscussionPlugin::Discussion, :profile_id => @profile.id) | ||
42 | + assert plugin.content_remove_new(page) | ||
43 | + end | ||
44 | + | ||
45 | + should 'remove upload button from content page for a discussion' do | ||
46 | + page = fast_create(ProposalsDiscussionPlugin::Discussion, :profile_id => @profile.id) | ||
47 | + assert plugin.content_remove_upload(page) | ||
48 | + end | ||
49 | + | ||
50 | + should 'remove new button from content page for a proposal' do | ||
51 | + page = fast_create(ProposalsDiscussionPlugin::Proposal, :profile_id => @profile.id) | ||
52 | + assert plugin.content_remove_new(page) | ||
53 | + end | ||
54 | + | ||
55 | + should 'remove upload button from content page for a proposal' do | ||
56 | + page = fast_create(ProposalsDiscussionPlugin::Proposal, :profile_id => @profile.id) | ||
57 | + assert plugin.content_remove_upload(page) | ||
58 | + end | ||
59 | + | ||
60 | + should 'do not remove new button from content page for others article types' do | ||
61 | + page = fast_create(Article, :profile_id => @profile.id) | ||
62 | + assert !plugin.content_remove_new(page) | ||
63 | + end | ||
64 | + | ||
65 | + should 'do not remove upload button from content page for others article types' do | ||
66 | + page = fast_create(Article, :profile_id => @profile.id) | ||
67 | + assert !plugin.content_remove_upload(page) | ||
68 | + end | ||
69 | + | ||
70 | +end |
plugins/proposals_discussion/views/cms/proposals_discussion_plugin/_proposal.html.erb
0 → 100644
@@ -0,0 +1,28 @@ | @@ -0,0 +1,28 @@ | ||
1 | +<%= required_fields_message %> | ||
2 | + | ||
3 | +<%= render :file => 'shared/tiny_mce' %> | ||
4 | + | ||
5 | +<% title_limit = 70 %> | ||
6 | +<% abstract_limit = 140 %> | ||
7 | + | ||
8 | +<div class="proposals-discussion-plugin"> | ||
9 | + <div class="title"> | ||
10 | + <%= required labelled_form_field _('Title'), limited_text_area(:article, :name, title_limit, 'title_textarea', :rows => 1) %> | ||
11 | + </div> | ||
12 | + | ||
13 | + <div class="abstract"> | ||
14 | + <%= required labelled_form_field _('Abstract'), limited_text_area(:article, :abstract, abstract_limit, 'abstract_textarea') %> | ||
15 | + </div> | ||
16 | + | ||
17 | + <div class="body"> | ||
18 | + <% editor_type = 'mceEditor' %> | ||
19 | + <%= labelled_form_field(_('Text'), text_area(:article, :body, :class => editor_type)) %> | ||
20 | + </div> | ||
21 | +</div> | ||
22 | + | ||
23 | +<script> | ||
24 | +jQuery( document ).ready(function( $ ) { | ||
25 | + limited_text_area('title_textarea', <%= title_limit %>); | ||
26 | + limited_text_area('abstract_textarea', <%= abstract_limit %>); | ||
27 | +}); | ||
28 | +</script> |
plugins/proposals_discussion/views/content_viewer/_proposal_card.html.erb
0 → 100644
@@ -0,0 +1,16 @@ | @@ -0,0 +1,16 @@ | ||
1 | +<div class="proposal"> | ||
2 | + <div class="title"> | ||
3 | + <%= link_to proposal_card.name, proposal_card.view_url %> | ||
4 | + </div> | ||
5 | + <div class="content"> | ||
6 | + <div class="info"> | ||
7 | + <div class="comments"><%= proposal_card.comments_count %></div> | ||
8 | + </div> | ||
9 | + <div class="actions"> | ||
10 | + <%= @plugins.dispatch(:article_header_extra_contents, proposal_card).collect { |content| instance_exec(&content) }.join("") %> | ||
11 | + </div> | ||
12 | + <div class="abstract"> | ||
13 | + <%= link_to strip_tags(proposal_card.lead), proposal_card.view_url %> | ||
14 | + </div> | ||
15 | + </div> | ||
16 | +</div> |
plugins/proposals_discussion/views/content_viewer/discussion.html.erb
0 → 100644
@@ -0,0 +1,12 @@ | @@ -0,0 +1,12 @@ | ||
1 | +<div class="description"> | ||
2 | + <%= @page.body %> | ||
3 | +</div> | ||
4 | + | ||
5 | +<%= link_to url_for({:controller => 'cms', :action => 'new', :type => "ProposalsDiscussionPlugin::Proposal", :parent_id => @page.id}), :class => 'button with-text icon-add' do %> | ||
6 | + <strong><%= _("New Proposal") %></strong> | ||
7 | +<% end %> | ||
8 | + | ||
9 | +<div class="proposals"> | ||
10 | + <%= render :partial => 'content_viewer/proposal_card', :collection => discussion.children %> | ||
11 | + <div class="clear"></div> | ||
12 | +</div> |