simple_teams 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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 %>