Gentoo Archives: gentoo-commits

From: "Petteri Räty" <betelgeuse@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/council-webapp:master commit in: site/db/, site/features/, site/config/, site/app/controllers/, site/app/models/, ...
Date: Mon, 01 Aug 2011 14:39:01
Message-Id: 1a15725aad91a3b16928cb43f608379d6ade13e3.betelgeuse@gentoo
1 commit: 1a15725aad91a3b16928cb43f608379d6ade13e3
2 Author: Joachim Filip Ignacy Bartosik <jbartosik <AT> gmail <DOT> com>
3 AuthorDate: Thu Jul 21 16:42:07 2011 +0000
4 Commit: Petteri Räty <betelgeuse <AT> gentoo <DOT> org>
5 CommitDate: Tue Jul 26 10:09:47 2011 +0000
6 URL: http://git.overlays.gentoo.org/gitweb/?p=proj/council-webapp.git;a=commit;h=1a15725a
7
8 Council members can approve summaries
9
10 Regular users can view summary only after 4 council members approve it.
11 When someone changes summary all approvals for that summary are deleted.
12
13 ---
14 site/app/controllers/approvals_controller.rb | 7 ++++
15 site/app/models/agenda.rb | 12 ++++++-
16 site/app/models/approval.rb | 27 +++++++++++++++
17 site/app/views/agendas/show.dryml | 16 +++++++++
18 site/config/hobo_routes.rb | 8 ++++
19 site/db/schema.rb | 12 ++++++-
20 site/features/meeting_summary_approvals.feature | 28 +++++++++++++++
21 .../meeting_summary_approvals_steps.rb | 5 +++
22 site/features/step_definitions/within_steps.rb | 1 +
23 site/spec/factories.rb | 5 +++
24 site/spec/models/agenda_spec.rb | 22 ++++++++++++
25 site/spec/models/approval_spec.rb | 36 ++++++++++++++++++++
26 12 files changed, 177 insertions(+), 2 deletions(-)
27
28 diff --git a/site/app/controllers/approvals_controller.rb b/site/app/controllers/approvals_controller.rb
29 new file mode 100644
30 index 0000000..aeead3b
31 --- /dev/null
32 +++ b/site/app/controllers/approvals_controller.rb
33 @@ -0,0 +1,7 @@
34 +class ApprovalsController < ApplicationController
35 +
36 + hobo_model_controller
37 +
38 + auto_actions :all, :except => [:new, :index]
39 +
40 +end
41
42 diff --git a/site/app/models/agenda.rb b/site/app/models/agenda.rb
43 index bf38838..75a9a23 100644
44 --- a/site/app/models/agenda.rb
45 +++ b/site/app/models/agenda.rb
46 @@ -13,6 +13,7 @@ class Agenda < ActiveRecord::Base
47 has_many :agenda_items
48 has_many :participations
49 has_many :proxies
50 + has_many :approvals
51
52 lifecycle do
53 state :open, :default => true
54 @@ -45,7 +46,16 @@ class Agenda < ActiveRecord::Base
55 end
56
57 def view_permitted?(field)
58 - true
59 + return true unless field == :summary
60 + return true if approvals.count >= 4
61 + return true if acting_user.council_member?
62 + false
63 + end
64 +
65 + after_update do |agenda|
66 + if agenda.summary_changed?
67 + agenda.approvals.each { |approval| approval.destroy }
68 + end
69 end
70
71 before_create do |agenda|
72
73 diff --git a/site/app/models/approval.rb b/site/app/models/approval.rb
74 new file mode 100644
75 index 0000000..d36232c
76 --- /dev/null
77 +++ b/site/app/models/approval.rb
78 @@ -0,0 +1,27 @@
79 +require 'permissions/set.rb'
80 +
81 +class Approval < ActiveRecord::Base
82 +
83 + hobo_model # Don't put anything above this
84 +
85 + fields do
86 + timestamps
87 + end
88 +
89 + belongs_to :user, :null => false
90 + belongs_to :agenda, :null => false
91 +
92 + validates_presence_of :user_id
93 + validates_presence_of :agenda_id
94 + validates_uniqueness_of :user_id, :scope => :agenda_id
95 +
96 + def view_permitted?(field)
97 + true
98 + end
99 +
100 + multi_permission(:create, :destroy, :update) do
101 + return false unless user_is?(acting_user)
102 + return false unless acting_user.council_member?
103 + true
104 + end
105 +end
106
107 diff --git a/site/app/views/agendas/show.dryml b/site/app/views/agendas/show.dryml
108 index 40a413e..0471eb4 100644
109 --- a/site/app/views/agendas/show.dryml
110 +++ b/site/app/views/agendas/show.dryml
111 @@ -13,5 +13,21 @@
112 <a href="&send(this.second)"><view:first/></a>
113 </collection>
114 </div>
115 + <if test="&current_user.council_member? and not this.summary.nil? and not this.summary.empty?">
116 + <form action="&create_approval_path" if="&Approval.user_is(current_user).agenda_is(this).count.zero?">
117 + <input type="hidden" name="approval[user_id]" value="&current_user.id"/>
118 + <input type="hidden" name="approval[agenda_id]" value="&this.id"/>
119 + <submit label="approve summary"/>
120 + </form>
121 + <else>
122 + <with with="&Approval.agenda_is(this).user_is(current_user).first">
123 + <delete-button label="remove your approval for this summary" />
124 + </with>
125 + </else>
126 + </if>
127 + <unless test="&this.approvals.count.zero?">
128 + Summary for this agenda was approved by <%= this.approvals.count %> council member(s):
129 + <%= this.approvals.*.user.*.name.join(", ") %>.
130 + </unless>
131 </append-content-body:>
132 </show-page>
133
134 diff --git a/site/config/hobo_routes.rb b/site/config/hobo_routes.rb
135 index a426e53..97dced8 100644
136 --- a/site/config/hobo_routes.rb
137 +++ b/site/config/hobo_routes.rb
138 @@ -15,6 +15,14 @@ Council::Application.routes.draw do
139 delete 'proxies/:id(.:format)' => 'proxies#destroy', :as => 'destroy_proxy', :constraints => { :id => %r([^/.?]+) }
140
141
142 + # Resource routes for controller "approvals"
143 + get 'approvals/:id/edit(.:format)' => 'approvals#edit', :as => 'edit_approval'
144 + get 'approvals/:id(.:format)' => 'approvals#show', :as => 'approval', :constraints => { :id => %r([^/.?]+) }
145 + post 'approvals(.:format)' => 'approvals#create', :as => 'create_approval'
146 + put 'approvals/:id(.:format)' => 'approvals#update', :as => 'update_approval', :constraints => { :id => %r([^/.?]+) }
147 + delete 'approvals/:id(.:format)' => 'approvals#destroy', :as => 'destroy_approval', :constraints => { :id => %r([^/.?]+) }
148 +
149 +
150 # Lifecycle routes for controller "users"
151 post 'users/signup(.:format)' => 'users#do_signup', :as => 'do_user_signup'
152 get 'users/signup(.:format)' => 'users#signup', :as => 'user_signup'
153
154 diff --git a/site/db/schema.rb b/site/db/schema.rb
155 index a6232e1..48027f5 100644
156 --- a/site/db/schema.rb
157 +++ b/site/db/schema.rb
158 @@ -10,7 +10,7 @@
159 #
160 # It's strongly recommended to check this file into your version control system.
161
162 -ActiveRecord::Schema.define(:version => 20110721103758) do
163 +ActiveRecord::Schema.define(:version => 20110721195225) do
164
165 create_table "agenda_items", :force => true do |t|
166 t.string "title", :default => "", :null => false
167 @@ -41,6 +41,16 @@ ActiveRecord::Schema.define(:version => 20110721103758) do
168
169 add_index "agendas", ["state"], :name => "index_agendas_on_state"
170
171 + create_table "approvals", :force => true do |t|
172 + t.datetime "created_at"
173 + t.datetime "updated_at"
174 + t.integer "user_id", :null => false
175 + t.integer "agenda_id", :null => false
176 + end
177 +
178 + add_index "approvals", ["agenda_id"], :name => "index_approvals_on_agenda_id"
179 + add_index "approvals", ["user_id"], :name => "index_approvals_on_user_id"
180 +
181 create_table "delayed_jobs", :force => true do |t|
182 t.integer "priority", :default => 0
183 t.integer "attempts", :default => 0
184
185 diff --git a/site/features/meeting_summary_approvals.feature b/site/features/meeting_summary_approvals.feature
186 new file mode 100644
187 index 0000000..e49e467
188 --- /dev/null
189 +++ b/site/features/meeting_summary_approvals.feature
190 @@ -0,0 +1,28 @@
191 +Feature: Meeting summary approvals
192 + As council member I want to prepare meeting summaries
193 + And I want other council members to approve them
194 + So they will become public only when majority of council approves
195 +
196 + Scenario: Write meeting summary
197 + Given I am logged in as a council member
198 + When I am on the current agenda page
199 + And I follow "Edit"
200 + And I fill in "agenda[summary]" with "some summary"
201 + And I press "Save"
202 + Then I should see "some summary" as summary
203 +
204 + Scenario: Approve meeting summary, then remove approval
205 + Given I am logged in as a council member
206 + When current agenda has a summary
207 + And I am on the current agenda page
208 + And I press "approve summary"
209 + Then I should see "The Approval was created successfully" in the notices
210 +
211 + When I am on the current agenda page
212 + Then I should see "Summary for this agenda was approved by 1 council member(s): Example."
213 +
214 + When I press "remove your approval for this summary"
215 + And I confirm
216 +
217 + When I am on the current agenda page
218 + Then I should not see "Summary for this agenda was approved"
219
220 diff --git a/site/features/step_definitions/meeting_summary_approvals_steps.rb b/site/features/step_definitions/meeting_summary_approvals_steps.rb
221 new file mode 100644
222 index 0000000..adf1481
223 --- /dev/null
224 +++ b/site/features/step_definitions/meeting_summary_approvals_steps.rb
225 @@ -0,0 +1,5 @@
226 +When /^current agenda has a summary$/ do
227 + agenda = Agenda.current
228 + agenda.summary = 'Summary'
229 + agenda.save!
230 +end
231
232 diff --git a/site/features/step_definitions/within_steps.rb b/site/features/step_definitions/within_steps.rb
233 index a36a4af..42f2ff6 100644
234 --- a/site/features/step_definitions/within_steps.rb
235 +++ b/site/features/step_definitions/within_steps.rb
236 @@ -11,6 +11,7 @@
237 'as meeting time' => '.meeting-time-view',
238 'as proxy' => '.collection.proxies.proxies-collection',
239 'as the user nick' => '.user-irc-nick',
240 + 'as summary' => '.agenda-summary',
241 'as voting option' => '.collection.voting-options',
242 'as voting option description' => '.voting-option-description'
243 }.
244
245 diff --git a/site/spec/factories.rb b/site/spec/factories.rb
246 index 01a69f7..2664917 100644
247 --- a/site/spec/factories.rb
248 +++ b/site/spec/factories.rb
249 @@ -32,4 +32,9 @@ Factory.define :proxy do |p|;
250 p.agenda {Factory(:agenda)}
251 end
252
253 +Factory.define :approval do |a|;
254 + a.user {users_factory(:council)}
255 + a.agenda {Agenda.current}
256 +end
257 +
258 require File.expand_path("../support/users_factory.rb", __FILE__)
259
260 diff --git a/site/spec/models/agenda_spec.rb b/site/spec/models/agenda_spec.rb
261 index 00165d1..b9e564c 100644
262 --- a/site/spec/models/agenda_spec.rb
263 +++ b/site/spec/models/agenda_spec.rb
264 @@ -23,6 +23,20 @@ describe Agenda do
265 end
266 end
267
268 + it 'should allow everybody to view summaries after 4 council members approved it' do
269 + agenda = Agenda.current
270 +
271 + for u in users_factory(:guest, :user, :admin)
272 + agenda.should_not be_viewable_by(u, :summary)
273 + end
274 +
275 + (1..4).each { |i| Factory(:approval, :agenda => agenda) }
276 +
277 + for u in users_factory(AllRoles)
278 + agenda.should be_viewable_by(u, :summary)
279 + end
280 + end
281 +
282 it 'should allow only administrators and council members to edit and update' do
283 a = Factory(:agenda)
284 for u in users_factory(:guest, :user)
285 @@ -310,4 +324,12 @@ describe Agenda do
286 VotingOption.last.description.should == 'new option'
287 end
288 end
289 +
290 + it 'should remove approvals for summary, when summary changes' do
291 + agenda = Agenda.current
292 + Factory(:approval, :agenda => agenda)
293 + agenda.summary = 'changed'
294 + agenda.save!
295 + Approval.count.should be_zero
296 + end
297 end
298
299 diff --git a/site/spec/models/approval_spec.rb b/site/spec/models/approval_spec.rb
300 new file mode 100644
301 index 0000000..4057a6d
302 --- /dev/null
303 +++ b/site/spec/models/approval_spec.rb
304 @@ -0,0 +1,36 @@
305 +require 'spec_helper'
306 +
307 +describe Approval do
308 + it 'should be viewable by everybody' do
309 + approval = Factory(:approval)
310 + for user in users_factory(AllRoles)
311 + approval.should be_viewable_by(user)
312 + end
313 + end
314 +
315 + it 'only council members should be able to change it - and only for themselves' do
316 + for user in users_factory(:council, :council_admin)
317 + approval = Factory(:approval, :user => user)
318 + approval.should be_creatable_by(user)
319 + approval.should be_editable_by(user)
320 + approval.should be_updatable_by(user)
321 + approval.should be_destroyable_by(user)
322 + end
323 +
324 + approval = Factory(:approval)
325 + for user in users_factory(:council, :council_admin)
326 + approval.should_not be_creatable_by(user)
327 + approval.should_not be_editable_by(user)
328 + approval.should_not be_updatable_by(user)
329 + approval.should_not be_destroyable_by(user)
330 + end
331 +
332 + for user in users_factory(:user, :admin)
333 + approval = Approval.new :user => user, :agenda => Agenda.current
334 + approval.should_not be_creatable_by(user)
335 + approval.should_not be_editable_by(user)
336 + approval.should_not be_updatable_by(user)
337 + approval.should_not be_destroyable_by(user)
338 + end
339 + end
340 +end