public inbox for gentoo-commits@lists.gentoo.org
 help / color / mirror / Atom feed
* [gentoo-commits] proj/council-webapp:master commit in: site/app/views/taglibs/, site/db/, site/features/support/, ...
@ 2011-05-24 16:58 Petteri Räty
  0 siblings, 0 replies; only message in thread
From: Petteri Räty @ 2011-05-24 16:58 UTC (permalink / raw
  To: gentoo-commits

commit:     83a9df9a9daf85bd6b13bfc8fdedec8f8780ce13
Author:     Joachim Filip Ignacy Bartosik <jbartosik <AT> gmail <DOT> com>
AuthorDate: Fri May 13 16:53:18 2011 +0000
Commit:     Petteri Räty <betelgeuse <AT> gentoo <DOT> org>
CommitDate: Tue May 24 16:55:39 2011 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/council-webapp.git;a=commit;h=83a9df9a

Agenda items

---
 site/app/controllers/agenda_items_controller.rb    |   12 +++
 site/app/models/agenda.rb                          |    6 +
 site/app/models/agenda_item.rb                     |   53 ++++++++++
 site/app/viewhints/agenda_hints.rb                 |    5 +
 site/app/views/agenda_items/show.dryml             |   14 +++
 site/app/views/agendas/show.dryml                  |    8 ++
 site/app/views/taglibs/application.dryml           |    2 +
 site/app/views/taglibs/main_nav.dryml              |    7 ++
 site/config/hobo_routes.rb                         |    9 ++
 site/db/schema.rb                                  |   16 +++-
 site/features/agenda_items.feature                 |   39 ++++++++
 .../features/step_definitions/agenda_item_steps.rb |   24 +++++
 site/features/step_definitions/within_steps.rb     |    1 +
 site/features/support/paths.rb                     |    4 +
 site/spec/factories.rb                             |    2 +
 site/spec/models/agenda_item_spec.rb               |  103 ++++++++++++++++++++
 16 files changed, 304 insertions(+), 1 deletions(-)

diff --git a/site/app/controllers/agenda_items_controller.rb b/site/app/controllers/agenda_items_controller.rb
new file mode 100644
index 0000000..4d28112
--- /dev/null
+++ b/site/app/controllers/agenda_items_controller.rb
@@ -0,0 +1,12 @@
+class AgendaItemsController < ApplicationController
+
+  hobo_model_controller
+
+  auto_actions :all, :except => :index
+  before_filter :login, :except => :show
+
+  protected
+    def login
+      redirect_to user_login_path unless current_user.signed_up?
+    end
+end

diff --git a/site/app/models/agenda.rb b/site/app/models/agenda.rb
index def1643..5998ae8 100644
--- a/site/app/models/agenda.rb
+++ b/site/app/models/agenda.rb
@@ -7,6 +7,8 @@ class Agenda < ActiveRecord::Base
     timestamps
   end
 
+  has_many :agenda_items
+
   lifecycle do
     state :open, :default => true
     state :submissions_closed, :meeting_ongoing, :old
@@ -67,6 +69,10 @@ class Agenda < ActiveRecord::Base
     end
   end
 
+  def current?
+    ['open', 'submissions_closed'].include?(state.to_s)
+  end
+
   protected
     def there_is_only_one_non_archival_agenda
       return if(state.to_s == 'old')

diff --git a/site/app/models/agenda_item.rb b/site/app/models/agenda_item.rb
new file mode 100644
index 0000000..1bb3a36
--- /dev/null
+++ b/site/app/models/agenda_item.rb
@@ -0,0 +1,53 @@
+class AgendaItem < ActiveRecord::Base
+
+  hobo_model # Don't put anything above this
+
+  fields do
+    title      :string
+    discussion :string
+    body       :text
+    rejected   :boolean, :default => false
+    timestamps
+  end
+
+  belongs_to :user, :creator => true
+  belongs_to :agenda
+
+  # --- Permissions --- #
+  def create_permitted?
+    return false if acting_user.guest?
+    return false if user != acting_user
+    true
+  end
+
+  def update_permitted?
+    return false if agenda._?.state == 'archived'
+    return false if user_changed?
+    return true if acting_user.council_member?
+    return true if acting_user.administrator?
+    return false unless agenda.nil?
+    return true if acting_user == user
+    false
+  end
+
+  def destroy_permitted?
+    acting_user.administrator?
+  end
+
+  def view_permitted?(field)
+    true
+  end
+
+  # Not deduced properly
+  def edit_permitted?(field)
+    return false if field == :rejected && !agenda.nil?
+    return false if field == :agenda && rejected?
+    return false if agenda._?.state == 'archived'
+    return false if field == :user
+    return true if acting_user.administrator?
+    return true if acting_user.council_member?
+    return false unless agenda.nil?
+    return acting_user == user if [nil, :title, :discussion, :body].include?(field)
+  end
+
+end

diff --git a/site/app/viewhints/agenda_hints.rb b/site/app/viewhints/agenda_hints.rb
new file mode 100644
index 0000000..05c7b96
--- /dev/null
+++ b/site/app/viewhints/agenda_hints.rb
@@ -0,0 +1,5 @@
+class AgendaHints < Hobo::ViewHints
+
+  children :agenda_items
+
+end

diff --git a/site/app/views/agenda_items/show.dryml b/site/app/views/agenda_items/show.dryml
new file mode 100644
index 0000000..626298d
--- /dev/null
+++ b/site/app/views/agenda_items/show.dryml
@@ -0,0 +1,14 @@
+<show-page>
+  <append-content:>
+    <form if="&this.editable_by?(current_user, :agenda)">
+      <input value="&Agenda.current.id" type="hidden" name="agenda_item[agenda_id]"/>
+      <submit label="Add to current agenda"/>
+    </form>
+
+    <form if="&this.editable_by?(current_user, :rejected)">
+      <input value="&!this.rejected?" type="hidden" name="agenda_item[rejected]"/>
+      <submit label="Reject" unless="&this.rejected"/>
+      <submit label="Un-reject" if="&this.rejected"/>
+    </form>
+  </append-content:>
+</show-page>

diff --git a/site/app/views/agendas/show.dryml b/site/app/views/agendas/show.dryml
index 7df2b72..113edb4 100644
--- a/site/app/views/agendas/show.dryml
+++ b/site/app/views/agendas/show.dryml
@@ -1,4 +1,12 @@
 <show-page>
+  <append-collection-section: if="&this.current?">
+    <h3 class="collection-heading">
+      Suggested items:
+    </h3>
+    <with with="&AgendaItem.all(:conditions => { :agenda_id => nil })">
+      <collection unless="&this.nil?" />
+    </with>
+  </append-collection-section:>
   <append-content-body:>
     <div class="transition" if="&Agenda.transitions_available(current_user)">
       <collection:possible_transitions>

diff --git a/site/app/views/taglibs/application.dryml b/site/app/views/taglibs/application.dryml
index 2f08a8e..017831f 100644
--- a/site/app/views/taglibs/application.dryml
+++ b/site/app/views/taglibs/application.dryml
@@ -6,4 +6,6 @@
 <include src="taglibs/auto/rapid/pages"/>
 <include src="taglibs/auto/rapid/forms"/>
 
+<include src="taglibs/main_nav"/>
+
 <set-theme name="clean"/>

diff --git a/site/app/views/taglibs/main_nav.dryml b/site/app/views/taglibs/main_nav.dryml
new file mode 100644
index 0000000..af60c6d
--- /dev/null
+++ b/site/app/views/taglibs/main_nav.dryml
@@ -0,0 +1,7 @@
+<def tag="main-nav">
+  <navigation class="main-nav" merge-attrs param="default">
+    <nav-item href="#{base_url}/">Home</nav-item>
+    <nav-item with="&Agenda"><ht key="agenda.nav_item" count="100"><model-name-human count="100"/></ht></nav-item>
+    <nav-item href="&new_agenda_item_path">Suggest agenda item</nav-item>
+  </navigation>
+</def>

diff --git a/site/config/hobo_routes.rb b/site/config/hobo_routes.rb
index 33b292b..11fb9b0 100644
--- a/site/config/hobo_routes.rb
+++ b/site/config/hobo_routes.rb
@@ -44,4 +44,13 @@ Council::Application.routes.draw do
   put 'agendas/:id(.:format)' => 'agendas#update', :as => 'update_agenda', :constraints => { :id => %r([^/.?]+) }
   delete 'agendas/:id(.:format)' => 'agendas#destroy', :as => 'destroy_agenda', :constraints => { :id => %r([^/.?]+) }
 
+
+  # Resource routes for controller "agenda_items"
+  get 'agenda_items/new(.:format)', :as => 'new_agenda_item'
+  get 'agenda_items/:id/edit(.:format)' => 'agenda_items#edit', :as => 'edit_agenda_item'
+  get 'agenda_items/:id(.:format)' => 'agenda_items#show', :as => 'agenda_item', :constraints => { :id => %r([^/.?]+) }
+  post 'agenda_items(.:format)' => 'agenda_items#create', :as => 'create_agenda_item'
+  put 'agenda_items/:id(.:format)' => 'agenda_items#update', :as => 'update_agenda_item', :constraints => { :id => %r([^/.?]+) }
+  delete 'agenda_items/:id(.:format)' => 'agenda_items#destroy', :as => 'destroy_agenda_item', :constraints => { :id => %r([^/.?]+) }
+
 end

diff --git a/site/db/schema.rb b/site/db/schema.rb
index b308e67..edd7ee0 100644
--- a/site/db/schema.rb
+++ b/site/db/schema.rb
@@ -10,7 +10,21 @@
 #
 # It's strongly recommended to check this file into your version control system.
 
-ActiveRecord::Schema.define(:version => 20110523175740) do
+ActiveRecord::Schema.define(:version => 20110523180314) do
+
+  create_table "agenda_items", :force => true do |t|
+    t.string   "title"
+    t.string   "discussion"
+    t.text     "body"
+    t.boolean  "rejected",   :default => false
+    t.datetime "created_at"
+    t.datetime "updated_at"
+    t.integer  "user_id"
+    t.integer  "agenda_id"
+  end
+
+  add_index "agenda_items", ["agenda_id"], :name => "index_agenda_items_on_agenda_id"
+  add_index "agenda_items", ["user_id"], :name => "index_agenda_items_on_user_id"
 
   create_table "agendas", :force => true do |t|
     t.datetime "meeting_time"

diff --git a/site/features/agenda_items.feature b/site/features/agenda_items.feature
new file mode 100644
index 0000000..e9b417c
--- /dev/null
+++ b/site/features/agenda_items.feature
@@ -0,0 +1,39 @@
+Feature: Suggest Agenda Items
+  As a user
+  I want to be able to suggest agenda items
+  so Council will consider my ideas
+
+  Scenario: Suggest Agenda item
+    Given I am logged in as example user
+    And an agenda
+		When I am on the home page
+		And I follow "Suggest agenda item"
+		And I fill in example agenda item data
+		And I press "Create Agenda item"
+		Then I should see "The Agenda item was created successfully" in the notices
+
+  Scenario: Approve Agenda items
+    Given example agenda item
+    And an agenda
+    And I am logged in as a council member
+    When I am on the current agenda page
+    And I follow first suggested agenda link
+    And I press "Add to current agenda"
+    And I should see current agenda as the agenda
+
+  Scenario: Reject Agenda item
+    Given example agenda item
+    And an agenda
+    And I am logged in as a council member
+    When I am on the first suggested agenda page
+    And I press "Reject"
+    Then I should see "Rejected"
+
+    When I press "Un-reject"
+    Then I should not see "Rejected"
+
+  Scenario: Don't list rejected agenda items
+    Given rejected agenda item
+    And an agenda
+    When I am on the current agenda page
+    Then I should not see "rejected"

diff --git a/site/features/step_definitions/agenda_item_steps.rb b/site/features/step_definitions/agenda_item_steps.rb
new file mode 100644
index 0000000..d68ee91
--- /dev/null
+++ b/site/features/step_definitions/agenda_item_steps.rb
@@ -0,0 +1,24 @@
+When /^I fill in example agenda item data$/ do
+  When "I fill in the following:", table(%{
+    |agenda_item_title|examle|
+    |agenda_item_discussion|http://example.com/mailinglist/example|
+    |agenda_item_body|example|
+  })
+end
+
+Given /^example agenda item$/ do
+  AgendaItem.new(:title => 'example', :discussion => '', :body => 'example').save!
+end
+
+Given /^rejected agenda item$/ do
+  AgendaItem.new(:title => 'Rejected', :discussion => '', :body => 'example', :rejected => true).save!
+end
+
+When /^I follow first suggested agenda link$/ do
+  firstItem = AgendaItem.first :conditions => {:agenda_id => nil, :rejected => false}
+  When "I follow \"#{firstItem.title}\""
+end
+
+When /^I should see current agenda as the agenda$/ do
+  When "I should see \"Agenda #{Agenda.current.id}\" within \".agenda-item-agenda\""
+end

diff --git a/site/features/step_definitions/within_steps.rb b/site/features/step_definitions/within_steps.rb
index 80bb8f0..7d56fc4 100644
--- a/site/features/step_definitions/within_steps.rb
+++ b/site/features/step_definitions/within_steps.rb
@@ -5,6 +5,7 @@
   'in the notices' => '.flash.notice',
   'in the errors' => '.error-messages',
   'in the content body' => '.content-body',
+  'in the agenda items' => '.agenda-items',
   'in the agendas collection' => '.collection.agendas',
   'as empty collection message' => '.empty-collection-message',
   'as meeting time' => '.meeting-time-view',

diff --git a/site/features/support/paths.rb b/site/features/support/paths.rb
index 515a7ec..ab24b9e 100644
--- a/site/features/support/paths.rb
+++ b/site/features/support/paths.rb
@@ -19,6 +19,10 @@ module NavigationHelpers
 
     when /the current agenda page/
       agenda_path(Agenda.current)
+
+    when /the first suggested agenda page/
+      agenda_item_path(AgendaItem.first(:conditions => {:agenda_id => nil}))
+
     # Add more mappings here.
     # Here is an example that pulls values out of the Regexp:
     #

diff --git a/site/spec/factories.rb b/site/spec/factories.rb
index b41c25c..3211032 100644
--- a/site/spec/factories.rb
+++ b/site/spec/factories.rb
@@ -9,3 +9,5 @@ Factory.define :user, :class => User do |u|
 end
 
 Factory.define :agenda do |a|; end
+
+Factory.define :agenda_item do |a|; end

diff --git a/site/spec/models/agenda_item_spec.rb b/site/spec/models/agenda_item_spec.rb
new file mode 100644
index 0000000..95d7659
--- /dev/null
+++ b/site/spec/models/agenda_item_spec.rb
@@ -0,0 +1,103 @@
+require 'spec_helper'
+
+describe AgendaItem do
+  it 'should allow all registered users to create' do
+    a = AgendaItem.new
+    for u in users_factory(:user, :council, :admin, :council_admin)
+      a.user = u
+      a.should be_creatable_by(u)
+    end
+  end
+
+    it 'should allow only administrators to destroy' do
+    a = Factory(:agenda_item)
+    for u in users_factory(:guest, :user, :council)
+      a.should_not be_destroyable_by(u)
+    end
+    for u in users_factory(:admin, :council_admin)
+      a.user = u
+      a.should be_destroyable_by(u)
+    end
+  end
+
+  it 'should allow owner, council members and administrators to edit and update unassigned items' do
+    owner = Factory(:user)
+    a = Factory(:agenda_item, :user => owner)
+    for u in users_factory(:guest, :user)
+      a.should_not be_editable_by(u)
+      a.should_not be_updatable_by(u)
+    end
+    for u in users_factory(:council, :admin, :council_admin) + [owner]
+      a.should be_editable_by(u)
+      a.should be_updatable_by(u)
+    end
+  end
+
+  it 'should allow only council members and administrators to edit and update assigned items' do
+    owner = Factory(:user)
+    agenda = Agenda.last || Factory(:agenda)
+    a = Factory(:agenda_item, :user => owner, :agenda => agenda)
+    for u in users_factory(:guest, :user) + [owner]
+      a.should_not be_editable_by(u)
+      a.should_not be_updatable_by(u)
+    end
+    for u in users_factory(:council, :admin, :council_admin)
+      a.should be_editable_by(u)
+      a.should be_updatable_by(u)
+    end
+  end
+
+  it 'should allow no one edit and update items assigned to archived agenda' do
+    owner = Factory(:user)
+    agenda = Factory(:agenda, :state => 'archived')
+    a = Factory(:agenda_item, :user => owner, :agenda => agenda)
+    for u in users_factory(AllRoles) + [owner]
+      a.should_not be_editable_by(u)
+      a.should_not be_updatable_by(u)
+    end
+  end
+
+  it 'should allow owner, council memebers and administrators to edit some fields' do
+    owner = Factory(:user)
+    a = Factory(:agenda_item, :user => owner)
+    for u in users_factory(:council, :admin, :council_admin) + [owner]
+      a.should be_editable_by(u, :title)
+      a.should be_editable_by(u, :discussion)
+      a.should be_editable_by(u, :body)
+    end
+  end
+
+  it 'should allow only council memebers and administrators to edit some fields' do
+    owner = Factory(:user)
+    a = Factory(:agenda_item, :user => owner)
+    for u in users_factory(:council, :admin, :council_admin)
+      a.should be_editable_by(u, :agenda)
+      a.should be_editable_by(u, :rejected)
+    end
+    a.should_not be_editable_by(owner, :agenda)
+    a.should_not be_editable_by(owner, :rejected)
+  end
+
+  it 'should allow no one to edit some fields' do
+    owner = Factory(:user)
+    a = Factory(:agenda_item, :user => owner)
+    for u in users_factory(:guest, :user, :council, :admin, :council_admin) + [owner]
+      a.should_not be_editable_by(u, :user)
+    end
+  end
+
+  it 'should not allow to edit agenda if rejected' do
+    agenda = Agenda.last || Factory(:agenda)
+    a = Factory(:agenda_item, :agenda => agenda)
+    for u in users_factory(:guest, :user, :council, :admin, :council_admin)
+      a.should_not be_editable_by(u, :rejected)
+    end
+  end
+
+  it 'should not allow to reject if assigned to agenda' do
+    a = Factory(:agenda_item, :rejected => true)
+    for u in users_factory(:guest, :user, :council, :admin, :council_admin)
+      a.should_not be_editable_by(u, :agenda)
+    end
+  end
+end



^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2011-05-24 16:58 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-05-24 16:58 [gentoo-commits] proj/council-webapp:master commit in: site/app/views/taglibs/, site/db/, site/features/support/, Petteri Räty

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox