Guest User

Untitled

a guest
Apr 12th, 2018
90
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 23.88 KB | None | 0 0
  1. # Initialize hobo
  2. $ rm -fr agility
  3. $ hobo agility
  4. $ cd agility
  5. {: .bash}
  6. ### add db:seeds rake task
  7. {: .bash}
  8. ::: ./lib/tasks/database.rake
  9. new file mode 100644
  10. @@ -0,0 +1,15 @@
  11. +# until rails 3.0, we grab this task from the edge...
  12. +namespace :db do
  13. + desc 'Drops and recreates the database from db/schema.rb for the current environment and loads the seeds.'
  14. + task :reset => [ 'db:drop', 'db:setup' ]
  15. +
  16. + desc 'Create the database, load the schema, and initialize with the seed data'
  17. + task :setup => [ 'db:create', 'db:schema:load', 'db:seed' ]
  18. +
  19. + desc 'Load the seed data from db/seeds.rb'
  20. + task :seed => :environment do
  21. + seed_file = File.join(Rails.root, 'db', 'seeds.rb')
  22. + load(seed_file) if File.exist?(seed_file)
  23. + end
  24. +end
  25. +
  26. {: .diff .ruby .dryml}
  27. ### add cucumber and rspec
  28. $ ./script/generate rspec -q
  29. $ ./script/generate cucumber -q
  30. {: .bash}
  31. # Generate the app, models and resources
  32. $ ./script/generate hobo_model_resource project name:string
  33. $ ./script/generate hobo_model_resource story title:string body:text status:string
  34. $ ./script/generate hobo_model_resource task description:string
  35. $ ./script/generate hobo_model task_assignment
  36. {: .bash}
  37. ### Associations
  38. {: .bash}
  39. ::: ./app/models/project.rb
  40. @@ -7,6 +7,7 @@ class Project < ActiveRecord::Base
  41. timestamps
  42. end
  43.  
  44. + has_many :stories, :dependent => :destroy
  45.  
  46. # --- Permissions --- #
  47.  
  48. {: .diff .ruby .dryml}
  49. ::: ./app/models/story.rb
  50. @@ -9,6 +9,9 @@ class Story < ActiveRecord::Base
  51. timestamps
  52. end
  53.  
  54. + belongs_to :project
  55. +
  56. + has_many :tasks, :dependent => :destroy
  57.  
  58. # --- Permissions --- #
  59.  
  60. {: .diff .ruby .dryml}
  61. ::: ./app/models/task.rb
  62. @@ -7,6 +7,10 @@ class Task < ActiveRecord::Base
  63. timestamps
  64. end
  65.  
  66. + belongs_to :story
  67. +
  68. + has_many :task_assignments, :dependent => :destroy
  69. + has_many :users, :through => :task_assignments
  70.  
  71. # --- Permissions --- #
  72.  
  73. {: .diff .ruby .dryml}
  74. ::: ./app/models/task_assignment.rb
  75. @@ -6,6 +6,8 @@ class TaskAssignment < ActiveRecord::Base
  76. timestamps
  77. end
  78.  
  79. + belongs_to :user
  80. + belongs_to :task
  81.  
  82. # --- Permissions --- #
  83.  
  84. {: .diff .ruby .dryml}
  85. ::: ./app/models/user.rb
  86. @@ -9,6 +9,9 @@ class User < ActiveRecord::Base
  87. timestamps
  88. end
  89.  
  90. + has_many :task_assignments, :dependent => :destroy
  91. + has_many :tasks, :through => :task_assignments
  92. +
  93. # This gives admin rights to the first sign-up.
  94. # Just remove it if you don't want that
  95. before_create { |user| user.administrator = true if RAILS_ENV != "test" && count == 0 }
  96. {: .diff .ruby .dryml}
  97. ### Run the Hobo Migrator
  98. $ ./script/generate hobo_migration initial_models --default-name --migrate
  99. {: .bash}
  100. ## Removing Actions / Permissions
  101. {: .bash}
  102. ::: ./app/controllers/stories_controller.rb
  103. @@ -2,6 +2,8 @@ class StoriesController < ApplicationController
  104.  
  105. hobo_model_controller
  106.  
  107. - auto_actions :all
  108. + auto_actions :all, :except => :index
  109. +
  110. + auto_actions_for :project, [:new, :create]
  111.  
  112. end
  113. {: .diff .ruby .dryml}
  114. ::: ./app/controllers/tasks_controller.rb
  115. @@ -2,6 +2,8 @@ class TasksController < ApplicationController
  116.  
  117. hobo_model_controller
  118.  
  119. - auto_actions :all
  120. + auto_actions :write_only, :edit
  121. +
  122. + auto_actions_for :story, :create
  123.  
  124. end
  125. {: .diff .ruby .dryml}
  126. ::: ./app/models/story.rb
  127. @@ -20,7 +20,7 @@ class Story < ActiveRecord::Base
  128. end
  129.  
  130. def update_permitted?
  131. - acting_user.administrator?
  132. + acting_user.signed_up? && !project_changed?
  133. end
  134.  
  135. def destroy_permitted?
  136. {: .diff .ruby .dryml}
  137. ::: ./app/models/task.rb
  138. @@ -10,7 +10,7 @@ class Task < ActiveRecord::Base
  139. belongs_to :story
  140.  
  141. has_many :task_assignments, :dependent => :destroy
  142. - has_many :users, :through => :task_assignments
  143. + has_many :users, :through => :task_assignments, :accessible => true
  144.  
  145. # --- Permissions --- #
  146.  
  147. @@ -19,7 +19,7 @@ class Task < ActiveRecord::Base
  148. end
  149.  
  150. def update_permitted?
  151. - acting_user.administrator?
  152. + acting_user.signed_up? && !story_changed?
  153. end
  154.  
  155. def destroy_permitted?
  156. {: .diff .ruby .dryml}
  157. ## Customising views
  158. {: .bash}
  159. ::: ./app/controllers/projects_controller.rb
  160. @@ -4,4 +4,11 @@ class ProjectsController < ApplicationController
  161.  
  162. auto_actions :all
  163.  
  164. + def show
  165. + @project = find_instance
  166. + @stories =
  167. + @project.stories.apply_scopes(:search => [params[:search], :title],
  168. + :order_by => parse_sort_param(:title, :status))
  169. + end
  170. +
  171. end
  172. {: .diff .ruby .dryml}
  173. ::: ./app/views/projects/show.dryml
  174. new file mode 100644
  175. @@ -0,0 +1,7 @@
  176. +<show-page>
  177. + <collection: replace>
  178. + <table-plus with="&@stories" fields="this, tasks.count, status">
  179. + <empty-message:>No stories match your criteria</empty-message:>
  180. + </table-plus>
  181. + </collection:>
  182. +</show-page>
  183. {: .diff .ruby .dryml}
  184. ::: ./app/views/taglibs/application.dryml
  185. @@ -8,4 +8,12 @@
  186.  
  187. <def tag="app-name">Agility</def>
  188.  
  189. -
  190. +<extend tag="card" for="Task">
  191. + <old-card merge>
  192. + <append-body:>
  193. + <div class="users">
  194. + Assigned users: <repeat:users join=", "><a/></repeat><else>None</else>
  195. + </div>
  196. + </append-body:>
  197. + </old-card>
  198. +</extend>
  199. {: .diff .ruby .dryml}
  200. ::: ./app/views/users/show.dryml
  201. new file mode 100644
  202. @@ -0,0 +1,9 @@
  203. +<show-page>
  204. + <content-body:>
  205. + <h3><Your/> Assigned Tasks</h3>
  206. + <repeat with="&@user.tasks.group_by(&:story)">
  207. + <h4>Story: <a with="&this_key"/></h4>
  208. + <collection/>
  209. + </repeat>
  210. + </content-body:>
  211. +</show-page>
  212. {: .diff .ruby .dryml}
  213. # Add User Activation
  214. {: .bash}
  215. ::: ./app/models/user.rb
  216. @@ -20,12 +20,16 @@ class User < ActiveRecord::Base
  217. # --- Signup lifecycle --- #
  218.  
  219. lifecycle do
  220. -
  221. - state :active, :default => true
  222. + state :inactive, :default => true
  223. + state :active
  224.  
  225. create :signup, :available_to => "Guest",
  226. :params => [:name, :email_address, :password, :password_confirmation],
  227. - :become => :active
  228. + :become => :inactive, :new_key => true do
  229. + UserMailer.deliver_activation(self, lifecycle.key)
  230. + end
  231. +
  232. + transition :activate, { :inactive => :active }, :available_to => :key_holder
  233.  
  234. transition :request_password_reset, { :active => :active }, :new_key => true do
  235. UserMailer.deliver_forgot_password(self, lifecycle.key)
  236. {: .diff .ruby .dryml}
  237. ::: ./app/models/user_mailer.rb
  238. @@ -11,4 +11,15 @@ class UserMailer < ActionMailer::Base
  239. @headers = {}
  240. end
  241.  
  242. + def activation(user, key)
  243. + host = Hobo::Controller.request_host
  244. + app_name = Hobo::Controller.app_name || host
  245. + @subject = "#{app_name} -- activate"
  246. + @body = { :user => user, :key => key, :host => host, :app_name => app_name }
  247. + @recipients = user.email_address
  248. + @from = "no-reply@#{host}"
  249. + @sent_on = Time.now
  250. + @headers = {}
  251. + end
  252. +
  253. end
  254. {: .diff .ruby .dryml}
  255. ::: ./app/views/user_mailer/activation.erb
  256. new file mode 100644
  257. @@ -0,0 +1,9 @@
  258. +<%= @user %>,
  259. +
  260. +To activate your account for <%= @app_name %>, click on this link:
  261. +
  262. + <%= user_activate_url :host => @host, :id => @user, :key => @key %>
  263. +
  264. +Thank you,
  265. +
  266. +The <%= @app_name %> team.
  267. {: .diff .ruby .dryml}
  268. ::: ./config/initializers/mailer.rb
  269. new file mode 100644
  270. @@ -0,0 +1,9 @@
  271. +ActionMailer::Base.delivery_method = :smtp
  272. +ActionMailer::Base.smtp_settings = {
  273. +# :address => "smtp.example.com",
  274. +# :port => 25,
  275. +# :domain => "example.com",
  276. +# :authentication => :login,
  277. +# :user_name => "username",
  278. +# :password => "password",
  279. +}
  280. {: .diff .ruby .dryml}
  281. ### Run the Hobo Migrator
  282. $ ./script/generate hobo_migration user_activation --default-name --migrate
  283. {: .bash}
  284. # Odds and ends
  285. ## Generate StoryStatus resource
  286. $ ./script/generate hobo_model_resource story_status name:string
  287. {: .bash}
  288. ## Story Status association/action/permission
  289. {: .bash}
  290. ::: ./app/controllers/story_statuses_controller.rb
  291. @@ -2,6 +2,6 @@ class StoryStatusesController < ApplicationController
  292.  
  293. hobo_model_controller
  294.  
  295. - auto_actions :all
  296. + auto_actions :write_only, :new, :index
  297.  
  298. end
  299. {: .diff .ruby .dryml}
  300. ::: ./app/models/story.rb
  301. @@ -5,11 +5,11 @@ class Story < ActiveRecord::Base
  302. fields do
  303. title :string
  304. body :text
  305. - status :string
  306. timestamps
  307. end
  308.  
  309. belongs_to :project
  310. + belongs_to :status, :class_name => "StoryStatus"
  311.  
  312. has_many :tasks, :dependent => :destroy
  313.  
  314. @@ -31,4 +31,9 @@ class Story < ActiveRecord::Base
  315. true
  316. end
  317.  
  318. + # force 'new' status at create.
  319. + def before_create
  320. + self.status = @default_status ||= StoryStatus.find_by_name( 'new' )
  321. + end
  322. +
  323. end
  324. {: .diff .ruby .dryml}
  325. ::: ./app/views/stories/show.dryml
  326. new file mode 100644
  327. @@ -0,0 +1,3 @@
  328. +<show-page>
  329. + <field-list: tag="editor"/>
  330. +</show-page>
  331. {: .diff .ruby .dryml}
  332. ::: ./db/seeds.rb
  333. new file mode 100644
  334. @@ -0,0 +1,3 @@
  335. +# Story Status
  336. +statuses = %w(new accepted discussion implementation user_testing deployed rejected)
  337. +statuses.each { |status| StoryStatus.create :name => status }
  338. {: .diff .ruby .dryml}
  339. ### Run the Hobo Migrator
  340. $ ./script/generate hobo_migration story_status_model --default-name --force-drop --migrate
  341. ### Use the new (Rails 3.0) rake task to seed the storystatus table
  342. $ rake -s db:seed
  343. {: .bash}
  344. ## Filtering stories by status
  345. {: .bash}
  346. ::: ./app/controllers/projects_controller.rb
  347. @@ -8,6 +8,7 @@ class ProjectsController < ApplicationController
  348. @project = find_instance
  349. @stories =
  350. @project.stories.apply_scopes(:search => [params[:search], :title],
  351. + :status_is => params[:status],
  352. :order_by => parse_sort_param(:title, :status))
  353. end
  354.  
  355. {: .diff .ruby .dryml}
  356. ::: ./app/views/projects/show.dryml
  357. @@ -1,6 +1,11 @@
  358. <show-page>
  359. <collection: replace>
  360. <table-plus with="&@stories" fields="this, tasks.count, status">
  361. + <prepend-header:>
  362. + <div class="filter">
  363. + Display by status: <filter-menu param-name="status" options="&StoryStatus.all"/>
  364. + </div>
  365. + </prepend-header:>
  366. <empty-message:>No stories match your criteria</empty-message:>
  367. </table-plus>
  368. </collection:>
  369. {: .diff .ruby .dryml}
  370. ::: ./public/stylesheets/application.css
  371. @@ -0,0 +1,2 @@
  372. +.show-page.project .filter {float: left;}
  373. +.show-page.project .filter form, .show-page.project .filter form div {display: inline;}
  374. {: .diff .ruby .dryml}
  375. {: .bash}
  376. ## Add Acts as List plugin
  377. $ ./script/plugin install acts_as_list
  378. {: .bash}
  379. ::: ./app/models/story.rb
  380. @@ -11,7 +11,7 @@ class Story < ActiveRecord::Base
  381. belongs_to :project
  382. belongs_to :status, :class_name => "StoryStatus"
  383.  
  384. - has_many :tasks, :dependent => :destroy
  385. + has_many :tasks, :dependent => :destroy, :order => :position
  386.  
  387. # --- Permissions --- #
  388.  
  389. {: .diff .ruby .dryml}
  390. ::: ./app/models/task.rb
  391. @@ -9,6 +9,9 @@ class Task < ActiveRecord::Base
  392.  
  393. belongs_to :story
  394.  
  395. + acts_as_list :scope => :story
  396. + attr_protected :position
  397. +
  398. has_many :task_assignments, :dependent => :destroy
  399. has_many :users, :through => :task_assignments, :accessible => true
  400.  
  401. {: .diff .ruby .dryml}
  402. ::: ./app/views/tasks/edit.dryml
  403. new file mode 100644
  404. @@ -0,0 +1,5 @@
  405. +<edit-page>
  406. + <form:>
  407. + <cancel: with="&this.story"/>
  408. + </form:>
  409. +</edit-page>
  410. {: .diff .ruby .dryml}
  411. ### Run the Hobo Migrator
  412. $ ./script/generate hobo_migration acts_as_list --default-name --migrate
  413. {: .bash}
  414. ## Markdown / Textile formatting of stories
  415. {: .bash}
  416. ::: ./app/models/story.rb
  417. @@ -4,7 +4,7 @@ class Story < ActiveRecord::Base
  418.  
  419. fields do
  420. title :string
  421. - body :text
  422. + body :markdown
  423. timestamps
  424. end
  425.  
  426. {: .diff .ruby .dryml}
  427. ::: ./config/environment.rb
  428. @@ -9,6 +9,8 @@ require File.join(File.dirname(__FILE__), 'boot')
  429. Rails::Initializer.run do |config|
  430. config.gem 'hobo'
  431.  
  432. + config.gem 'bluecloth'
  433. +
  434. # Settings in config/environments/* take precedence over those specified here.
  435. # Application configuration should go into files in config/initializers
  436. # -- all .rb files in that directory are automatically loaded.
  437. {: .diff .ruby .dryml}
  438. $ rake -s gems:install
  439. ## Front page touch up.
  440. {: .bash}
  441. ::: ./app/views/front/index.dryml
  442. @@ -13,7 +13,9 @@
  443. </section>
  444. </header>
  445.  
  446. - <section class="content-body">
  447. + <section class="content-body" if="&logged_in?">
  448. + <h3>Your Projects</h3>
  449. + <collection:projects with="&current_user"><card without-creator-link/></collection>
  450. </section>
  451. </content:>
  452.  
  453. {: .diff .ruby .dryml}
  454. # Project ownership
  455. {: .bash}
  456. ::: ./app/models/project.rb
  457. @@ -9,18 +9,20 @@ class Project < ActiveRecord::Base
  458.  
  459. has_many :stories, :dependent => :destroy
  460.  
  461. + belongs_to :owner, :class_name => "User", :creator => true
  462. +
  463. # --- Permissions --- #
  464.  
  465. def create_permitted?
  466. - acting_user.administrator?
  467. + owner_is? acting_user
  468. end
  469.  
  470. def update_permitted?
  471. - acting_user.administrator?
  472. + acting_user.administrator? || (owner_is?(acting_user) && !owner_changed?)
  473. end
  474.  
  475. def destroy_permitted?
  476. - acting_user.administrator?
  477. + acting_user.administrator? || owner_is?(acting_user)
  478. end
  479.  
  480. def view_permitted?(field)
  481. {: .diff .ruby .dryml}
  482. ::: ./app/models/user.rb
  483. @@ -11,6 +11,7 @@ class User < ActiveRecord::Base
  484.  
  485. has_many :task_assignments, :dependent => :destroy
  486. has_many :tasks, :through => :task_assignments
  487. + has_many :projects, :class_name => "Project", :foreign_key => "owner_id"
  488.  
  489. # This gives admin rights to the first sign-up.
  490. # Just remove it if you don't want that
  491. {: .diff .ruby .dryml}
  492. ### Project Ownership - migration
  493. $ ./script/generate hobo_migration project_ownership --default-name --migrate
  494. {: .bash}
  495. ## Granting read access to others
  496. $ ./script/generate hobo_model_resource project_membership
  497. {: .bash}
  498. ## Project Membership - association/action
  499. {: .bash}
  500. ::: ./app/controllers/project_memberships_controller.rb
  501. @@ -2,6 +2,6 @@ class ProjectMembershipsController < ApplicationController
  502.  
  503. hobo_model_controller
  504.  
  505. - auto_actions :all
  506. + auto_actions :write_only
  507.  
  508. end
  509. {: .diff .ruby .dryml}
  510. ::: ./app/models/project_membership.rb
  511. @@ -6,6 +6,8 @@ class ProjectMembership < ActiveRecord::Base
  512. timestamps
  513. end
  514.  
  515. + belongs_to :project
  516. + belongs_to :user
  517.  
  518. # --- Permissions --- #
  519.  
  520. {: .diff .ruby .dryml}
  521. ### Project Membership migration
  522. $ ./script/generate hobo_migration project_memberships --default-name --migrate
  523. {: .bash}
  524. ## Project Membership associations/actions/permissions
  525. {: .bash}
  526. ::: ./app/controllers/projects_controller.rb
  527. @@ -2,7 +2,9 @@ class ProjectsController < ApplicationController
  528.  
  529. hobo_model_controller
  530.  
  531. - auto_actions :all
  532. + auto_actions :show, :edit, :update, :destroy
  533. +
  534. + auto_actions_for :owner, [:new, :create]
  535.  
  536. def show
  537. @project = find_instance
  538. {: .diff .ruby .dryml}
  539. ::: ./app/models/project.rb
  540. @@ -8,6 +8,8 @@ class Project < ActiveRecord::Base
  541. end
  542.  
  543. has_many :stories, :dependent => :destroy
  544. + has_many :memberships, :class_name => "ProjectMembership", :dependent => :destroy
  545. + has_many :members, :through => :memberships, :source => :user
  546.  
  547. belongs_to :owner, :class_name => "User", :creator => true
  548.  
  549. @@ -26,7 +28,7 @@ class Project < ActiveRecord::Base
  550. end
  551.  
  552. def view_permitted?(field)
  553. - true
  554. + acting_user.administrator? || acting_user == owner || acting_user.in?(members)
  555. end
  556.  
  557. end
  558. {: .diff .ruby .dryml}
  559. ::: ./app/models/project_membership.rb
  560. @@ -12,15 +12,15 @@ class ProjectMembership < ActiveRecord::Base
  561. # --- Permissions --- #
  562.  
  563. def create_permitted?
  564. - acting_user.administrator?
  565. + acting_user.administrator? || project.owner_is?(acting_user)
  566. end
  567.  
  568. def update_permitted?
  569. - acting_user.administrator?
  570. + acting_user.administrator? || project.owner_is?(acting_user)
  571. end
  572.  
  573. def destroy_permitted?
  574. - acting_user.administrator?
  575. + acting_user.administrator? || project.owner_is?(acting_user)
  576. end
  577.  
  578. def view_permitted?(field)
  579. {: .diff .ruby .dryml}
  580. ::: ./app/models/story.rb
  581. @@ -28,7 +28,7 @@ class Story < ActiveRecord::Base
  582. end
  583.  
  584. def view_permitted?(field)
  585. - true
  586. + project.viewable_by?(acting_user)
  587. end
  588.  
  589. # force 'new' status at create.
  590. {: .diff .ruby .dryml}
  591. ::: ./app/models/task.rb
  592. @@ -30,7 +30,7 @@ class Task < ActiveRecord::Base
  593. end
  594.  
  595. def view_permitted?(field)
  596. - true
  597. + story.viewable_by?(acting_user)
  598. end
  599.  
  600. end
  601. {: .diff .ruby .dryml}
  602. ::: ./app/models/user.rb
  603. @@ -12,6 +12,8 @@ class User < ActiveRecord::Base
  604. has_many :task_assignments, :dependent => :destroy
  605. has_many :tasks, :through => :task_assignments
  606. has_many :projects, :class_name => "Project", :foreign_key => "owner_id"
  607. + has_many :project_memberships, :dependent => :destroy
  608. + has_many :joined_projects, :through => :project_memberships, :source => :project
  609.  
  610. # This gives admin rights to the first sign-up.
  611. # Just remove it if you don't want that
  612. {: .diff .ruby .dryml}
  613. ## Project Contributor associations/actions/permissions
  614. {: .bash}
  615. ::: ./app/controllers/projects_controller.rb
  616. @@ -6,6 +6,11 @@ class ProjectsController < ApplicationController
  617.  
  618. auto_actions_for :owner, [:new, :create]
  619.  
  620. + autocomplete :new_member_name do
  621. + project = find_instance
  622. + hobo_completions :name, User.without_project(project).is_not(project.owner)
  623. + end
  624. +
  625. def show
  626. @project = find_instance
  627. @stories =
  628. {: .diff .ruby .dryml}
  629. ::: ./app/models/project.rb
  630. @@ -13,6 +13,14 @@ class Project < ActiveRecord::Base
  631.  
  632. belongs_to :owner, :class_name => "User", :creator => true
  633.  
  634. + has_many :contributor_memberships, :class_name => "ProjectMembership", :scope => :contributor
  635. + has_many :contributors, :through => :contributor_memberships, :source => :user
  636. +
  637. + # permission helper
  638. + def accepts_changes_from?(user)
  639. + user.administrator? || user == owner || user.in?(contributors)
  640. + end
  641. +
  642. # --- Permissions --- #
  643.  
  644. def create_permitted?
  645. @@ -20,7 +28,7 @@ class Project < ActiveRecord::Base
  646. end
  647.  
  648. def update_permitted?
  649. - acting_user.administrator? || (owner_is?(acting_user) && !owner_changed?)
  650. + accepts_changes_from?(acting_user) && !owner_changed?
  651. end
  652.  
  653. def destroy_permitted?
  654. {: .diff .ruby .dryml}
  655. ::: ./app/models/project_membership.rb
  656. @@ -3,6 +3,7 @@ class ProjectMembership < ActiveRecord::Base
  657. hobo_model # Don't put anything above this
  658.  
  659. fields do
  660. + contributor :boolean, :default => false
  661. timestamps
  662. end
  663.  
  664. {: .diff .ruby .dryml}
  665. ::: ./app/models/story.rb
  666. @@ -16,15 +16,15 @@ class Story < ActiveRecord::Base
  667. # --- Permissions --- #
  668.  
  669. def create_permitted?
  670. - acting_user.administrator?
  671. + project.creatable_by?(acting_user)
  672. end
  673.  
  674. def update_permitted?
  675. - acting_user.signed_up? && !project_changed?
  676. + project.updatable_by?(acting_user)
  677. end
  678.  
  679. def destroy_permitted?
  680. - acting_user.administrator?
  681. + project.destroyable_by?(acting_user)
  682. end
  683.  
  684. def view_permitted?(field)
  685. {: .diff .ruby .dryml}
  686. ::: ./app/models/task.rb
  687. @@ -18,15 +18,15 @@ class Task < ActiveRecord::Base
  688. # --- Permissions --- #
  689.  
  690. def create_permitted?
  691. - acting_user.administrator?
  692. + story.creatable_by?(acting_user)
  693. end
  694.  
  695. def update_permitted?
  696. - acting_user.signed_up? && !story_changed?
  697. + story.updatable_by?(acting_user)
  698. end
  699.  
  700. def destroy_permitted?
  701. - acting_user.administrator?
  702. + story.destroyable_by?(acting_user)
  703. end
  704.  
  705. def view_permitted?(field)
  706. {: .diff .ruby .dryml}
  707. ::: ./app/models/task_assignment.rb
  708. @@ -12,19 +12,19 @@ class TaskAssignment < ActiveRecord::Base
  709. # --- Permissions --- #
  710.  
  711. def create_permitted?
  712. - acting_user.administrator?
  713. + task.creatable_by?(acting_user)
  714. end
  715.  
  716. def update_permitted?
  717. - acting_user.administrator?
  718. + task.updatable_by?(acting_user)
  719. end
  720.  
  721. def destroy_permitted?
  722. - acting_user.administrator?
  723. + task.destroyable_by?(acting_user)
  724. end
  725.  
  726. def view_permitted?(field)
  727. - true
  728. + task.viewable_by?(acting_user)
  729. end
  730.  
  731. end
  732. {: .diff .ruby .dryml}
  733. ::: ./app/viewhints/project_hints.rb
  734. @@ -1,4 +1,3 @@
  735. class ProjectHints < Hobo::ViewHints
  736. -
  737. -
  738. + children :stories, :memberships
  739. end
  740. {: .diff .ruby .dryml}
  741. ### Project Contributor migration
  742. $ ./script/generate hobo_migration project_contributorships --default-name --migrate
  743. {: .bash}
  744. ## Project Contributor view layer
  745. {: .bash}
  746. ::: ./app/views/front/index.dryml
  747. @@ -13,9 +13,14 @@
  748. </section>
  749. </header>
  750.  
  751. - <section class="content-body" if="&logged_in?">
  752. + <section with="&current_user" class="content-body" if="&logged_in?">
  753. <h3>Your Projects</h3>
  754. - <collection:projects with="&current_user"><card without-creator-link/></collection>
  755. + <collection:projects><card without-creator-link/></collection>
  756. +
  757. + <a:projects action="new">New Project</a>
  758. +
  759. + <h3>Projects you have joined</h3>
  760. + <collection:joined-projects><card without-creator-link/></collection>
  761. </section>
  762. </content:>
  763.  
  764. {: .diff .ruby .dryml}
  765. ::: ./app/views/projects/show.dryml
  766. @@ -9,4 +9,19 @@
  767. <empty-message:>No stories match your criteria</empty-message:>
  768. </table-plus>
  769. </collection:>
  770. +
  771. + <aside:>
  772. + <h2>Project Members</h2>
  773. + <collection:memberships part="members">
  774. + <card><heading:><a:user/></heading:></card>
  775. + </collection>
  776. +
  777. + <form:memberships.new update="members" reset-form refocus-form>
  778. + <div>
  779. + Add a member:
  780. + <name-one:user complete-target="&@project" completer="new_member_name"/>
  781. + </div>
  782. + </form>
  783. + </aside:>
  784. +
  785. </show-page>
  786. {: .diff .ruby .dryml}
  787. ::: ./app/views/taglibs/application.dryml
  788. @@ -17,3 +17,13 @@
  789. </append-body:>
  790. </old-card>
  791. </extend>
  792. +
  793. +<extend tag="card" for="ProjectMembership">
  794. + <old-card merge>
  795. + <body:>
  796. + <span>Contributor?</span>
  797. + <editor:contributor/>
  798. + </body:>
  799. + </old-card>
  800. +</extend>
  801. +
  802. {: .diff .ruby .dryml}
Add Comment
Please, Sign In to add comment