Created
June 30, 2009 19:04
-
-
Save TMorgan99/138343 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Initialize hobo | |
$ rm -fr agility | |
$ hobo agility | |
$ cd agility | |
{: .bash} | |
### add db:seeds rake task | |
{: .bash} | |
::: ./lib/tasks/database.rake | |
new file mode 100644 | |
@@ -0,0 +1,15 @@ | |
+# until rails 3.0, we grab this task from the edge... | |
+namespace :db do | |
+ desc 'Drops and recreates the database from db/schema.rb for the current environment and loads the seeds.' | |
+ task :reset => [ 'db:drop', 'db:setup' ] | |
+ | |
+ desc 'Create the database, load the schema, and initialize with the seed data' | |
+ task :setup => [ 'db:create', 'db:schema:load', 'db:seed' ] | |
+ | |
+ desc 'Load the seed data from db/seeds.rb' | |
+ task :seed => :environment do | |
+ seed_file = File.join(Rails.root, 'db', 'seeds.rb') | |
+ load(seed_file) if File.exist?(seed_file) | |
+ end | |
+end | |
+ | |
{: .diff .ruby .dryml} | |
### add cucumber and rspec | |
$ ./script/generate rspec -q | |
$ ./script/generate cucumber -q | |
{: .bash} | |
# Generate the app, models and resources | |
$ ./script/generate hobo_model_resource project name:string | |
$ ./script/generate hobo_model_resource story title:string body:text status:string | |
$ ./script/generate hobo_model_resource task description:string | |
$ ./script/generate hobo_model task_assignment | |
{: .bash} | |
### Associations | |
{: .bash} | |
::: ./app/models/project.rb | |
@@ -7,6 +7,7 @@ class Project < ActiveRecord::Base | |
timestamps | |
end | |
+ has_many :stories, :dependent => :destroy | |
# --- Permissions --- # | |
{: .diff .ruby .dryml} | |
::: ./app/models/story.rb | |
@@ -9,6 +9,9 @@ class Story < ActiveRecord::Base | |
timestamps | |
end | |
+ belongs_to :project | |
+ | |
+ has_many :tasks, :dependent => :destroy | |
# --- Permissions --- # | |
{: .diff .ruby .dryml} | |
::: ./app/models/task.rb | |
@@ -7,6 +7,10 @@ class Task < ActiveRecord::Base | |
timestamps | |
end | |
+ belongs_to :story | |
+ | |
+ has_many :task_assignments, :dependent => :destroy | |
+ has_many :users, :through => :task_assignments | |
# --- Permissions --- # | |
{: .diff .ruby .dryml} | |
::: ./app/models/task_assignment.rb | |
@@ -6,6 +6,8 @@ class TaskAssignment < ActiveRecord::Base | |
timestamps | |
end | |
+ belongs_to :user | |
+ belongs_to :task | |
# --- Permissions --- # | |
{: .diff .ruby .dryml} | |
::: ./app/models/user.rb | |
@@ -9,6 +9,9 @@ class User < ActiveRecord::Base | |
timestamps | |
end | |
+ has_many :task_assignments, :dependent => :destroy | |
+ has_many :tasks, :through => :task_assignments | |
+ | |
# This gives admin rights to the first sign-up. | |
# Just remove it if you don't want that | |
before_create { |user| user.administrator = true if RAILS_ENV != "test" && count == 0 } | |
{: .diff .ruby .dryml} | |
### Run the Hobo Migrator | |
$ ./script/generate hobo_migration initial_models --default-name --migrate | |
{: .bash} | |
## Removing Actions / Permissions | |
{: .bash} | |
::: ./app/controllers/stories_controller.rb | |
@@ -2,6 +2,8 @@ class StoriesController < ApplicationController | |
hobo_model_controller | |
- auto_actions :all | |
+ auto_actions :all, :except => :index | |
+ | |
+ auto_actions_for :project, [:new, :create] | |
end | |
{: .diff .ruby .dryml} | |
::: ./app/controllers/tasks_controller.rb | |
@@ -2,6 +2,8 @@ class TasksController < ApplicationController | |
hobo_model_controller | |
- auto_actions :all | |
+ auto_actions :write_only, :edit | |
+ | |
+ auto_actions_for :story, :create | |
end | |
{: .diff .ruby .dryml} | |
::: ./app/models/story.rb | |
@@ -20,7 +20,7 @@ class Story < ActiveRecord::Base | |
end | |
def update_permitted? | |
- acting_user.administrator? | |
+ acting_user.signed_up? && !project_changed? | |
end | |
def destroy_permitted? | |
{: .diff .ruby .dryml} | |
::: ./app/models/task.rb | |
@@ -10,7 +10,7 @@ class Task < ActiveRecord::Base | |
belongs_to :story | |
has_many :task_assignments, :dependent => :destroy | |
- has_many :users, :through => :task_assignments | |
+ has_many :users, :through => :task_assignments, :accessible => true | |
# --- Permissions --- # | |
@@ -19,7 +19,7 @@ class Task < ActiveRecord::Base | |
end | |
def update_permitted? | |
- acting_user.administrator? | |
+ acting_user.signed_up? && !story_changed? | |
end | |
def destroy_permitted? | |
{: .diff .ruby .dryml} | |
## Customising views | |
{: .bash} | |
::: ./app/controllers/projects_controller.rb | |
@@ -4,4 +4,11 @@ class ProjectsController < ApplicationController | |
auto_actions :all | |
+ def show | |
+ @project = find_instance | |
+ @stories = | |
+ @project.stories.apply_scopes(:search => [params[:search], :title], | |
+ :order_by => parse_sort_param(:title, :status)) | |
+ end | |
+ | |
end | |
{: .diff .ruby .dryml} | |
::: ./app/views/projects/show.dryml | |
new file mode 100644 | |
@@ -0,0 +1,7 @@ | |
+<show-page> | |
+ <collection: replace> | |
+ <table-plus with="&@stories" fields="this, tasks.count, status"> | |
+ <empty-message:>No stories match your criteria</empty-message:> | |
+ </table-plus> | |
+ </collection:> | |
+</show-page> | |
{: .diff .ruby .dryml} | |
::: ./app/views/taglibs/application.dryml | |
@@ -8,4 +8,12 @@ | |
<def tag="app-name">Agility</def> | |
- | |
+<extend tag="card" for="Task"> | |
+ <old-card merge> | |
+ <append-body:> | |
+ <div class="users"> | |
+ Assigned users: <repeat:users join=", "><a/></repeat><else>None</else> | |
+ </div> | |
+ </append-body:> | |
+ </old-card> | |
+</extend> | |
{: .diff .ruby .dryml} | |
::: ./app/views/users/show.dryml | |
new file mode 100644 | |
@@ -0,0 +1,9 @@ | |
+<show-page> | |
+ <content-body:> | |
+ <h3><Your/> Assigned Tasks</h3> | |
+ <repeat with="&@user.tasks.group_by(&:story)"> | |
+ <h4>Story: <a with="&this_key"/></h4> | |
+ <collection/> | |
+ </repeat> | |
+ </content-body:> | |
+</show-page> | |
{: .diff .ruby .dryml} | |
# Add User Activation | |
{: .bash} | |
::: ./app/models/user.rb | |
@@ -20,12 +20,16 @@ class User < ActiveRecord::Base | |
# --- Signup lifecycle --- # | |
lifecycle do | |
- | |
- state :active, :default => true | |
+ state :inactive, :default => true | |
+ state :active | |
create :signup, :available_to => "Guest", | |
:params => [:name, :email_address, :password, :password_confirmation], | |
- :become => :active | |
+ :become => :inactive, :new_key => true do | |
+ UserMailer.deliver_activation(self, lifecycle.key) | |
+ end | |
+ | |
+ transition :activate, { :inactive => :active }, :available_to => :key_holder | |
transition :request_password_reset, { :active => :active }, :new_key => true do | |
UserMailer.deliver_forgot_password(self, lifecycle.key) | |
{: .diff .ruby .dryml} | |
::: ./app/models/user_mailer.rb | |
@@ -11,4 +11,15 @@ class UserMailer < ActionMailer::Base | |
@headers = {} | |
end | |
+ def activation(user, key) | |
+ host = Hobo::Controller.request_host | |
+ app_name = Hobo::Controller.app_name || host | |
+ @subject = "#{app_name} -- activate" | |
+ @body = { :user => user, :key => key, :host => host, :app_name => app_name } | |
+ @recipients = user.email_address | |
+ @from = "no-reply@#{host}" | |
+ @sent_on = Time.now | |
+ @headers = {} | |
+ end | |
+ | |
end | |
{: .diff .ruby .dryml} | |
::: ./app/views/user_mailer/activation.erb | |
new file mode 100644 | |
@@ -0,0 +1,9 @@ | |
+<%= @user %>, | |
+ | |
+To activate your account for <%= @app_name %>, click on this link: | |
+ | |
+ <%= user_activate_url :host => @host, :id => @user, :key => @key %> | |
+ | |
+Thank you, | |
+ | |
+The <%= @app_name %> team. | |
{: .diff .ruby .dryml} | |
::: ./config/initializers/mailer.rb | |
new file mode 100644 | |
@@ -0,0 +1,9 @@ | |
+ActionMailer::Base.delivery_method = :smtp | |
+ActionMailer::Base.smtp_settings = { | |
+# :address => "smtp.example.com", | |
+# :port => 25, | |
+# :domain => "example.com", | |
+# :authentication => :login, | |
+# :user_name => "username", | |
+# :password => "password", | |
+} | |
{: .diff .ruby .dryml} | |
### Run the Hobo Migrator | |
$ ./script/generate hobo_migration user_activation --default-name --migrate | |
{: .bash} | |
# Odds and ends | |
## Generate StoryStatus resource | |
$ ./script/generate hobo_model_resource story_status name:string | |
{: .bash} | |
## Story Status association/action/permission | |
{: .bash} | |
::: ./app/controllers/story_statuses_controller.rb | |
@@ -2,6 +2,6 @@ class StoryStatusesController < ApplicationController | |
hobo_model_controller | |
- auto_actions :all | |
+ auto_actions :write_only, :new, :index | |
end | |
{: .diff .ruby .dryml} | |
::: ./app/models/story.rb | |
@@ -5,11 +5,11 @@ class Story < ActiveRecord::Base | |
fields do | |
title :string | |
body :text | |
- status :string | |
timestamps | |
end | |
belongs_to :project | |
+ belongs_to :status, :class_name => "StoryStatus" | |
has_many :tasks, :dependent => :destroy | |
@@ -31,4 +31,9 @@ class Story < ActiveRecord::Base | |
true | |
end | |
+ # force 'new' status at create. | |
+ def before_create | |
+ self.status = @default_status ||= StoryStatus.find_by_name( 'new' ) | |
+ end | |
+ | |
end | |
{: .diff .ruby .dryml} | |
::: ./app/views/stories/show.dryml | |
new file mode 100644 | |
@@ -0,0 +1,3 @@ | |
+<show-page> | |
+ <field-list: tag="editor"/> | |
+</show-page> | |
{: .diff .ruby .dryml} | |
::: ./db/seeds.rb | |
new file mode 100644 | |
@@ -0,0 +1,3 @@ | |
+# Story Status | |
+statuses = %w(new accepted discussion implementation user_testing deployed rejected) | |
+statuses.each { |status| StoryStatus.create :name => status } | |
{: .diff .ruby .dryml} | |
### Run the Hobo Migrator | |
$ ./script/generate hobo_migration story_status_model --default-name --force-drop --migrate | |
### Use the new (Rails 3.0) rake task to seed the storystatus table | |
$ rake -s db:seed | |
{: .bash} | |
## Filtering stories by status | |
{: .bash} | |
::: ./app/controllers/projects_controller.rb | |
@@ -8,6 +8,7 @@ class ProjectsController < ApplicationController | |
@project = find_instance | |
@stories = | |
@project.stories.apply_scopes(:search => [params[:search], :title], | |
+ :status_is => params[:status], | |
:order_by => parse_sort_param(:title, :status)) | |
end | |
{: .diff .ruby .dryml} | |
::: ./app/views/projects/show.dryml | |
@@ -1,6 +1,11 @@ | |
<show-page> | |
<collection: replace> | |
<table-plus with="&@stories" fields="this, tasks.count, status"> | |
+ <prepend-header:> | |
+ <div class="filter"> | |
+ Display by status: <filter-menu param-name="status" options="&StoryStatus.all"/> | |
+ </div> | |
+ </prepend-header:> | |
<empty-message:>No stories match your criteria</empty-message:> | |
</table-plus> | |
</collection:> | |
{: .diff .ruby .dryml} | |
::: ./public/stylesheets/application.css | |
@@ -0,0 +1,2 @@ | |
+.show-page.project .filter {float: left;} | |
+.show-page.project .filter form, .show-page.project .filter form div {display: inline;} | |
{: .diff .ruby .dryml} | |
{: .bash} | |
## Add Acts as List plugin | |
$ ./script/plugin install acts_as_list | |
{: .bash} | |
::: ./app/models/story.rb | |
@@ -11,7 +11,7 @@ class Story < ActiveRecord::Base | |
belongs_to :project | |
belongs_to :status, :class_name => "StoryStatus" | |
- has_many :tasks, :dependent => :destroy | |
+ has_many :tasks, :dependent => :destroy, :order => :position | |
# --- Permissions --- # | |
{: .diff .ruby .dryml} | |
::: ./app/models/task.rb | |
@@ -9,6 +9,9 @@ class Task < ActiveRecord::Base | |
belongs_to :story | |
+ acts_as_list :scope => :story | |
+ attr_protected :position | |
+ | |
has_many :task_assignments, :dependent => :destroy | |
has_many :users, :through => :task_assignments, :accessible => true | |
{: .diff .ruby .dryml} | |
::: ./app/views/tasks/edit.dryml | |
new file mode 100644 | |
@@ -0,0 +1,5 @@ | |
+<edit-page> | |
+ <form:> | |
+ <cancel: with="&this.story"/> | |
+ </form:> | |
+</edit-page> | |
{: .diff .ruby .dryml} | |
### Run the Hobo Migrator | |
$ ./script/generate hobo_migration acts_as_list --default-name --migrate | |
{: .bash} | |
## Markdown / Textile formatting of stories | |
{: .bash} | |
::: ./app/models/story.rb | |
@@ -4,7 +4,7 @@ class Story < ActiveRecord::Base | |
fields do | |
title :string | |
- body :text | |
+ body :markdown | |
timestamps | |
end | |
{: .diff .ruby .dryml} | |
::: ./config/environment.rb | |
@@ -9,6 +9,8 @@ require File.join(File.dirname(__FILE__), 'boot') | |
Rails::Initializer.run do |config| | |
config.gem 'hobo' | |
+ config.gem 'bluecloth' | |
+ | |
# Settings in config/environments/* take precedence over those specified here. | |
# Application configuration should go into files in config/initializers | |
# -- all .rb files in that directory are automatically loaded. | |
{: .diff .ruby .dryml} | |
$ rake -s gems:install | |
## Front page touch up. | |
{: .bash} | |
::: ./app/views/front/index.dryml | |
@@ -13,7 +13,9 @@ | |
</section> | |
</header> | |
- <section class="content-body"> | |
+ <section class="content-body" if="&logged_in?"> | |
+ <h3>Your Projects</h3> | |
+ <collection:projects with="¤t_user"><card without-creator-link/></collection> | |
</section> | |
</content:> | |
{: .diff .ruby .dryml} | |
# Project ownership | |
{: .bash} | |
::: ./app/models/project.rb | |
@@ -9,18 +9,20 @@ class Project < ActiveRecord::Base | |
has_many :stories, :dependent => :destroy | |
+ belongs_to :owner, :class_name => "User", :creator => true | |
+ | |
# --- Permissions --- # | |
def create_permitted? | |
- acting_user.administrator? | |
+ owner_is? acting_user | |
end | |
def update_permitted? | |
- acting_user.administrator? | |
+ acting_user.administrator? || (owner_is?(acting_user) && !owner_changed?) | |
end | |
def destroy_permitted? | |
- acting_user.administrator? | |
+ acting_user.administrator? || owner_is?(acting_user) | |
end | |
def view_permitted?(field) | |
{: .diff .ruby .dryml} | |
::: ./app/models/user.rb | |
@@ -11,6 +11,7 @@ class User < ActiveRecord::Base | |
has_many :task_assignments, :dependent => :destroy | |
has_many :tasks, :through => :task_assignments | |
+ has_many :projects, :class_name => "Project", :foreign_key => "owner_id" | |
# This gives admin rights to the first sign-up. | |
# Just remove it if you don't want that | |
{: .diff .ruby .dryml} | |
### Project Ownership - migration | |
$ ./script/generate hobo_migration project_ownership --default-name --migrate | |
{: .bash} | |
## Granting read access to others | |
$ ./script/generate hobo_model_resource project_membership | |
{: .bash} | |
## Project Membership - association/action | |
{: .bash} | |
::: ./app/controllers/project_memberships_controller.rb | |
@@ -2,6 +2,6 @@ class ProjectMembershipsController < ApplicationController | |
hobo_model_controller | |
- auto_actions :all | |
+ auto_actions :write_only | |
end | |
{: .diff .ruby .dryml} | |
::: ./app/models/project_membership.rb | |
@@ -6,6 +6,8 @@ class ProjectMembership < ActiveRecord::Base | |
timestamps | |
end | |
+ belongs_to :project | |
+ belongs_to :user | |
# --- Permissions --- # | |
{: .diff .ruby .dryml} | |
### Project Membership migration | |
$ ./script/generate hobo_migration project_memberships --default-name --migrate | |
{: .bash} | |
## Project Membership associations/actions/permissions | |
{: .bash} | |
::: ./app/controllers/projects_controller.rb | |
@@ -2,7 +2,9 @@ class ProjectsController < ApplicationController | |
hobo_model_controller | |
- auto_actions :all | |
+ auto_actions :show, :edit, :update, :destroy | |
+ | |
+ auto_actions_for :owner, [:new, :create] | |
def show | |
@project = find_instance | |
{: .diff .ruby .dryml} | |
::: ./app/models/project.rb | |
@@ -8,6 +8,8 @@ class Project < ActiveRecord::Base | |
end | |
has_many :stories, :dependent => :destroy | |
+ has_many :memberships, :class_name => "ProjectMembership", :dependent => :destroy | |
+ has_many :members, :through => :memberships, :source => :user | |
belongs_to :owner, :class_name => "User", :creator => true | |
@@ -26,7 +28,7 @@ class Project < ActiveRecord::Base | |
end | |
def view_permitted?(field) | |
- true | |
+ acting_user.administrator? || acting_user == owner || acting_user.in?(members) | |
end | |
end | |
{: .diff .ruby .dryml} | |
::: ./app/models/project_membership.rb | |
@@ -12,15 +12,15 @@ class ProjectMembership < ActiveRecord::Base | |
# --- Permissions --- # | |
def create_permitted? | |
- acting_user.administrator? | |
+ acting_user.administrator? || project.owner_is?(acting_user) | |
end | |
def update_permitted? | |
- acting_user.administrator? | |
+ acting_user.administrator? || project.owner_is?(acting_user) | |
end | |
def destroy_permitted? | |
- acting_user.administrator? | |
+ acting_user.administrator? || project.owner_is?(acting_user) | |
end | |
def view_permitted?(field) | |
{: .diff .ruby .dryml} | |
::: ./app/models/story.rb | |
@@ -28,7 +28,7 @@ class Story < ActiveRecord::Base | |
end | |
def view_permitted?(field) | |
- true | |
+ project.viewable_by?(acting_user) | |
end | |
# force 'new' status at create. | |
{: .diff .ruby .dryml} | |
::: ./app/models/task.rb | |
@@ -30,7 +30,7 @@ class Task < ActiveRecord::Base | |
end | |
def view_permitted?(field) | |
- true | |
+ story.viewable_by?(acting_user) | |
end | |
end | |
{: .diff .ruby .dryml} | |
::: ./app/models/user.rb | |
@@ -12,6 +12,8 @@ class User < ActiveRecord::Base | |
has_many :task_assignments, :dependent => :destroy | |
has_many :tasks, :through => :task_assignments | |
has_many :projects, :class_name => "Project", :foreign_key => "owner_id" | |
+ has_many :project_memberships, :dependent => :destroy | |
+ has_many :joined_projects, :through => :project_memberships, :source => :project | |
# This gives admin rights to the first sign-up. | |
# Just remove it if you don't want that | |
{: .diff .ruby .dryml} | |
## Project Contributor associations/actions/permissions | |
{: .bash} | |
::: ./app/controllers/projects_controller.rb | |
@@ -6,6 +6,11 @@ class ProjectsController < ApplicationController | |
auto_actions_for :owner, [:new, :create] | |
+ autocomplete :new_member_name do | |
+ project = find_instance | |
+ hobo_completions :name, User.without_project(project).is_not(project.owner) | |
+ end | |
+ | |
def show | |
@project = find_instance | |
@stories = | |
{: .diff .ruby .dryml} | |
::: ./app/models/project.rb | |
@@ -13,6 +13,14 @@ class Project < ActiveRecord::Base | |
belongs_to :owner, :class_name => "User", :creator => true | |
+ has_many :contributor_memberships, :class_name => "ProjectMembership", :scope => :contributor | |
+ has_many :contributors, :through => :contributor_memberships, :source => :user | |
+ | |
+ # permission helper | |
+ def accepts_changes_from?(user) | |
+ user.administrator? || user == owner || user.in?(contributors) | |
+ end | |
+ | |
# --- Permissions --- # | |
def create_permitted? | |
@@ -20,7 +28,7 @@ class Project < ActiveRecord::Base | |
end | |
def update_permitted? | |
- acting_user.administrator? || (owner_is?(acting_user) && !owner_changed?) | |
+ accepts_changes_from?(acting_user) && !owner_changed? | |
end | |
def destroy_permitted? | |
{: .diff .ruby .dryml} | |
::: ./app/models/project_membership.rb | |
@@ -3,6 +3,7 @@ class ProjectMembership < ActiveRecord::Base | |
hobo_model # Don't put anything above this | |
fields do | |
+ contributor :boolean, :default => false | |
timestamps | |
end | |
{: .diff .ruby .dryml} | |
::: ./app/models/story.rb | |
@@ -16,15 +16,15 @@ class Story < ActiveRecord::Base | |
# --- Permissions --- # | |
def create_permitted? | |
- acting_user.administrator? | |
+ project.creatable_by?(acting_user) | |
end | |
def update_permitted? | |
- acting_user.signed_up? && !project_changed? | |
+ project.updatable_by?(acting_user) | |
end | |
def destroy_permitted? | |
- acting_user.administrator? | |
+ project.destroyable_by?(acting_user) | |
end | |
def view_permitted?(field) | |
{: .diff .ruby .dryml} | |
::: ./app/models/task.rb | |
@@ -18,15 +18,15 @@ class Task < ActiveRecord::Base | |
# --- Permissions --- # | |
def create_permitted? | |
- acting_user.administrator? | |
+ story.creatable_by?(acting_user) | |
end | |
def update_permitted? | |
- acting_user.signed_up? && !story_changed? | |
+ story.updatable_by?(acting_user) | |
end | |
def destroy_permitted? | |
- acting_user.administrator? | |
+ story.destroyable_by?(acting_user) | |
end | |
def view_permitted?(field) | |
{: .diff .ruby .dryml} | |
::: ./app/models/task_assignment.rb | |
@@ -12,19 +12,19 @@ class TaskAssignment < ActiveRecord::Base | |
# --- Permissions --- # | |
def create_permitted? | |
- acting_user.administrator? | |
+ task.creatable_by?(acting_user) | |
end | |
def update_permitted? | |
- acting_user.administrator? | |
+ task.updatable_by?(acting_user) | |
end | |
def destroy_permitted? | |
- acting_user.administrator? | |
+ task.destroyable_by?(acting_user) | |
end | |
def view_permitted?(field) | |
- true | |
+ task.viewable_by?(acting_user) | |
end | |
end | |
{: .diff .ruby .dryml} | |
::: ./app/viewhints/project_hints.rb | |
@@ -1,4 +1,3 @@ | |
class ProjectHints < Hobo::ViewHints | |
- | |
- | |
+ children :stories, :memberships | |
end | |
{: .diff .ruby .dryml} | |
### Project Contributor migration | |
$ ./script/generate hobo_migration project_contributorships --default-name --migrate | |
{: .bash} | |
## Project Contributor view layer | |
{: .bash} | |
::: ./app/views/front/index.dryml | |
@@ -13,9 +13,14 @@ | |
</section> | |
</header> | |
- <section class="content-body" if="&logged_in?"> | |
+ <section with="¤t_user" class="content-body" if="&logged_in?"> | |
<h3>Your Projects</h3> | |
- <collection:projects with="¤t_user"><card without-creator-link/></collection> | |
+ <collection:projects><card without-creator-link/></collection> | |
+ | |
+ <a:projects action="new">New Project</a> | |
+ | |
+ <h3>Projects you have joined</h3> | |
+ <collection:joined-projects><card without-creator-link/></collection> | |
</section> | |
</content:> | |
{: .diff .ruby .dryml} | |
::: ./app/views/projects/show.dryml | |
@@ -9,4 +9,19 @@ | |
<empty-message:>No stories match your criteria</empty-message:> | |
</table-plus> | |
</collection:> | |
+ | |
+ <aside:> | |
+ <h2>Project Members</h2> | |
+ <collection:memberships part="members"> | |
+ <card><heading:><a:user/></heading:></card> | |
+ </collection> | |
+ | |
+ <form:memberships.new update="members" reset-form refocus-form> | |
+ <div> | |
+ Add a member: | |
+ <name-one:user complete-target="&@project" completer="new_member_name"/> | |
+ </div> | |
+ </form> | |
+ </aside:> | |
+ | |
</show-page> | |
{: .diff .ruby .dryml} | |
::: ./app/views/taglibs/application.dryml | |
@@ -17,3 +17,13 @@ | |
</append-body:> | |
</old-card> | |
</extend> | |
+ | |
+<extend tag="card" for="ProjectMembership"> | |
+ <old-card merge> | |
+ <body:> | |
+ <span>Contributor?</span> | |
+ <editor:contributor/> | |
+ </body:> | |
+ </old-card> | |
+</extend> | |
+ | |
{: .diff .ruby .dryml} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment