simple_teams 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (98) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +28 -0
  4. data/Rakefile +8 -0
  5. data/app/assets/config/simple_teams_manifest.js +1 -0
  6. data/app/assets/stylesheets/simple_teams/application.css +15 -0
  7. data/app/controllers/simple_teams/accept_invitations_controller.rb +57 -0
  8. data/app/controllers/simple_teams/admin/invitations_controller.rb +60 -0
  9. data/app/controllers/simple_teams/admin/memberships_controller.rb +60 -0
  10. data/app/controllers/simple_teams/admin/teams_controller.rb +60 -0
  11. data/app/controllers/simple_teams/application_controller.rb +13 -0
  12. data/app/controllers/simple_teams/invitations_controller.rb +96 -0
  13. data/app/controllers/simple_teams/leave_teams_controller.rb +25 -0
  14. data/app/controllers/simple_teams/memberships_controller.rb +61 -0
  15. data/app/controllers/simple_teams/related_members_controller.rb +33 -0
  16. data/app/controllers/simple_teams/teams_controller.rb +19 -0
  17. data/app/forms/simple_teams/invitation_form.rb +77 -0
  18. data/app/forms/simple_teams/invitation_forms/create.rb +24 -0
  19. data/app/forms/simple_teams/invitation_forms/create_bulk.rb +125 -0
  20. data/app/forms/simple_teams/invitation_forms/create_combo.rb +75 -0
  21. data/app/forms/simple_teams/invitation_forms/update.rb +29 -0
  22. data/app/forms/simple_teams/membership_form.rb +91 -0
  23. data/app/helpers/simple_teams/application_helper.rb +4 -0
  24. data/app/helpers/simple_teams/invitations_helper.rb +4 -0
  25. data/app/helpers/simple_teams/memberships_helper.rb +4 -0
  26. data/app/helpers/simple_teams/teams_helper.rb +4 -0
  27. data/app/jobs/simple_teams/application_job.rb +4 -0
  28. data/app/mailers/simple_teams/application_mailer.rb +6 -0
  29. data/app/mailers/simple_teams/mailer.rb +17 -0
  30. data/app/models/concerns/simple_teams/member_object.rb +22 -0
  31. data/app/models/concerns/simple_teams/team_object.rb +23 -0
  32. data/app/models/simple_teams/ability.rb +34 -0
  33. data/app/models/simple_teams/application_record.rb +5 -0
  34. data/app/models/simple_teams/invitation.rb +85 -0
  35. data/app/models/simple_teams/membership.rb +16 -0
  36. data/app/models/simple_teams/team.rb +23 -0
  37. data/app/notifications/application_notification.rb +4 -0
  38. data/app/notifications/simple_teams/bulk_invitations_notification.rb +51 -0
  39. data/app/notifications/simple_teams/invitation_notification.rb +54 -0
  40. data/app/notifications/simple_teams/invitations/accepted_notification.rb +13 -0
  41. data/app/notifications/simple_teams/invitations/created_notification.rb +13 -0
  42. data/app/notifications/simple_teams/invitations/destroyed_notification.rb +13 -0
  43. data/app/notifications/simple_teams/invitations/updated_notification.rb +13 -0
  44. data/app/notifications/simple_teams/membership_notification.rb +58 -0
  45. data/app/notifications/simple_teams/memberships/destroyed_notification.rb +13 -0
  46. data/app/notifications/simple_teams/memberships/left_notification.rb +17 -0
  47. data/app/notifications/simple_teams/memberships/updated_notification.rb +17 -0
  48. data/app/service_objects/simple_teams/accept_invitation_service.rb +61 -0
  49. data/app/service_objects/simple_teams/initialize_team_service.rb +25 -0
  50. data/app/service_objects/simple_teams/leave_team_service.rb +56 -0
  51. data/app/views/layouts/simple_teams/application.html.erb +20 -0
  52. data/app/views/simple_teams/_roles_field.html.erb +22 -0
  53. data/app/views/simple_teams/accept_invitations/invalid_token.html.erb +7 -0
  54. data/app/views/simple_teams/accept_invitations/new.html.erb +18 -0
  55. data/app/views/simple_teams/admin/invitations/_form.html.erb +62 -0
  56. data/app/views/simple_teams/admin/invitations/_invitation.html.erb +47 -0
  57. data/app/views/simple_teams/admin/invitations/edit.html.erb +10 -0
  58. data/app/views/simple_teams/admin/invitations/index.html.erb +14 -0
  59. data/app/views/simple_teams/admin/invitations/new.html.erb +9 -0
  60. data/app/views/simple_teams/admin/invitations/show.html.erb +10 -0
  61. data/app/views/simple_teams/admin/memberships/_form.html.erb +32 -0
  62. data/app/views/simple_teams/admin/memberships/_membership.html.erb +17 -0
  63. data/app/views/simple_teams/admin/memberships/edit.html.erb +10 -0
  64. data/app/views/simple_teams/admin/memberships/index.html.erb +14 -0
  65. data/app/views/simple_teams/admin/memberships/new.html.erb +9 -0
  66. data/app/views/simple_teams/admin/memberships/show.html.erb +10 -0
  67. data/app/views/simple_teams/admin/teams/_form.html.erb +22 -0
  68. data/app/views/simple_teams/admin/teams/_team.html.erb +7 -0
  69. data/app/views/simple_teams/admin/teams/edit.html.erb +10 -0
  70. data/app/views/simple_teams/admin/teams/index.html.erb +14 -0
  71. data/app/views/simple_teams/admin/teams/new.html.erb +9 -0
  72. data/app/views/simple_teams/admin/teams/show.html.erb +10 -0
  73. data/app/views/simple_teams/invitations/_bulk_form.html.erb +63 -0
  74. data/app/views/simple_teams/invitations/_form.html.erb +15 -0
  75. data/app/views/simple_teams/invitations/_invitation.html.erb +19 -0
  76. data/app/views/simple_teams/invitations/_invitation.json.jbuilder +2 -0
  77. data/app/views/simple_teams/invitations/edit.html.erb +12 -0
  78. data/app/views/simple_teams/invitations/new.html.erb +12 -0
  79. data/app/views/simple_teams/leave_teams/edit.html.erb +2 -0
  80. data/app/views/simple_teams/memberships/_form.html.erb +12 -0
  81. data/app/views/simple_teams/memberships/_membership.html.erb +23 -0
  82. data/app/views/simple_teams/memberships/edit.html.erb +12 -0
  83. data/app/views/simple_teams/related_members/index.json.jbuilder +5 -0
  84. data/app/views/simple_teams/related_members/select2.json.jbuilder +6 -0
  85. data/app/views/simple_teams/teams/_add_member_link.html.erb +3 -0
  86. data/app/views/simple_teams/teams/_members_table.html.erb +20 -0
  87. data/app/views/simple_teams/teams/show.html.erb +38 -0
  88. data/app/views/simple_teams/teams_mailer/invitation_notification.html.erb +9 -0
  89. data/config/locales/simple_teams.en.yml +18 -0
  90. data/config/routes.rb +21 -0
  91. data/db/migrate/20240311052758_create_simple_teams_teams.rb +9 -0
  92. data/db/migrate/20240311053006_create_simple_teams_memberships.rb +11 -0
  93. data/db/migrate/20240311053607_create_simple_teams_invitations.rb +17 -0
  94. data/lib/simple_teams/engine.rb +22 -0
  95. data/lib/simple_teams/version.rb +3 -0
  96. data/lib/simple_teams.rb +6 -0
  97. data/lib/tasks/simple_teams_tasks.rake +4 -0
  98. metadata +160 -0
@@ -0,0 +1,54 @@
1
+ module SimpleTeams
2
+ class InvitationNotification < ApplicationNotification
3
+ param :team_id, :invitation_id, :user_id, :team_name, :invitation_name, :user_name
4
+
5
+ def message
6
+ raise NotImplemented
7
+ end
8
+
9
+ def subject
10
+ raise NotImplemented
11
+ end
12
+
13
+ def url
14
+ if team.present? and team.members.include? recipient
15
+ "/teams/#{team.id}"
16
+ end
17
+ end
18
+
19
+ def link_text
20
+ "View Invitations"
21
+ end
22
+
23
+ # Objects
24
+ def team
25
+ Team.find_by(id: params[:team_id])
26
+ end
27
+
28
+ def user
29
+ SimpleTeams.member_class.find_by(id: params[:user_id])
30
+ end
31
+
32
+ def invitation
33
+ team.invitations.find_by(id: params[:invitation_id]) if team.present?
34
+ end
35
+
36
+ # Names (fallback)
37
+ def team_name
38
+ team.present? ? team.name : params[:team_name]
39
+ end
40
+
41
+ def invitation_name
42
+ invitation.present? ? invitation.email : params[:invitation_name]
43
+ end
44
+
45
+ def user_name
46
+ if recipient.id == params[:user_id]
47
+ "You"
48
+ else
49
+ user.present? ? user.full_name : params[:user_name]
50
+ end
51
+ end
52
+
53
+ end
54
+ end
@@ -0,0 +1,13 @@
1
+ module SimpleTeams
2
+ class Invitations::AcceptedNotification < SimpleTeams::InvitationNotification
3
+
4
+ def message
5
+ "#{user_name} accepted the invitation to #{team_name}."
6
+ end
7
+
8
+ def subject
9
+ "Invitation Accepted"
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module SimpleTeams
2
+ class Invitations::CreatedNotification < SimpleTeams::InvitationNotification
3
+
4
+ def message
5
+ "#{user_name} invited #{invitation_name} to #{team_name}."
6
+ end
7
+
8
+ def subject
9
+ "User Invited"
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module SimpleTeams
2
+ class Invitations::DestroyedNotification < SimpleTeams::InvitationNotification
3
+
4
+ def message
5
+ "#{user_name} deleted the invitation for #{invitation_name} to #{team_name}."
6
+ end
7
+
8
+ def subject
9
+ "Invitation Deleted"
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module SimpleTeams
2
+ class Invitations::UpdatedNotification < SimpleTeams::InvitationNotification
3
+
4
+ def message
5
+ "#{user_name} updated the invitation for #{invitation_name} to #{team_name}."
6
+ end
7
+
8
+ def subject
9
+ "Invitation Updated"
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,58 @@
1
+ module SimpleTeams
2
+ class MembershipNotification < ApplicationNotification
3
+ param :team_id, :member_id, :user_id, :team_name, :member_name, :user_name
4
+
5
+ def message
6
+ raise NotImplemented
7
+ end
8
+
9
+ def subject
10
+ raise NotImplemented
11
+ end
12
+
13
+ def url
14
+ if team.present? and team.members.include? recipient
15
+ "/teams/#{team.id}"
16
+ end
17
+ end
18
+
19
+ def link_text
20
+ "View Permissions"
21
+ end
22
+
23
+ # Objects
24
+ def team
25
+ Team.find_by(id: params[:team_id])
26
+ end
27
+
28
+ def user
29
+ SimpleTeams.member_class.find_by(id: params[:user_id])
30
+ end
31
+
32
+ def member
33
+ team.members.find_by(id: params[:member_id]) if team.present?
34
+ end
35
+
36
+ # Names (fallback)
37
+ def team_name
38
+ team.present? ? team.name : params[:team_name]
39
+ end
40
+
41
+ def member_name
42
+ if recipient.id == params[:member_id]
43
+ "you"
44
+ else
45
+ member.present? ? member.full_name : params[:member_name]
46
+ end
47
+ end
48
+
49
+ def user_name
50
+ if recipient.id == params[:user_id]
51
+ "You"
52
+ else
53
+ user.present? ? user.full_name : params[:user_name]
54
+ end
55
+ end
56
+
57
+ end
58
+ end
@@ -0,0 +1,13 @@
1
+ module SimpleTeams
2
+ class Memberships::DestroyedNotification < SimpleTeams::MembershipNotification
3
+
4
+ def message
5
+ "#{user_name} removed #{member_name} from #{team_name}."
6
+ end
7
+
8
+ def subject
9
+ "Member Removed"
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,17 @@
1
+ module SimpleTeams
2
+ class Memberships::LeftNotification < SimpleTeams::MembershipNotification
3
+
4
+ def message
5
+ if recipient.id == params[:member_id]
6
+ "You left #{team_name}."
7
+ else
8
+ "#{member_name} left #{team_name}."
9
+ end
10
+ end
11
+
12
+ def subject
13
+ "Member Left"
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ module SimpleTeams
2
+ class Memberships::UpdatedNotification < SimpleTeams::MembershipNotification
3
+
4
+ def message
5
+ if recipient.id == params[:member_id]
6
+ "#{user_name} updated your role for #{team_name}."
7
+ else
8
+ "#{user_name} updated the role of #{member_name} for #{team_name}."
9
+ end
10
+ end
11
+
12
+ def subject
13
+ "Member Updated"
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,61 @@
1
+ module SimpleTeams
2
+ class AcceptInvitationService
3
+ include ActiveModel::Model
4
+
5
+ attr_accessor :user_id, :invitation_token
6
+
7
+ def initialize(user_id, invitation_token)
8
+ @user_id = user_id
9
+ @invitation_token = invitation_token
10
+ end
11
+
12
+ def valid?
13
+ self.errors.clear
14
+ validate_invitation_token
15
+ validate_user_not_a_member
16
+ !self.errors.any?
17
+ end
18
+
19
+ def perform
20
+ ActiveRecord::Base.transaction do
21
+ membership = team.memberships.create!(
22
+ :member => user,
23
+ :role => invitation.role
24
+ )
25
+ invitation.update!(membership: membership)
26
+ invitation.accepted!
27
+ end
28
+ end
29
+
30
+ def user
31
+ @user ||= SimpleTeams.member_class.find(user_id)
32
+ end
33
+
34
+ def invitation
35
+ @invitation ||= Teams::Invitation.find_by(token: @invitation_token)
36
+ end
37
+
38
+ private
39
+
40
+ def team
41
+ invitation.team
42
+ end
43
+
44
+ def validate_invitation_token
45
+ if invitation.blank?
46
+ self.errors.add(:invitation_token, "That invitation token is not valid.")
47
+ elsif !invitation.initial?
48
+ self.errors.add(:invitation_token, "That invitation token has already been used. If you believe this is in error, please contact the team administrator to send you a new invitation.")
49
+ elsif invitation.expired?
50
+ self.errors.add(:invitation_token, "That invitation token is expired. Please contact the team administrator to resend your invitation.")
51
+ end
52
+ end
53
+
54
+ def validate_user_not_a_member
55
+ if user.teams.include? invitation.team
56
+ self.errors.add(:user_id, "You are already a member of this team.")
57
+ end
58
+ end
59
+
60
+ end
61
+ end
@@ -0,0 +1,25 @@
1
+ module SimpleTeams
2
+ class InitializeTeamService
3
+
4
+ attr_accessor :user, :team
5
+
6
+ def initialize(user, team)
7
+ @user = user
8
+ @team = team
9
+ end
10
+
11
+ def valid?
12
+ !user.teams.include? team
13
+ end
14
+
15
+ def perform
16
+ ActiveRecord::Base.transaction do
17
+ team.memberships.create(
18
+ :member => user,
19
+ :role => :owner
20
+ )
21
+ end
22
+ end
23
+
24
+ end
25
+ end
@@ -0,0 +1,56 @@
1
+ module SimpleTeams
2
+ class LeaveTeamService
3
+ include ActiveModel::Model
4
+
5
+ attr_accessor :user_id, :team_id
6
+
7
+ def initialize(user_id, team_id)
8
+ @user_id = user_id
9
+ @team_id = team_id
10
+ end
11
+
12
+ def valid?
13
+ self.errors.clear
14
+ validate_not_last_owner
15
+ !self.errors.any?
16
+ end
17
+
18
+ def perform
19
+ membership.destroy
20
+ generate_notification
21
+ end
22
+
23
+ def user
24
+ @user ||= SimpleTeams.member_class.find(user_id)
25
+ end
26
+
27
+ def team
28
+ @team ||= SimpleTeams::Team.find(team_id)
29
+ end
30
+
31
+ def membership
32
+ @membership ||= user.membership_for_team(team)
33
+ end
34
+
35
+ private
36
+
37
+ def validate_not_last_owner
38
+ if membership.owner? and team.memberships.where(:role => :owner).count == 1
39
+ self.errors.add(:user_id, "You must specify at least one other owner before leaving this #{team.teamable.class.model_name.human}.")
40
+ end
41
+ end
42
+
43
+ def generate_notification
44
+ recipients = team.members.to_a << user
45
+ SimpleTeams::Memberships::LeftNotification.with(
46
+ :team_id => team.id,
47
+ :member_id => user.id,
48
+ :user_id => user.id,
49
+ :team_name => team.name,
50
+ :member_name => user.full_name,
51
+ :user_name => user.full_name
52
+ ).deliver_later(recipients)
53
+ end
54
+
55
+ end
56
+ end
@@ -0,0 +1,20 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Simple teams</title>
5
+ <%= csrf_meta_tags %>
6
+ <%= csp_meta_tag %>
7
+
8
+ <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
9
+ <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
10
+
11
+ <%= stylesheet_link_tag "simple_teams/application", media: "all" %>
12
+ </head>
13
+ <body>
14
+
15
+ <div class="container">
16
+ <%= yield %>
17
+ </div>
18
+
19
+ </body>
20
+ </html>
@@ -0,0 +1,22 @@
1
+ <fieldset class="form-check-collection mt-4">
2
+ <legend class="h3">Role</legend>
3
+ <% @service_object.available_roles.each do |name, id| %>
4
+ <div class="card mb-3">
5
+ <div class="card-body">
6
+ <div class="form-check">
7
+ <%= radio_button_tag "#{prefix}[role]", name, [name].include?(f.object.role), :class => "form-check-input" %>
8
+ <%= label_tag "#{prefix}_role_#{name}", :class => "form-check-label w-100" do %>
9
+ <div class="">
10
+ <div class="col"><b><%= name.capitalize %></b></div>
11
+ <div class="col"><%= t "simple_teams.roles.#{name}" %></div>
12
+ </div>
13
+ <% end %>
14
+ </div>
15
+ </div>
16
+ </div>
17
+ <% end %>
18
+ </fieldset>
19
+
20
+ <% if f.object.errors[:role].present? %>
21
+ <div class="invalid-feedback d-block"><%= f.object.errors[:role].to_sentence %></div>
22
+ <% end %>
@@ -0,0 +1,7 @@
1
+ <div class="row">
2
+ <div class="col-md-8 offset-md-2 col-lg-6 offset-lg-3">
3
+ <h1>Invitation Token Invalid</h1>
4
+
5
+ <p>That invitation token is invalid, or has already been used.</p>
6
+ </div>
7
+ </div>
@@ -0,0 +1,18 @@
1
+ <div class="centered-content-template">
2
+ <% if @invitation.initial? %>
3
+ <h1>Accept Invitation: <%= @invitation.team.name %></h1>
4
+
5
+ <p class="lead"><%= @invitation.inviter.full_name %> has invited you to the '<%= @invitation.team.name %>' <%= @invitation.team.teamable.class.model_name.human %>.</p>
6
+
7
+ <%= simple_form_for @service_object, :url => accept_team_invitation_path(@invitation.token) do |f| %>
8
+
9
+ <%= f.submit "Accept", :class => "btn btn-primary" %>
10
+ <%= f.submit "Decline", :class => "btn btn-danger" %>
11
+
12
+ <% end %>
13
+ <% else %>
14
+ <h1>Invitation Token</h1>
15
+
16
+ <p>This invitation token has already been used.</p>
17
+ <% end %>
18
+ </div>
@@ -0,0 +1,62 @@
1
+ <%= form_with(model: invitation) do |form| %>
2
+ <% if invitation.errors.any? %>
3
+ <div style="color: red">
4
+ <h2><%= pluralize(invitation.errors.count, "error") %> prohibited this invitation from being saved:</h2>
5
+
6
+ <ul>
7
+ <% invitation.errors.each do |error| %>
8
+ <li><%= error.full_message %></li>
9
+ <% end %>
10
+ </ul>
11
+ </div>
12
+ <% end %>
13
+
14
+ <div>
15
+ <%= form.label :team_id, style: "display: block" %>
16
+ <%= form.text_field :team_id %>
17
+ </div>
18
+
19
+ <div>
20
+ <%= form.label :inviter_id, style: "display: block" %>
21
+ <%= form.text_field :inviter_id %>
22
+ </div>
23
+
24
+ <div>
25
+ <%= form.label :membership_id, style: "display: block" %>
26
+ <%= form.text_field :membership_id %>
27
+ </div>
28
+
29
+ <div>
30
+ <%= form.label :email, style: "display: block" %>
31
+ <%= form.text_field :email %>
32
+ </div>
33
+
34
+ <div>
35
+ <%= form.label :role, style: "display: block" %>
36
+ <%= form.text_field :role %>
37
+ </div>
38
+
39
+ <div>
40
+ <%= form.label :token, style: "display: block" %>
41
+ <%= form.text_field :token %>
42
+ </div>
43
+
44
+ <div>
45
+ <%= form.label :status, style: "display: block" %>
46
+ <%= form.number_field :status %>
47
+ </div>
48
+
49
+ <div>
50
+ <%= form.label :sent_at, style: "display: block" %>
51
+ <%= form.datetime_field :sent_at %>
52
+ </div>
53
+
54
+ <div>
55
+ <%= form.label :expires_at, style: "display: block" %>
56
+ <%= form.datetime_field :expires_at %>
57
+ </div>
58
+
59
+ <div>
60
+ <%= form.submit %>
61
+ </div>
62
+ <% end %>
@@ -0,0 +1,47 @@
1
+ <div id="<%= dom_id invitation %>">
2
+ <p>
3
+ <strong>Team:</strong>
4
+ <%= invitation.team_id %>
5
+ </p>
6
+
7
+ <p>
8
+ <strong>Inviter:</strong>
9
+ <%= invitation.inviter_id %>
10
+ </p>
11
+
12
+ <p>
13
+ <strong>Membership:</strong>
14
+ <%= invitation.membership_id %>
15
+ </p>
16
+
17
+ <p>
18
+ <strong>Email:</strong>
19
+ <%= invitation.email %>
20
+ </p>
21
+
22
+ <p>
23
+ <strong>Role:</strong>
24
+ <%= invitation.role %>
25
+ </p>
26
+
27
+ <p>
28
+ <strong>Token:</strong>
29
+ <%= invitation.token %>
30
+ </p>
31
+
32
+ <p>
33
+ <strong>Status:</strong>
34
+ <%= invitation.status %>
35
+ </p>
36
+
37
+ <p>
38
+ <strong>Sent at:</strong>
39
+ <%= invitation.sent_at %>
40
+ </p>
41
+
42
+ <p>
43
+ <strong>Expires at:</strong>
44
+ <%= invitation.expires_at %>
45
+ </p>
46
+
47
+ </div>
@@ -0,0 +1,10 @@
1
+ <h1>Editing invitation</h1>
2
+
3
+ <%= render "form", invitation: @invitation %>
4
+
5
+ <br>
6
+
7
+ <div>
8
+ <%= link_to "Show this invitation", @invitation %> |
9
+ <%= link_to "Back to invitations", invitations_path %>
10
+ </div>
@@ -0,0 +1,14 @@
1
+ <p style="color: green"><%= notice %></p>
2
+
3
+ <h1>Invitations</h1>
4
+
5
+ <div id="invitations">
6
+ <% @invitations.each do |invitation| %>
7
+ <%= render invitation %>
8
+ <p>
9
+ <%= link_to "Show this invitation", invitation %>
10
+ </p>
11
+ <% end %>
12
+ </div>
13
+
14
+ <%= link_to "New invitation", new_invitation_path %>
@@ -0,0 +1,9 @@
1
+ <h1>New invitation</h1>
2
+
3
+ <%= render "form", invitation: @invitation %>
4
+
5
+ <br>
6
+
7
+ <div>
8
+ <%= link_to "Back to invitations", invitations_path %>
9
+ </div>
@@ -0,0 +1,10 @@
1
+ <p style="color: green"><%= notice %></p>
2
+
3
+ <%= render @invitation %>
4
+
5
+ <div>
6
+ <%= link_to "Edit this invitation", edit_invitation_path(@invitation) %> |
7
+ <%= link_to "Back to invitations", invitations_path %>
8
+
9
+ <%= button_to "Destroy this invitation", @invitation, method: :delete %>
10
+ </div>
@@ -0,0 +1,32 @@
1
+ <%= form_with(model: membership) do |form| %>
2
+ <% if membership.errors.any? %>
3
+ <div style="color: red">
4
+ <h2><%= pluralize(membership.errors.count, "error") %> prohibited this membership from being saved:</h2>
5
+
6
+ <ul>
7
+ <% membership.errors.each do |error| %>
8
+ <li><%= error.full_message %></li>
9
+ <% end %>
10
+ </ul>
11
+ </div>
12
+ <% end %>
13
+
14
+ <div>
15
+ <%= form.label :team_id, style: "display: block" %>
16
+ <%= form.text_field :team_id %>
17
+ </div>
18
+
19
+ <div>
20
+ <%= form.label :member_id, style: "display: block" %>
21
+ <%= form.text_field :member_id %>
22
+ </div>
23
+
24
+ <div>
25
+ <%= form.label :role, style: "display: block" %>
26
+ <%= form.number_field :role %>
27
+ </div>
28
+
29
+ <div>
30
+ <%= form.submit %>
31
+ </div>
32
+ <% end %>
@@ -0,0 +1,17 @@
1
+ <div id="<%= dom_id membership %>">
2
+ <p>
3
+ <strong>Team:</strong>
4
+ <%= membership.team_id %>
5
+ </p>
6
+
7
+ <p>
8
+ <strong>Member:</strong>
9
+ <%= membership.member_id %>
10
+ </p>
11
+
12
+ <p>
13
+ <strong>Role:</strong>
14
+ <%= membership.role %>
15
+ </p>
16
+
17
+ </div>
@@ -0,0 +1,10 @@
1
+ <h1>Editing membership</h1>
2
+
3
+ <%= render "form", membership: @membership %>
4
+
5
+ <br>
6
+
7
+ <div>
8
+ <%= link_to "Show this membership", @membership %> |
9
+ <%= link_to "Back to memberships", memberships_path %>
10
+ </div>
@@ -0,0 +1,14 @@
1
+ <p style="color: green"><%= notice %></p>
2
+
3
+ <h1>Memberships</h1>
4
+
5
+ <div id="memberships">
6
+ <% @memberships.each do |membership| %>
7
+ <%= render membership %>
8
+ <p>
9
+ <%= link_to "Show this membership", membership %>
10
+ </p>
11
+ <% end %>
12
+ </div>
13
+
14
+ <%= link_to "New membership", new_membership_path %>