simple_teams 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +28 -0
- data/Rakefile +8 -0
- data/app/assets/config/simple_teams_manifest.js +1 -0
- data/app/assets/stylesheets/simple_teams/application.css +15 -0
- data/app/controllers/simple_teams/accept_invitations_controller.rb +57 -0
- data/app/controllers/simple_teams/admin/invitations_controller.rb +60 -0
- data/app/controllers/simple_teams/admin/memberships_controller.rb +60 -0
- data/app/controllers/simple_teams/admin/teams_controller.rb +60 -0
- data/app/controllers/simple_teams/application_controller.rb +13 -0
- data/app/controllers/simple_teams/invitations_controller.rb +96 -0
- data/app/controllers/simple_teams/leave_teams_controller.rb +25 -0
- data/app/controllers/simple_teams/memberships_controller.rb +61 -0
- data/app/controllers/simple_teams/related_members_controller.rb +33 -0
- data/app/controllers/simple_teams/teams_controller.rb +19 -0
- data/app/forms/simple_teams/invitation_form.rb +77 -0
- data/app/forms/simple_teams/invitation_forms/create.rb +24 -0
- data/app/forms/simple_teams/invitation_forms/create_bulk.rb +125 -0
- data/app/forms/simple_teams/invitation_forms/create_combo.rb +75 -0
- data/app/forms/simple_teams/invitation_forms/update.rb +29 -0
- data/app/forms/simple_teams/membership_form.rb +91 -0
- data/app/helpers/simple_teams/application_helper.rb +4 -0
- data/app/helpers/simple_teams/invitations_helper.rb +4 -0
- data/app/helpers/simple_teams/memberships_helper.rb +4 -0
- data/app/helpers/simple_teams/teams_helper.rb +4 -0
- data/app/jobs/simple_teams/application_job.rb +4 -0
- data/app/mailers/simple_teams/application_mailer.rb +6 -0
- data/app/mailers/simple_teams/mailer.rb +17 -0
- data/app/models/concerns/simple_teams/member_object.rb +22 -0
- data/app/models/concerns/simple_teams/team_object.rb +23 -0
- data/app/models/simple_teams/ability.rb +34 -0
- data/app/models/simple_teams/application_record.rb +5 -0
- data/app/models/simple_teams/invitation.rb +85 -0
- data/app/models/simple_teams/membership.rb +16 -0
- data/app/models/simple_teams/team.rb +23 -0
- data/app/notifications/application_notification.rb +4 -0
- data/app/notifications/simple_teams/bulk_invitations_notification.rb +51 -0
- data/app/notifications/simple_teams/invitation_notification.rb +54 -0
- data/app/notifications/simple_teams/invitations/accepted_notification.rb +13 -0
- data/app/notifications/simple_teams/invitations/created_notification.rb +13 -0
- data/app/notifications/simple_teams/invitations/destroyed_notification.rb +13 -0
- data/app/notifications/simple_teams/invitations/updated_notification.rb +13 -0
- data/app/notifications/simple_teams/membership_notification.rb +58 -0
- data/app/notifications/simple_teams/memberships/destroyed_notification.rb +13 -0
- data/app/notifications/simple_teams/memberships/left_notification.rb +17 -0
- data/app/notifications/simple_teams/memberships/updated_notification.rb +17 -0
- data/app/service_objects/simple_teams/accept_invitation_service.rb +61 -0
- data/app/service_objects/simple_teams/initialize_team_service.rb +25 -0
- data/app/service_objects/simple_teams/leave_team_service.rb +56 -0
- data/app/views/layouts/simple_teams/application.html.erb +20 -0
- data/app/views/simple_teams/_roles_field.html.erb +22 -0
- data/app/views/simple_teams/accept_invitations/invalid_token.html.erb +7 -0
- data/app/views/simple_teams/accept_invitations/new.html.erb +18 -0
- data/app/views/simple_teams/admin/invitations/_form.html.erb +62 -0
- data/app/views/simple_teams/admin/invitations/_invitation.html.erb +47 -0
- data/app/views/simple_teams/admin/invitations/edit.html.erb +10 -0
- data/app/views/simple_teams/admin/invitations/index.html.erb +14 -0
- data/app/views/simple_teams/admin/invitations/new.html.erb +9 -0
- data/app/views/simple_teams/admin/invitations/show.html.erb +10 -0
- data/app/views/simple_teams/admin/memberships/_form.html.erb +32 -0
- data/app/views/simple_teams/admin/memberships/_membership.html.erb +17 -0
- data/app/views/simple_teams/admin/memberships/edit.html.erb +10 -0
- data/app/views/simple_teams/admin/memberships/index.html.erb +14 -0
- data/app/views/simple_teams/admin/memberships/new.html.erb +9 -0
- data/app/views/simple_teams/admin/memberships/show.html.erb +10 -0
- data/app/views/simple_teams/admin/teams/_form.html.erb +22 -0
- data/app/views/simple_teams/admin/teams/_team.html.erb +7 -0
- data/app/views/simple_teams/admin/teams/edit.html.erb +10 -0
- data/app/views/simple_teams/admin/teams/index.html.erb +14 -0
- data/app/views/simple_teams/admin/teams/new.html.erb +9 -0
- data/app/views/simple_teams/admin/teams/show.html.erb +10 -0
- data/app/views/simple_teams/invitations/_bulk_form.html.erb +63 -0
- data/app/views/simple_teams/invitations/_form.html.erb +15 -0
- data/app/views/simple_teams/invitations/_invitation.html.erb +19 -0
- data/app/views/simple_teams/invitations/_invitation.json.jbuilder +2 -0
- data/app/views/simple_teams/invitations/edit.html.erb +12 -0
- data/app/views/simple_teams/invitations/new.html.erb +12 -0
- data/app/views/simple_teams/leave_teams/edit.html.erb +2 -0
- data/app/views/simple_teams/memberships/_form.html.erb +12 -0
- data/app/views/simple_teams/memberships/_membership.html.erb +23 -0
- data/app/views/simple_teams/memberships/edit.html.erb +12 -0
- data/app/views/simple_teams/related_members/index.json.jbuilder +5 -0
- data/app/views/simple_teams/related_members/select2.json.jbuilder +6 -0
- data/app/views/simple_teams/teams/_add_member_link.html.erb +3 -0
- data/app/views/simple_teams/teams/_members_table.html.erb +20 -0
- data/app/views/simple_teams/teams/show.html.erb +38 -0
- data/app/views/simple_teams/teams_mailer/invitation_notification.html.erb +9 -0
- data/config/locales/simple_teams.en.yml +18 -0
- data/config/routes.rb +21 -0
- data/db/migrate/20240311052758_create_simple_teams_teams.rb +9 -0
- data/db/migrate/20240311053006_create_simple_teams_memberships.rb +11 -0
- data/db/migrate/20240311053607_create_simple_teams_invitations.rb +17 -0
- data/lib/simple_teams/engine.rb +22 -0
- data/lib/simple_teams/version.rb +3 -0
- data/lib/simple_teams.rb +6 -0
- data/lib/tasks/simple_teams_tasks.rake +4 -0
- metadata +160 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 7f626da6c44a20f9b042cea11e321034ddaea542c5a96504017c309850d67bdb
|
4
|
+
data.tar.gz: 5c8bc35a2bbd95fc017ce9e427197cc962bb7118096de9675ca8980cfec0d79c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 7012cf09146fa7e7f5c2b86835baf11db9a72d26194cc1125021980aa65567d66fd56a37e7d668634a9989e3665fddad1ea773d1572f37e8a110d50cf8d8c872
|
7
|
+
data.tar.gz: 4e69cb8dab76dc70b37171e043d89c877daa75d2389c2757a62e85311d6143b8df3d85a6164a232550b368bc46b95979ca625147be109d249d7f9df0e1dd0fe2
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2024 Laney Stroup
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# SimpleTeams
|
2
|
+
Short description and motivation.
|
3
|
+
|
4
|
+
## Usage
|
5
|
+
How to use my plugin.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
Add this line to your application's Gemfile:
|
9
|
+
|
10
|
+
```ruby
|
11
|
+
gem "simple_teams"
|
12
|
+
```
|
13
|
+
|
14
|
+
And then execute:
|
15
|
+
```bash
|
16
|
+
$ bundle
|
17
|
+
```
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
```bash
|
21
|
+
$ gem install simple_teams
|
22
|
+
```
|
23
|
+
|
24
|
+
## Contributing
|
25
|
+
Contribution directions go here.
|
26
|
+
|
27
|
+
## License
|
28
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
//= link_directory ../stylesheets/simple_teams .css
|
@@ -0,0 +1,15 @@
|
|
1
|
+
/*
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
3
|
+
* listed below.
|
4
|
+
*
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
6
|
+
* or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
|
7
|
+
*
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
|
9
|
+
* compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
|
10
|
+
* files in this directory. Styles in this file should be added after the last require_* statement.
|
11
|
+
* It is generally better to create a new file per style scope.
|
12
|
+
*
|
13
|
+
*= require_tree .
|
14
|
+
*= require_self
|
15
|
+
*/
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module SimpleTeams
|
2
|
+
class AcceptInvitationsController < ApplicationController
|
3
|
+
skip_before_action :authenticate_user!
|
4
|
+
before_action :set_invitation
|
5
|
+
before_action :ensure_invitation_token_is_valid
|
6
|
+
before_action :set_team
|
7
|
+
before_action :set_service_object
|
8
|
+
|
9
|
+
def new
|
10
|
+
end
|
11
|
+
|
12
|
+
def create
|
13
|
+
if params[:commit] == "Decline"
|
14
|
+
@invitation.declined!
|
15
|
+
redirect_to root_path, :notice => "You have declined the invitation to the '#{@team.name}' #{@team.teamable.class.model_name.human}."
|
16
|
+
else
|
17
|
+
if @service_object.valid?
|
18
|
+
@service_object.perform
|
19
|
+
|
20
|
+
SimpleTeams::Invitations::AcceptedNotification.with(
|
21
|
+
:team_id => @team.id,
|
22
|
+
:invitation_id => @invitation.id,
|
23
|
+
:user_id => current_user.id,
|
24
|
+
:team_name => @team.name,
|
25
|
+
:invitation_name => @invitation.email,
|
26
|
+
:user_name => current_user.full_name
|
27
|
+
).deliver_later(@team.members)
|
28
|
+
|
29
|
+
redirect_to url_for(@team.teamable), :notice => "You have accepted the invitation to the '#{@team.name}' #{@team.teamable.class.model_name.human}."
|
30
|
+
else
|
31
|
+
render :new
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def set_invitation
|
39
|
+
@invitation = SimpleTeams::Invitation.initial.unexpired.find_by(token: params[:id])
|
40
|
+
end
|
41
|
+
|
42
|
+
def ensure_invitation_token_is_valid
|
43
|
+
unless @invitation.present?
|
44
|
+
render "invalid_token"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def set_team
|
49
|
+
@team = @invitation.team
|
50
|
+
end
|
51
|
+
|
52
|
+
def set_service_object
|
53
|
+
@service_object = SimpleTeams::AcceptInvitationService.new(current_user.id, @invitation.token)
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module SimpleTeams
|
2
|
+
class InvitationsController < ApplicationController
|
3
|
+
before_action :set_invitation, only: %i[ show edit update destroy ]
|
4
|
+
|
5
|
+
# GET /invitations
|
6
|
+
def index
|
7
|
+
@invitations = Invitation.all
|
8
|
+
end
|
9
|
+
|
10
|
+
# GET /invitations/1
|
11
|
+
def show
|
12
|
+
end
|
13
|
+
|
14
|
+
# GET /invitations/new
|
15
|
+
def new
|
16
|
+
@invitation = Invitation.new
|
17
|
+
end
|
18
|
+
|
19
|
+
# GET /invitations/1/edit
|
20
|
+
def edit
|
21
|
+
end
|
22
|
+
|
23
|
+
# POST /invitations
|
24
|
+
def create
|
25
|
+
@invitation = Invitation.new(invitation_params)
|
26
|
+
|
27
|
+
if @invitation.save
|
28
|
+
redirect_to @invitation, notice: "Invitation was successfully created."
|
29
|
+
else
|
30
|
+
render :new, status: :unprocessable_entity
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# PATCH/PUT /invitations/1
|
35
|
+
def update
|
36
|
+
if @invitation.update(invitation_params)
|
37
|
+
redirect_to @invitation, notice: "Invitation was successfully updated.", status: :see_other
|
38
|
+
else
|
39
|
+
render :edit, status: :unprocessable_entity
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# DELETE /invitations/1
|
44
|
+
def destroy
|
45
|
+
@invitation.destroy
|
46
|
+
redirect_to invitations_url, notice: "Invitation was successfully destroyed.", status: :see_other
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
# Use callbacks to share common setup or constraints between actions.
|
51
|
+
def set_invitation
|
52
|
+
@invitation = Invitation.find(params[:id])
|
53
|
+
end
|
54
|
+
|
55
|
+
# Only allow a list of trusted parameters through.
|
56
|
+
def invitation_params
|
57
|
+
params.require(:invitation).permit(:team_id, :inviter_id, :membership_id, :email, :role, :token, :status, :sent_at, :expires_at)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module SimpleTeams
|
2
|
+
class MembershipsController < ApplicationController
|
3
|
+
before_action :set_membership, only: %i[ show edit update destroy ]
|
4
|
+
|
5
|
+
# GET /memberships
|
6
|
+
def index
|
7
|
+
@memberships = Membership.all
|
8
|
+
end
|
9
|
+
|
10
|
+
# GET /memberships/1
|
11
|
+
def show
|
12
|
+
end
|
13
|
+
|
14
|
+
# GET /memberships/new
|
15
|
+
def new
|
16
|
+
@membership = Membership.new
|
17
|
+
end
|
18
|
+
|
19
|
+
# GET /memberships/1/edit
|
20
|
+
def edit
|
21
|
+
end
|
22
|
+
|
23
|
+
# POST /memberships
|
24
|
+
def create
|
25
|
+
@membership = Membership.new(membership_params)
|
26
|
+
|
27
|
+
if @membership.save
|
28
|
+
redirect_to @membership, notice: "Membership was successfully created."
|
29
|
+
else
|
30
|
+
render :new, status: :unprocessable_entity
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# PATCH/PUT /memberships/1
|
35
|
+
def update
|
36
|
+
if @membership.update(membership_params)
|
37
|
+
redirect_to @membership, notice: "Membership was successfully updated.", status: :see_other
|
38
|
+
else
|
39
|
+
render :edit, status: :unprocessable_entity
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# DELETE /memberships/1
|
44
|
+
def destroy
|
45
|
+
@membership.destroy
|
46
|
+
redirect_to memberships_url, notice: "Membership was successfully destroyed.", status: :see_other
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
# Use callbacks to share common setup or constraints between actions.
|
51
|
+
def set_membership
|
52
|
+
@membership = Membership.find(params[:id])
|
53
|
+
end
|
54
|
+
|
55
|
+
# Only allow a list of trusted parameters through.
|
56
|
+
def membership_params
|
57
|
+
params.require(:membership).permit(:team_id, :member_id, :role)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module SimpleTeams
|
2
|
+
class TeamsController < ApplicationController
|
3
|
+
before_action :set_team, only: %i[ show edit update destroy ]
|
4
|
+
|
5
|
+
# GET /teams
|
6
|
+
def index
|
7
|
+
@teams = Team.all
|
8
|
+
end
|
9
|
+
|
10
|
+
# GET /teams/1
|
11
|
+
def show
|
12
|
+
end
|
13
|
+
|
14
|
+
# GET /teams/new
|
15
|
+
def new
|
16
|
+
@team = Team.new
|
17
|
+
end
|
18
|
+
|
19
|
+
# GET /teams/1/edit
|
20
|
+
def edit
|
21
|
+
end
|
22
|
+
|
23
|
+
# POST /teams
|
24
|
+
def create
|
25
|
+
@team = Team.new(team_params)
|
26
|
+
|
27
|
+
if @team.save
|
28
|
+
redirect_to @team, notice: "Team was successfully created."
|
29
|
+
else
|
30
|
+
render :new, status: :unprocessable_entity
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# PATCH/PUT /teams/1
|
35
|
+
def update
|
36
|
+
if @team.update(team_params)
|
37
|
+
redirect_to @team, notice: "Team was successfully updated.", status: :see_other
|
38
|
+
else
|
39
|
+
render :edit, status: :unprocessable_entity
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# DELETE /teams/1
|
44
|
+
def destroy
|
45
|
+
@team.destroy
|
46
|
+
redirect_to teams_url, notice: "Team was successfully destroyed.", status: :see_other
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
# Use callbacks to share common setup or constraints between actions.
|
51
|
+
def set_team
|
52
|
+
@team = Team.find(params[:id])
|
53
|
+
end
|
54
|
+
|
55
|
+
# Only allow a list of trusted parameters through.
|
56
|
+
def team_params
|
57
|
+
params.require(:team).permit(:teamable_id, :teamable_type)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module SimpleTeams
|
2
|
+
class ApplicationController < SimpleTeams.parent_controller
|
3
|
+
before_action :authenticate_user!
|
4
|
+
|
5
|
+
layout SimpleTeams.layout
|
6
|
+
|
7
|
+
def current_ability
|
8
|
+
SimpleTeams::Ability.new(current_user)
|
9
|
+
end
|
10
|
+
helper_method :current_ability
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
module SimpleTeams
|
2
|
+
class InvitationsController < ApplicationController
|
3
|
+
before_action :set_team
|
4
|
+
before_action :set_invitation, except: %i[ new create index]
|
5
|
+
|
6
|
+
def new
|
7
|
+
authorize! :create, @team.invitations.new
|
8
|
+
@service_object = SimpleTeams::InvitationForms::CreateCombo.new(@team, current_user)
|
9
|
+
end
|
10
|
+
|
11
|
+
def create
|
12
|
+
authorize! :create, @team.invitations.new
|
13
|
+
@service_object = SimpleTeams::InvitationForms::CreateCombo.new(@team, current_user)
|
14
|
+
|
15
|
+
respond_to do |format|
|
16
|
+
if @service_object.perform(new_service_object_params)
|
17
|
+
format.html { redirect_to team_path(@team), notice: "Invitations were successfully created." }
|
18
|
+
format.json { render :show, status: :created, location: @invitation }
|
19
|
+
else
|
20
|
+
format.html { render :new, status: :unprocessable_entity }
|
21
|
+
format.json { render json: @invitation.errors, status: :unprocessable_entity }
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def edit
|
27
|
+
authorize! :update, @invitation
|
28
|
+
@service_object = SimpleTeams::InvitationForms::Update.new(@invitation, current_user)
|
29
|
+
end
|
30
|
+
|
31
|
+
def update
|
32
|
+
authorize! :update, @invitation
|
33
|
+
@service_object = SimpleTeams::InvitationForms::Update.new(@invitation, current_user)
|
34
|
+
|
35
|
+
respond_to do |format|
|
36
|
+
if @service_object.perform(service_object_params)
|
37
|
+
format.html { redirect_to team_path(@team), notice: "Invitation was successfully updated." }
|
38
|
+
format.json { head :no_content }
|
39
|
+
else
|
40
|
+
format.html { render :edit, status: :unprocessable_entity }
|
41
|
+
format.json { render json: @invitation.errors, status: :unprocessable_entity }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
def resend
|
48
|
+
authorize! :update, @invitation
|
49
|
+
@invitation.resend_invitation_notification
|
50
|
+
|
51
|
+
respond_to do |format|
|
52
|
+
format.html { redirect_to team_path(@team), notice: "Invitation was successfully resent." }
|
53
|
+
format.json { head :no_content }
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def destroy
|
58
|
+
authorize! :destroy, @invitation
|
59
|
+
invitation_id = @invitation.id
|
60
|
+
invitation_email = @invitation.email
|
61
|
+
@invitation.destroy
|
62
|
+
|
63
|
+
SimpleTeams::Invitations::DestroyedNotification.with(
|
64
|
+
:team_id => @team.id,
|
65
|
+
:invitation_id => invitation_id,
|
66
|
+
:user_id => current_user.id,
|
67
|
+
:team_name => @team.name,
|
68
|
+
:invitation_name => invitation_email,
|
69
|
+
:user_name => current_user.full_name
|
70
|
+
).deliver_later(@team.members)
|
71
|
+
|
72
|
+
respond_to do |format|
|
73
|
+
format.html { redirect_to team_path(@team), notice: "Invitation was successfully destroyed." }
|
74
|
+
format.json { head :no_content }
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
def new_service_object_params
|
81
|
+
params.require(:invitation_forms_create_combo).permit(:role, :single_vs_multiple, :email, :accessible_emails, :select2_emails => [])
|
82
|
+
end
|
83
|
+
|
84
|
+
def service_object_params
|
85
|
+
params.require(:invitation_forms_update).permit(:email, :role)
|
86
|
+
end
|
87
|
+
|
88
|
+
def set_team
|
89
|
+
@team = SimpleTeams::Team.find(params[:team_id])
|
90
|
+
end
|
91
|
+
|
92
|
+
def set_invitation
|
93
|
+
@invitation = SimpleTeams::Invitation.find(params[:id])
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module SimpleTeams
|
2
|
+
class LeaveTeamsController < ApplicationController
|
3
|
+
before_action :set_team
|
4
|
+
before_action :set_service_object
|
5
|
+
|
6
|
+
def destroy
|
7
|
+
if @service_object.valid? and @service_object.perform
|
8
|
+
redirect_to root_path, :notice => "You have successfully left the #{@team.name} #{@team.teamable.class.model_name.human}."
|
9
|
+
else
|
10
|
+
redirect_to team_path(@team), :notice => @service_object.errors[:user_id].first
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def set_team
|
17
|
+
@team = SimpleTeams::Team.find(params[:team_id])
|
18
|
+
end
|
19
|
+
|
20
|
+
def set_service_object
|
21
|
+
@service_object = SimpleTeams::LeaveTeamService.new(current_user.id, @team.id)
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module SimpleTeams
|
2
|
+
class MembershipsController < ApplicationController
|
3
|
+
before_action :set_team
|
4
|
+
before_action :set_membership, :except => [:index]
|
5
|
+
|
6
|
+
def edit
|
7
|
+
authorize! :edit, @membership
|
8
|
+
@service_object = SimpleTeams::MembershipForm.new(@membership, current_user)
|
9
|
+
end
|
10
|
+
|
11
|
+
def update
|
12
|
+
authorize! :edit, @membership
|
13
|
+
@service_object = SimpleTeams::MembershipForm.new(@membership, current_user)
|
14
|
+
|
15
|
+
respond_to do |format|
|
16
|
+
if @service_object.perform(service_object_params)
|
17
|
+
format.html { redirect_to team_path(@team), notice: "Membership was updated successfully." }
|
18
|
+
format.json { render :show, status: :created, location: @service_object.membership }
|
19
|
+
else
|
20
|
+
format.html { render :edit, status: :unprocessable_entity }
|
21
|
+
format.json { render json: @service_object.errors, status: :unprocessable_entity }
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def destroy
|
27
|
+
authorize! :destroy, @membership
|
28
|
+
|
29
|
+
member_id = @membership.member.id
|
30
|
+
member_name = @membership.member.full_name
|
31
|
+
recipients = @team.members.to_a
|
32
|
+
|
33
|
+
@membership.destroy
|
34
|
+
|
35
|
+
SimpleTeams::Memberships::DestroyedNotification.with(
|
36
|
+
:team_id => @team.id,
|
37
|
+
:member_id => member_id,
|
38
|
+
:user_id => current_user.id,
|
39
|
+
:team_name => @team.name,
|
40
|
+
:member_name => member_name,
|
41
|
+
:user_name => current_user.full_name
|
42
|
+
).deliver_later(recipients)
|
43
|
+
|
44
|
+
redirect_to team_path(@team)
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def service_object_params
|
50
|
+
params.require(:teams_membership_form).permit(:role)
|
51
|
+
end
|
52
|
+
|
53
|
+
def set_team
|
54
|
+
@team = SimpleTeams::Team.find(params[:team_id])
|
55
|
+
end
|
56
|
+
|
57
|
+
def set_membership
|
58
|
+
@membership = @team.memberships.find(params[:id])
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module SimpleTeams
|
2
|
+
class RelatedUsersController < ApplicationController
|
3
|
+
|
4
|
+
def index
|
5
|
+
if params[:term].present?
|
6
|
+
@members = SimpleTeams.member_class
|
7
|
+
.joins(:team_memberships, :teams)
|
8
|
+
.where("teams_teams.id" => current_user.teams.pluck(:id))
|
9
|
+
.where("email ilike ?", "%#{params[:term]}%")
|
10
|
+
.order("#{SimpleTeams.member_class.table_name}.first_name")
|
11
|
+
.uniq
|
12
|
+
@members.reject! { |member| member.id == current_user.id }
|
13
|
+
else
|
14
|
+
@members= SimpleTeams.member_class.none
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def select2
|
19
|
+
if params[:term].present?
|
20
|
+
@members = SimpleTeams.member_class
|
21
|
+
.joins(:team_memberships, :teams)
|
22
|
+
.where("teams_teams.id" => current_user.teams.pluck(:id))
|
23
|
+
.where("email ilike ?", "%#{params[:term]}%")
|
24
|
+
.order("#{SimpleTeams.member_class.table_name}.first_name")
|
25
|
+
.uniq
|
26
|
+
@members.reject! { |member| member.id == current_user.id }
|
27
|
+
else
|
28
|
+
@members = SimpleTeams.member_class.none
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module SimpleTeams
|
2
|
+
class TeamsController < ApplicationController
|
3
|
+
before_action :set_team
|
4
|
+
|
5
|
+
def show
|
6
|
+
authorize! :read, @team
|
7
|
+
@memberships = @team.memberships.joins(:member).order(:first_name)
|
8
|
+
@invitations = @team.invitations.initial.order(:email)
|
9
|
+
@memberships_and_invitations = @memberships.to_a + @invitations.to_a
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def set_team
|
15
|
+
@team = SimpleTeams::Team.find(params[:id])
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
module SimpleTeams
|
2
|
+
class InvitationForm < ApplicationForm
|
3
|
+
|
4
|
+
attr_accessor :team, :current_user, :invitation, :email, :role
|
5
|
+
|
6
|
+
def initialize(team, current_user)
|
7
|
+
raise NotImplementedError
|
8
|
+
end
|
9
|
+
|
10
|
+
def perform(params)
|
11
|
+
self.assign_attributes(params)
|
12
|
+
|
13
|
+
if valid?
|
14
|
+
invitation.update!(params)
|
15
|
+
generate_notification
|
16
|
+
else
|
17
|
+
false
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# Attributes
|
22
|
+
def self.invitation_attributes
|
23
|
+
[:email, :role]
|
24
|
+
end
|
25
|
+
|
26
|
+
def available_roles
|
27
|
+
@available_roles ||= SimpleTeams::Membership.roles
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def valid?
|
33
|
+
self.errors.clear
|
34
|
+
validate_role_is_available
|
35
|
+
validate_invitation
|
36
|
+
validate_current_user_has_rights_to_invite_an_owner
|
37
|
+
!self.errors.present?
|
38
|
+
end
|
39
|
+
|
40
|
+
def validate_role_is_available
|
41
|
+
# Note: Users will never see this error message unless they hack the form
|
42
|
+
if role.present?
|
43
|
+
unless available_roles.keys.include? role
|
44
|
+
self.errors.add(:role, "that role is not available for this resource")
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def validate_invitation
|
50
|
+
# Update invitation object
|
51
|
+
self.class.invitation_attributes.each do |a|
|
52
|
+
invitation.assign_attributes(a => self.send(a))
|
53
|
+
end
|
54
|
+
|
55
|
+
# Call valid?
|
56
|
+
invitation.valid?
|
57
|
+
|
58
|
+
# Reassign errors
|
59
|
+
self.class.invitation_attributes.each do |a|
|
60
|
+
if invitation.errors[a].present?
|
61
|
+
invitation.errors[a].each do |e|
|
62
|
+
self.errors.add(a, e)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def validate_current_user_has_rights_to_invite_an_owner
|
69
|
+
if role == "owner"
|
70
|
+
unless current_user.membership_for_team(team).owner?
|
71
|
+
self.errors.add(:role, "you must be an owner yourself to add add another owner")
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module SimpleTeams
|
2
|
+
class InvitationForms::Create < SimpleTeams::InvitationForm
|
3
|
+
|
4
|
+
def initialize(team, current_user)
|
5
|
+
@team = team
|
6
|
+
@current_user = current_user
|
7
|
+
@invitation = team.invitations.new(:inviter => @current_user)
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def generate_notification
|
13
|
+
SimpleTeams::Invitations::CreatedNotification.with(
|
14
|
+
:team_id => team.id,
|
15
|
+
:invitation_id => invitation.id,
|
16
|
+
:user_id => current_user.id,
|
17
|
+
:team_name => team.name,
|
18
|
+
:invitation_name => invitation.email,
|
19
|
+
:user_name => current_user.full_name
|
20
|
+
).deliver_later(team.members)
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|