Commit 17b51105dce70f1854f884ec698efdd0b1bd9892

Authored by Victor Costa
1 parent 3f489bc4

proposals_discussion: a plugin to promote a debate over ideas proposed by users

plugins/proposals_discussion/lib/proposals_discussion_plugin.rb 0 → 100644
... ... @@ -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 @@
  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
... ... @@ -0,0 +1,13 @@
  1 +class ProposalsDiscussionPlugin::Proposal < TinyMceArticle
  2 +
  3 + def self.short_description
  4 + _("Proposal")
  5 + end
  6 +
  7 + def self.description
  8 + _('Proposal')
  9 + end
  10 +
  11 + validates_presence_of :abstract
  12 +
  13 +end
... ...
plugins/proposals_discussion/public/images/comments.gif 0 → 100644

1.66 KB

plugins/proposals_discussion/public/style.css 0 → 100644
... ... @@ -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 +}
... ...
plugins/proposals_discussion/test/test_helper.rb 0 → 100644
... ... @@ -0,0 +1 @@
  1 +require File.dirname(__FILE__) + '/../../../test/test_helper'
... ...
plugins/proposals_discussion/test/unit/proposal_test.rb 0 → 100644
... ... @@ -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 @@
  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 @@
  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 @@
  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 @@
  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>
... ...