From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from pigeon.gentoo.org ([208.92.234.80] helo=lists.gentoo.org) by finch.gentoo.org with esmtp (Exim 4.60) (envelope-from ) id 1QOuw1-0003Pz-Fd for garchives@archives.gentoo.org; Tue, 24 May 2011 16:58:21 +0000 Received: from pigeon.gentoo.org (localhost [127.0.0.1]) by pigeon.gentoo.org (Postfix) with SMTP id E0C9E1C586; Tue, 24 May 2011 16:58:03 +0000 (UTC) Received: from smtp.gentoo.org (smtp.gentoo.org [140.211.166.183]) by pigeon.gentoo.org (Postfix) with ESMTP id 90D441C4E1 for ; Tue, 24 May 2011 16:58:03 +0000 (UTC) Received: from pelican.gentoo.org (unknown [66.219.59.40]) (using TLSv1 with cipher ADH-CAMELLIA256-SHA (256/256 bits)) (No client certificate requested) by smtp.gentoo.org (Postfix) with ESMTPS id EAE841B4036 for ; Tue, 24 May 2011 16:58:02 +0000 (UTC) Received: from localhost.localdomain (localhost [127.0.0.1]) by pelican.gentoo.org (Postfix) with ESMTP id 2F7C980510 for ; Tue, 24 May 2011 16:58:02 +0000 (UTC) From: "Petteri Räty" To: gentoo-commits@lists.gentoo.org Content-type: text/plain; charset=UTF-8 Reply-To: gentoo-dev@lists.gentoo.org, "Petteri Räty" Message-ID: <83a9df9a9daf85bd6b13bfc8fdedec8f8780ce13.betelgeuse@gentoo> Subject: [gentoo-commits] proj/council-webapp:master commit in: site/app/views/taglibs/, site/db/, site/features/support/, ... X-VCS-Repository: proj/council-webapp X-VCS-Files: site/app/controllers/agenda_items_controller.rb site/app/models/agenda.rb site/app/models/agenda_item.rb site/app/viewhints/agenda_hints.rb site/app/views/agenda_items/show.dryml site/app/views/agendas/show.dryml site/app/views/taglibs/application.dryml site/app/views/taglibs/main_nav.dryml site/config/hobo_routes.rb site/db/schema.rb site/features/agenda_items.feature site/features/step_definitions/agenda_item_steps.rb site/features/step_definitions/within_steps.rb site/features/support/paths.rb site/spec/factories.rb site/spec/models/agenda_item_spec.rb X-VCS-Directories: site/app/views/taglibs/ site/db/ site/features/support/ site/app/views/agenda_items/ site/features/ site/config/ site/app/models/ site/app/controllers/ site/spec/models/ site/spec/ site/features/step_definitions/ site/app/views/agendas/ site/app/viewhints/ X-VCS-Committer: betelgeuse X-VCS-Committer-Name: Petteri Räty X-VCS-Revision: 83a9df9a9daf85bd6b13bfc8fdedec8f8780ce13 Date: Tue, 24 May 2011 16:58:02 +0000 (UTC) Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-Id: Gentoo Linux mail X-BeenThere: gentoo-commits@lists.gentoo.org Content-Transfer-Encoding: quoted-printable X-Archives-Salt: X-Archives-Hash: 528cf28f8fa6117b6fa225fc712b0a49 commit: 83a9df9a9daf85bd6b13bfc8fdedec8f8780ce13 Author: Joachim Filip Ignacy Bartosik gmail com= > AuthorDate: Fri May 13 16:53:18 2011 +0000 Commit: Petteri R=C3=A4ty gentoo org> CommitDate: Tue May 24 16:55:39 2011 +0000 URL: http://git.overlays.gentoo.org/gitweb/?p=3Dproj/council-webap= p.git;a=3Dcommit;h=3D83a9df9a 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/c= ontrollers/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 =3D> :index + before_filter :login, :except =3D> :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 =20 + has_many :agenda_items + lifecycle do state :open, :default =3D> true state :submissions_closed, :meeting_ongoing, :old @@ -67,6 +69,10 @@ class Agenda < ActiveRecord::Base end end =20 + def current? + ['open', 'submissions_closed'].include?(state.to_s) + end + protected def there_is_only_one_non_archival_agenda return if(state.to_s =3D=3D '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 =3D> false + timestamps + end + + belongs_to :user, :creator =3D> true + belongs_to :agenda + + # --- Permissions --- # + def create_permitted? + return false if acting_user.guest? + return false if user !=3D acting_user + true + end + + def update_permitted? + return false if agenda._?.state =3D=3D '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 =3D=3D 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 =3D=3D :rejected && !agenda.nil? + return false if field =3D=3D :agenda && rejected? + return false if agenda._?.state =3D=3D 'archived' + return false if field =3D=3D :user + return true if acting_user.administrator? + return true if acting_user.council_member? + return false unless agenda.nil? + return acting_user =3D=3D user if [nil, :title, :discussion, :body].= include?(field) + end + +end diff --git a/site/app/viewhints/agenda_hints.rb b/site/app/viewhints/agen= da_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/agen= da_items/show.dryml new file mode 100644 index 0000000..626298d --- /dev/null +++ b/site/app/views/agenda_items/show.dryml @@ -0,0 +1,14 @@ + + +
+ + + + +
+ + + + +
+
diff --git a/site/app/views/agendas/show.dryml b/site/app/views/agendas/s= how.dryml index 7df2b72..113edb4 100644 --- a/site/app/views/agendas/show.dryml +++ b/site/app/views/agendas/show.dryml @@ -1,4 +1,12 @@ + +

+ Suggested items: +

+ { :agenda_id =3D> nil= })"> + + +
diff --git a/site/app/views/taglibs/application.dryml b/site/app/views/ta= glibs/application.dryml index 2f08a8e..017831f 100644 --- a/site/app/views/taglibs/application.dryml +++ b/site/app/views/taglibs/application.dryml @@ -6,4 +6,6 @@ =20 + + diff --git a/site/app/views/taglibs/main_nav.dryml b/site/app/views/tagli= bs/main_nav.dryml new file mode 100644 index 0000000..af60c6d --- /dev/null +++ b/site/app/views/taglibs/main_nav.dryml @@ -0,0 +1,7 @@ + + + Home + + Suggest agenda item + + 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)' =3D> 'agendas#update', :as =3D> 'update_ag= enda', :constraints =3D> { :id =3D> %r([^/.?]+) } delete 'agendas/:id(.:format)' =3D> 'agendas#destroy', :as =3D> 'destr= oy_agenda', :constraints =3D> { :id =3D> %r([^/.?]+) } =20 + + # Resource routes for controller "agenda_items" + get 'agenda_items/new(.:format)', :as =3D> 'new_agenda_item' + get 'agenda_items/:id/edit(.:format)' =3D> 'agenda_items#edit', :as =3D= > 'edit_agenda_item' + get 'agenda_items/:id(.:format)' =3D> 'agenda_items#show', :as =3D> 'a= genda_item', :constraints =3D> { :id =3D> %r([^/.?]+) } + post 'agenda_items(.:format)' =3D> 'agenda_items#create', :as =3D> 'cr= eate_agenda_item' + put 'agenda_items/:id(.:format)' =3D> 'agenda_items#update', :as =3D> = 'update_agenda_item', :constraints =3D> { :id =3D> %r([^/.?]+) } + delete 'agenda_items/:id(.:format)' =3D> 'agenda_items#destroy', :as =3D= > 'destroy_agenda_item', :constraints =3D> { :id =3D> %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. =20 -ActiveRecord::Schema.define(:version =3D> 20110523175740) do +ActiveRecord::Schema.define(:version =3D> 20110523180314) do + + create_table "agenda_items", :force =3D> true do |t| + t.string "title" + t.string "discussion" + t.text "body" + t.boolean "rejected", :default =3D> 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 =3D> "index_agenda_item= s_on_agenda_id" + add_index "agenda_items", ["user_id"], :name =3D> "index_agenda_items_= on_user_id" =20 create_table "agendas", :force =3D> true do |t| t.datetime "meeting_time" diff --git a/site/features/agenda_items.feature b/site/features/agenda_it= ems.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 no= tices + + 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/f= eatures/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 =3D> 'example', :discussion =3D> '', :body =3D> = 'example').save! +end + +Given /^rejected agenda item$/ do + AgendaItem.new(:title =3D> 'Rejected', :discussion =3D> '', :body =3D>= 'example', :rejected =3D> true).save! +end + +When /^I follow first suggested agenda link$/ do + firstItem =3D AgendaItem.first :conditions =3D> {:agenda_id =3D> nil, = :rejected =3D> 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-it= em-agenda\"" +end diff --git a/site/features/step_definitions/within_steps.rb b/site/featur= es/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' =3D> '.flash.notice', 'in the errors' =3D> '.error-messages', 'in the content body' =3D> '.content-body', + 'in the agenda items' =3D> '.agenda-items', 'in the agendas collection' =3D> '.collection.agendas', 'as empty collection message' =3D> '.empty-collection-message', 'as meeting time' =3D> '.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 =20 when /the current agenda page/ agenda_path(Agenda.current) + + when /the first suggested agenda page/ + agenda_item_path(AgendaItem.first(:conditions =3D> {:agenda_id =3D= > 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 =3D> User do |u| end =20 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/agen= da_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 =3D AgendaItem.new + for u in users_factory(:user, :council, :admin, :council_admin) + a.user =3D u + a.should be_creatable_by(u) + end + end + + it 'should allow only administrators to destroy' do + a =3D 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 =3D 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 =3D Factory(:user) + a =3D Factory(:agenda_item, :user =3D> 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 u= pdate assigned items' do + owner =3D Factory(:user) + agenda =3D Agenda.last || Factory(:agenda) + a =3D Factory(:agenda_item, :user =3D> owner, :agenda =3D> 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 age= nda' do + owner =3D Factory(:user) + agenda =3D Factory(:agenda, :state =3D> 'archived') + a =3D Factory(:agenda_item, :user =3D> owner, :agenda =3D> 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 so= me fields' do + owner =3D Factory(:user) + a =3D Factory(:agenda_item, :user =3D> 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 =3D Factory(:user) + a =3D Factory(:agenda_item, :user =3D> 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 =3D Factory(:user) + a =3D Factory(:agenda_item, :user =3D> owner) + for u in users_factory(:guest, :user, :council, :admin, :council_adm= in) + [owner] + a.should_not be_editable_by(u, :user) + end + end + + it 'should not allow to edit agenda if rejected' do + agenda =3D Agenda.last || Factory(:agenda) + a =3D Factory(:agenda_item, :agenda =3D> agenda) + for u in users_factory(:guest, :user, :council, :admin, :council_adm= in) + a.should_not be_editable_by(u, :rejected) + end + end + + it 'should not allow to reject if assigned to agenda' do + a =3D Factory(:agenda_item, :rejected =3D> true) + for u in users_factory(:guest, :user, :council, :admin, :council_adm= in) + a.should_not be_editable_by(u, :agenda) + end + end +end