PLT-2863 adding remove user from team (#3429)
* PLT-2863 adding remove user from team * PLT-2863 adding the client side UI * Fixing trailing space * Fixing reported issues * Adding documentatino * Switching to final javascript driver
Этот коммит содержится в:
@@ -334,6 +334,43 @@ func TestCliJoinTeam(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCliLeaveTeam(t *testing.T) {
|
||||||
|
if disableCliTests {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
th := Setup().InitBasic()
|
||||||
|
|
||||||
|
cmd := exec.Command("bash", "-c", `go run ../mattermost.go -leave_team -team_name="`+th.BasicTeam.Name+`" -email="`+th.BasicUser.Email+`"`)
|
||||||
|
output, err := cmd.CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
t.Log(string(output))
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
profiles := th.BasicClient.Must(th.BasicClient.GetProfiles(th.BasicTeam.Id, "")).Data.(map[string]*model.User)
|
||||||
|
|
||||||
|
found := false
|
||||||
|
|
||||||
|
for _, user := range profiles {
|
||||||
|
if user.Email == th.BasicUser.Email {
|
||||||
|
found = true
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if !found {
|
||||||
|
t.Fatal("profile still should be in team even if deleted")
|
||||||
|
}
|
||||||
|
|
||||||
|
if result := <-Srv.Store.Team().GetTeamsByUserId(th.BasicUser.Id); result.Err != nil {
|
||||||
|
teamMembers := result.Data.([]*model.TeamMember)
|
||||||
|
if len(teamMembers) > 0 {
|
||||||
|
t.Fatal("Shouldn't be in team")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestCliResetPassword(t *testing.T) {
|
func TestCliResetPassword(t *testing.T) {
|
||||||
if disableCliTests {
|
if disableCliTests {
|
||||||
return
|
return
|
||||||
|
|||||||
115
api/team.go
115
api/team.go
@@ -17,7 +17,6 @@ import (
|
|||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
|
|
||||||
"github.com/mattermost/platform/model"
|
"github.com/mattermost/platform/model"
|
||||||
"github.com/mattermost/platform/store"
|
|
||||||
"github.com/mattermost/platform/utils"
|
"github.com/mattermost/platform/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -39,6 +38,7 @@ func InitTeam() {
|
|||||||
BaseRoutes.NeedTeam.Handle("/invite_members", ApiUserRequired(inviteMembers)).Methods("POST")
|
BaseRoutes.NeedTeam.Handle("/invite_members", ApiUserRequired(inviteMembers)).Methods("POST")
|
||||||
|
|
||||||
BaseRoutes.NeedTeam.Handle("/add_user_to_team", ApiUserRequired(addUserToTeam)).Methods("POST")
|
BaseRoutes.NeedTeam.Handle("/add_user_to_team", ApiUserRequired(addUserToTeam)).Methods("POST")
|
||||||
|
BaseRoutes.NeedTeam.Handle("/remove_user_from_team", ApiUserRequired(removeUserFromTeam)).Methods("POST")
|
||||||
|
|
||||||
// These should be moved to the global admin console
|
// These should be moved to the global admin console
|
||||||
BaseRoutes.NeedTeam.Handle("/import_team", ApiUserRequired(importTeam)).Methods("POST")
|
BaseRoutes.NeedTeam.Handle("/import_team", ApiUserRequired(importTeam)).Methods("POST")
|
||||||
@@ -266,11 +266,23 @@ func JoinUserToTeam(team *model.Team, user *model.User) *model.AppError {
|
|||||||
channelRole = model.CHANNEL_ROLE_ADMIN
|
channelRole = model.CHANNEL_ROLE_ADMIN
|
||||||
}
|
}
|
||||||
|
|
||||||
if tmr := <-Srv.Store.Team().SaveMember(tm); tmr.Err != nil {
|
if etmr := <-Srv.Store.Team().GetMember(team.Id, user.Id); etmr.Err == nil {
|
||||||
if tmr.Err.Id == store.TEAM_MEMBER_EXISTS_ERROR {
|
// Membership alredy exists. Check if deleted and and update, otherwise do nothing
|
||||||
|
rtm := etmr.Data.(model.TeamMember)
|
||||||
|
|
||||||
|
// Do nothing if already added
|
||||||
|
if rtm.DeleteAt == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return tmr.Err
|
|
||||||
|
if tmr := <-Srv.Store.Team().UpdateMember(tm); tmr.Err != nil {
|
||||||
|
return tmr.Err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Membership appears to be missing. Lets try to add.
|
||||||
|
if tmr := <-Srv.Store.Team().SaveMember(tm); tmr.Err != nil {
|
||||||
|
return tmr.Err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if uua := <-Srv.Store.User().UpdateUpdateAt(user.Id); uua.Err != nil {
|
if uua := <-Srv.Store.User().UpdateUpdateAt(user.Id); uua.Err != nil {
|
||||||
@@ -291,6 +303,56 @@ func JoinUserToTeam(team *model.Team, user *model.User) *model.AppError {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func LeaveTeam(team *model.Team, user *model.User) *model.AppError {
|
||||||
|
|
||||||
|
var teamMember model.TeamMember
|
||||||
|
|
||||||
|
if result := <-Srv.Store.Team().GetMember(team.Id, user.Id); result.Err != nil {
|
||||||
|
return model.NewLocAppError("RemoveUserFromTeam", "api.team.remove_user_from_team.missing.app_error", nil, result.Err.Error())
|
||||||
|
} else {
|
||||||
|
teamMember = result.Data.(model.TeamMember)
|
||||||
|
}
|
||||||
|
|
||||||
|
var channelMembers *model.ChannelList
|
||||||
|
|
||||||
|
if result := <-Srv.Store.Channel().GetChannels(team.Id, user.Id); result.Err != nil {
|
||||||
|
if result.Err.Id == "store.sql_channel.get_channels.not_found.app_error" {
|
||||||
|
channelMembers = &model.ChannelList{make([]*model.Channel, 0), make(map[string]*model.ChannelMember)}
|
||||||
|
} else {
|
||||||
|
return result.Err
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
channelMembers = result.Data.(*model.ChannelList)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, channel := range channelMembers.Channels {
|
||||||
|
if channel.Type != model.CHANNEL_DIRECT {
|
||||||
|
if result := <-Srv.Store.Channel().RemoveMember(channel.Id, user.Id); result.Err != nil {
|
||||||
|
return result.Err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
teamMember.Roles = ""
|
||||||
|
teamMember.DeleteAt = model.GetMillis()
|
||||||
|
|
||||||
|
if result := <-Srv.Store.Team().UpdateMember(&teamMember); result.Err != nil {
|
||||||
|
return result.Err
|
||||||
|
}
|
||||||
|
|
||||||
|
if uua := <-Srv.Store.User().UpdateUpdateAt(user.Id); uua.Err != nil {
|
||||||
|
return uua.Err
|
||||||
|
}
|
||||||
|
|
||||||
|
RemoveAllSessionsForUserId(user.Id)
|
||||||
|
InvalidateCacheForUser(user.Id)
|
||||||
|
|
||||||
|
go Publish(model.NewMessage(team.Id, "", user.Id, model.ACTION_LEAVE_TEAM))
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func isTeamCreationAllowed(c *Context, email string) bool {
|
func isTeamCreationAllowed(c *Context, email string) bool {
|
||||||
|
|
||||||
email = strings.ToLower(email)
|
email = strings.ToLower(email)
|
||||||
@@ -483,6 +545,51 @@ func addUserToTeam(c *Context, w http.ResponseWriter, r *http.Request) {
|
|||||||
w.Write([]byte(model.MapToJson(params)))
|
w.Write([]byte(model.MapToJson(params)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func removeUserFromTeam(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||||
|
params := model.MapFromJson(r.Body)
|
||||||
|
userId := params["user_id"]
|
||||||
|
|
||||||
|
if len(userId) != 26 {
|
||||||
|
c.SetInvalidParam("removeUserFromTeam", "user_id")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
tchan := Srv.Store.Team().Get(c.TeamId)
|
||||||
|
uchan := Srv.Store.User().Get(userId)
|
||||||
|
|
||||||
|
var team *model.Team
|
||||||
|
if result := <-tchan; result.Err != nil {
|
||||||
|
c.Err = result.Err
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
team = result.Data.(*model.Team)
|
||||||
|
}
|
||||||
|
|
||||||
|
var user *model.User
|
||||||
|
if result := <-uchan; result.Err != nil {
|
||||||
|
c.Err = result.Err
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
user = result.Data.(*model.User)
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.Session.UserId != user.Id {
|
||||||
|
if !c.IsTeamAdmin() {
|
||||||
|
c.Err = model.NewLocAppError("removeUserFromTeam", "api.team.update_team.permissions.app_error", nil, "userId="+c.Session.UserId)
|
||||||
|
c.Err.StatusCode = http.StatusForbidden
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err := LeaveTeam(team, user)
|
||||||
|
if err != nil {
|
||||||
|
c.Err = err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
w.Write([]byte(model.MapToJson(params)))
|
||||||
|
}
|
||||||
|
|
||||||
func addUserToTeamFromInvite(c *Context, w http.ResponseWriter, r *http.Request) {
|
func addUserToTeamFromInvite(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
params := model.MapFromJson(r.Body)
|
params := model.MapFromJson(r.Body)
|
||||||
|
|||||||
@@ -158,7 +158,7 @@ func TestAddUserToTeam(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
user2 := th.CreateUser(th.BasicClient)
|
user2 := th.CreateUser(th.BasicClient)
|
||||||
if result, err := th.BasicClient.AddUserToTeam(user2.Id); err != nil {
|
if result, err := th.BasicClient.AddUserToTeam("", user2.Id); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
} else {
|
} else {
|
||||||
rm := result.Data.(map[string]string)
|
rm := result.Data.(map[string]string)
|
||||||
@@ -168,6 +168,39 @@ func TestAddUserToTeam(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRemoveUserFromTeam(t *testing.T) {
|
||||||
|
th := Setup().InitSystemAdmin().InitBasic()
|
||||||
|
|
||||||
|
if _, err := th.BasicClient.RemoveUserFromTeam(th.SystemAdminTeam.Id, th.SystemAdminUser.Id); err == nil {
|
||||||
|
t.Fatal("should fail not enough permissions")
|
||||||
|
} else {
|
||||||
|
if err.Id != "api.context.permissions.app_error" {
|
||||||
|
t.Fatal("wrong error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := th.BasicClient.RemoveUserFromTeam("", th.SystemAdminUser.Id); err == nil {
|
||||||
|
t.Fatal("should fail not enough permissions")
|
||||||
|
} else {
|
||||||
|
if err.Id != "api.team.update_team.permissions.app_error" {
|
||||||
|
t.Fatal("wrong error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := th.BasicClient.RemoveUserFromTeam("", th.BasicUser.Id); err != nil {
|
||||||
|
t.Fatal("should have removed the user from the team")
|
||||||
|
}
|
||||||
|
|
||||||
|
th.BasicClient.Logout()
|
||||||
|
th.LoginSystemAdmin()
|
||||||
|
|
||||||
|
th.SystemAdminClient.Must(th.SystemAdminClient.AddUserToTeam(th.BasicTeam.Id, th.BasicUser.Id))
|
||||||
|
|
||||||
|
if _, err := th.SystemAdminClient.RemoveUserFromTeam(th.BasicTeam.Id, th.BasicUser.Id); err != nil {
|
||||||
|
t.Fatal("should have removed the user from the team")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestAddUserToTeamFromInvite(t *testing.T) {
|
func TestAddUserToTeamFromInvite(t *testing.T) {
|
||||||
th := Setup().InitBasic()
|
th := Setup().InitBasic()
|
||||||
th.BasicClient.Logout()
|
th.BasicClient.Logout()
|
||||||
|
|||||||
25
i18n/en.json
25
i18n/en.json
@@ -1263,6 +1263,10 @@
|
|||||||
"id": "api.slackimport.slack_import.zip.app_error",
|
"id": "api.slackimport.slack_import.zip.app_error",
|
||||||
"translation": "Unable to open zip file"
|
"translation": "Unable to open zip file"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "api.team.remove_user_from_team.missing.app_error",
|
||||||
|
"translation": "The user does not appear to be part of this team."
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "api.team.create_team.email_disabled.app_error",
|
"id": "api.team.create_team.email_disabled.app_error",
|
||||||
"translation": "Team sign-up with email is disabled."
|
"translation": "Team sign-up with email is disabled."
|
||||||
@@ -4223,6 +4227,27 @@
|
|||||||
"id": "utils.mail.test.configured.error",
|
"id": "utils.mail.test.configured.error",
|
||||||
"translation": "SMTP server settings do not appear to be configured properly err=%v details=%v"
|
"translation": "SMTP server settings do not appear to be configured properly err=%v details=%v"
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"id": "utils.mail.test.configured.error",
|
||||||
|
"translation": "SMTP server settings do not appear to be configured properly err=%v details=%v"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "leave_team_modal.title",
|
||||||
|
"translation": "Leave the team?"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "leave_team_modal.desc",
|
||||||
|
"translation": "You will be removed from all public channels and private groups. If the team is private you will not be able to rejoin the team. Are you sure?"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "leave_team_modal.no",
|
||||||
|
"translation": "No"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "leave_team_modal.yes",
|
||||||
|
"translation": "Yes"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "web.admin_console.title",
|
"id": "web.admin_console.title",
|
||||||
"translation": "Admin Console"
|
"translation": "Admin Console"
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ var flagCmdLeaveChannel bool
|
|||||||
var flagCmdListChannels bool
|
var flagCmdListChannels bool
|
||||||
var flagCmdRestoreChannel bool
|
var flagCmdRestoreChannel bool
|
||||||
var flagCmdJoinTeam bool
|
var flagCmdJoinTeam bool
|
||||||
|
var flagCmdLeaveTeam bool
|
||||||
var flagCmdVersion bool
|
var flagCmdVersion bool
|
||||||
var flagCmdRunWebClientTests bool
|
var flagCmdRunWebClientTests bool
|
||||||
var flagCmdRunJavascriptClientTests bool
|
var flagCmdRunJavascriptClientTests bool
|
||||||
@@ -286,6 +287,7 @@ func parseCmds() {
|
|||||||
flag.BoolVar(&flagCmdListChannels, "list_channels", false, "")
|
flag.BoolVar(&flagCmdListChannels, "list_channels", false, "")
|
||||||
flag.BoolVar(&flagCmdRestoreChannel, "restore_channel", false, "")
|
flag.BoolVar(&flagCmdRestoreChannel, "restore_channel", false, "")
|
||||||
flag.BoolVar(&flagCmdJoinTeam, "join_team", false, "")
|
flag.BoolVar(&flagCmdJoinTeam, "join_team", false, "")
|
||||||
|
flag.BoolVar(&flagCmdLeaveTeam, "leave_team", false, "")
|
||||||
flag.BoolVar(&flagCmdVersion, "version", false, "")
|
flag.BoolVar(&flagCmdVersion, "version", false, "")
|
||||||
flag.BoolVar(&flagCmdRunWebClientTests, "run_web_client_tests", false, "")
|
flag.BoolVar(&flagCmdRunWebClientTests, "run_web_client_tests", false, "")
|
||||||
flag.BoolVar(&flagCmdRunJavascriptClientTests, "run_javascript_client_tests", false, "")
|
flag.BoolVar(&flagCmdRunJavascriptClientTests, "run_javascript_client_tests", false, "")
|
||||||
@@ -303,6 +305,7 @@ func parseCmds() {
|
|||||||
flagRunCmds = (flagCmdCreateTeam ||
|
flagRunCmds = (flagCmdCreateTeam ||
|
||||||
flagCmdCreateUser ||
|
flagCmdCreateUser ||
|
||||||
flagCmdInviteUser ||
|
flagCmdInviteUser ||
|
||||||
|
flagCmdLeaveTeam ||
|
||||||
flagCmdAssignRole ||
|
flagCmdAssignRole ||
|
||||||
flagCmdJoinChannel ||
|
flagCmdJoinChannel ||
|
||||||
flagCmdLeaveChannel ||
|
flagCmdLeaveChannel ||
|
||||||
@@ -328,6 +331,7 @@ func runCmds() {
|
|||||||
cmdCreateTeam()
|
cmdCreateTeam()
|
||||||
cmdCreateUser()
|
cmdCreateUser()
|
||||||
cmdInviteUser()
|
cmdInviteUser()
|
||||||
|
cmdLeaveTeam()
|
||||||
cmdAssignRole()
|
cmdAssignRole()
|
||||||
cmdJoinChannel()
|
cmdJoinChannel()
|
||||||
cmdLeaveChannel()
|
cmdLeaveChannel()
|
||||||
@@ -1187,6 +1191,47 @@ func cmdJoinTeam() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func cmdLeaveTeam() {
|
||||||
|
if flagCmdLeaveTeam {
|
||||||
|
if len(flagTeamName) == 0 {
|
||||||
|
fmt.Fprintln(os.Stderr, "flag needs an argument: -team_name")
|
||||||
|
flag.Usage()
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(flagEmail) == 0 {
|
||||||
|
fmt.Fprintln(os.Stderr, "flag needs an argument: -email")
|
||||||
|
flag.Usage()
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
var team *model.Team
|
||||||
|
if result := <-api.Srv.Store.Team().GetByName(flagTeamName); result.Err != nil {
|
||||||
|
l4g.Error("%v", result.Err)
|
||||||
|
flushLogAndExit(1)
|
||||||
|
} else {
|
||||||
|
team = result.Data.(*model.Team)
|
||||||
|
}
|
||||||
|
|
||||||
|
var user *model.User
|
||||||
|
if result := <-api.Srv.Store.User().GetByEmail(flagEmail); result.Err != nil {
|
||||||
|
l4g.Error("%v", result.Err)
|
||||||
|
flushLogAndExit(1)
|
||||||
|
} else {
|
||||||
|
user = result.Data.(*model.User)
|
||||||
|
}
|
||||||
|
|
||||||
|
err := api.LeaveTeam(team, user)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
l4g.Error("%v", err)
|
||||||
|
flushLogAndExit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func cmdResetPassword() {
|
func cmdResetPassword() {
|
||||||
if flagCmdResetPassword {
|
if flagCmdResetPassword {
|
||||||
if len(flagEmail) == 0 {
|
if len(flagEmail) == 0 {
|
||||||
@@ -1517,7 +1562,12 @@ COMMANDS:
|
|||||||
Example:
|
Example:
|
||||||
platform -invite_user -team_name="name" -email="user@example.com" -site_url="https://mattermost.example.com"
|
platform -invite_user -team_name="name" -email="user@example.com" -site_url="https://mattermost.example.com"
|
||||||
|
|
||||||
-join_team Joins a user to the team. It requires the -email and
|
-leave_team Removes a user from a team. It requires the -team_name
|
||||||
|
and -email.
|
||||||
|
Example:
|
||||||
|
platform -remove_user_from_team -team_name="name" -email="user@example.com"
|
||||||
|
|
||||||
|
-join_team Joins a user to the team. It required the -email and
|
||||||
-team_name. You may need to logout of your current session
|
-team_name. You may need to logout of your current session
|
||||||
for the new team to be applied.
|
for the new team to be applied.
|
||||||
Example:
|
Example:
|
||||||
|
|||||||
@@ -345,10 +345,18 @@ func (c *Client) FindTeamByName(name string) (*Result, *AppError) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) AddUserToTeam(userId string) (*Result, *AppError) {
|
// Adds a user directly to the team without sending an invite.
|
||||||
|
// The teamId and userId are required. You must be a valid member of the team and/or
|
||||||
|
// have the correct role to add new users to the team. Returns a map of user_id=userId
|
||||||
|
// if successful, otherwise returns an AppError.
|
||||||
|
func (c *Client) AddUserToTeam(teamId string, userId string) (*Result, *AppError) {
|
||||||
|
if len(teamId) == 0 {
|
||||||
|
teamId = c.GetTeamId()
|
||||||
|
}
|
||||||
|
|
||||||
data := make(map[string]string)
|
data := make(map[string]string)
|
||||||
data["user_id"] = userId
|
data["user_id"] = userId
|
||||||
if r, err := c.DoApiPost(c.GetTeamRoute()+"/add_user_to_team", MapToJson(data)); err != nil {
|
if r, err := c.DoApiPost(fmt.Sprintf("/teams/%v", teamId)+"/add_user_to_team", MapToJson(data)); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
} else {
|
} else {
|
||||||
defer closeBody(r)
|
defer closeBody(r)
|
||||||
@@ -371,6 +379,26 @@ func (c *Client) AddUserToTeamFromInvite(hash, dataToHash, inviteId string) (*Re
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Removes a user directly from the team.
|
||||||
|
// The teamId and userId are required. You must be a valid member of the team and/or
|
||||||
|
// have the correct role to remove a user from the team. Returns a map of user_id=userId
|
||||||
|
// if successful, otherwise returns an AppError.
|
||||||
|
func (c *Client) RemoveUserFromTeam(teamId string, userId string) (*Result, *AppError) {
|
||||||
|
if len(teamId) == 0 {
|
||||||
|
teamId = c.GetTeamId()
|
||||||
|
}
|
||||||
|
|
||||||
|
data := make(map[string]string)
|
||||||
|
data["user_id"] = userId
|
||||||
|
if r, err := c.DoApiPost(fmt.Sprintf("/teams/%v", teamId)+"/remove_user_from_team", MapToJson(data)); err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else {
|
||||||
|
defer closeBody(r)
|
||||||
|
return &Result{r.Header.Get(HEADER_REQUEST_ID),
|
||||||
|
r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Client) InviteMembers(invites *Invites) (*Result, *AppError) {
|
func (c *Client) InviteMembers(invites *Invites) (*Result, *AppError) {
|
||||||
if r, err := c.DoApiPost(c.GetTeamRoute()+"/invite_members", invites.ToJson()); err != nil {
|
if r, err := c.DoApiPost(c.GetTeamRoute()+"/invite_members", invites.ToJson()); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ const (
|
|||||||
ACTION_CHANNEL_VIEWED = "channel_viewed"
|
ACTION_CHANNEL_VIEWED = "channel_viewed"
|
||||||
ACTION_DIRECT_ADDED = "direct_added"
|
ACTION_DIRECT_ADDED = "direct_added"
|
||||||
ACTION_NEW_USER = "new_user"
|
ACTION_NEW_USER = "new_user"
|
||||||
|
ACTION_LEAVE_TEAM = "leave_team"
|
||||||
ACTION_USER_ADDED = "user_added"
|
ACTION_USER_ADDED = "user_added"
|
||||||
ACTION_USER_REMOVED = "user_removed"
|
ACTION_USER_REMOVED = "user_removed"
|
||||||
ACTION_PREFERENCE_CHANGED = "preference_changed"
|
ACTION_PREFERENCE_CHANGED = "preference_changed"
|
||||||
|
|||||||
@@ -14,9 +14,10 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type TeamMember struct {
|
type TeamMember struct {
|
||||||
TeamId string `json:"team_id"`
|
TeamId string `json:"team_id"`
|
||||||
UserId string `json:"user_id"`
|
UserId string `json:"user_id"`
|
||||||
Roles string `json:"roles"`
|
Roles string `json:"roles"`
|
||||||
|
DeleteAt int64 `json:"delete_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *TeamMember) ToJson() string {
|
func (o *TeamMember) ToJson() string {
|
||||||
|
|||||||
@@ -75,7 +75,13 @@ func (me SqlSessionStore) Save(session *model.Session) StoreChannel {
|
|||||||
result.Err = model.NewLocAppError("SqlSessionStore.Save", "store.sql_session.save.app_error", nil, "id="+session.Id+", "+rtcs.Err.Error())
|
result.Err = model.NewLocAppError("SqlSessionStore.Save", "store.sql_session.save.app_error", nil, "id="+session.Id+", "+rtcs.Err.Error())
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
session.TeamMembers = rtcs.Data.([]*model.TeamMember)
|
tempMembers := rtcs.Data.([]*model.TeamMember)
|
||||||
|
session.TeamMembers = make([]*model.TeamMember, 0, len(tempMembers))
|
||||||
|
for _, tm := range tempMembers {
|
||||||
|
if tm.DeleteAt == 0 {
|
||||||
|
session.TeamMembers = append(session.TeamMembers, tm)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
storeChannel <- result
|
storeChannel <- result
|
||||||
@@ -106,7 +112,13 @@ func (me SqlSessionStore) Get(sessionIdOrToken string) StoreChannel {
|
|||||||
result.Err = model.NewLocAppError("SqlSessionStore.Get", "store.sql_session.get.app_error", nil, "sessionIdOrToken="+sessionIdOrToken+", "+rtcs.Err.Error())
|
result.Err = model.NewLocAppError("SqlSessionStore.Get", "store.sql_session.get.app_error", nil, "sessionIdOrToken="+sessionIdOrToken+", "+rtcs.Err.Error())
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
sessions[0].TeamMembers = rtcs.Data.([]*model.TeamMember)
|
tempMembers := rtcs.Data.([]*model.TeamMember)
|
||||||
|
sessions[0].TeamMembers = make([]*model.TeamMember, 0, len(tempMembers))
|
||||||
|
for _, tm := range tempMembers {
|
||||||
|
if tm.DeleteAt == 0 {
|
||||||
|
sessions[0].TeamMembers = append(sessions[0].TeamMembers, tm)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,7 +156,13 @@ func (me SqlSessionStore) GetSessions(userId string) StoreChannel {
|
|||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
for _, session := range sessions {
|
for _, session := range sessions {
|
||||||
session.TeamMembers = rtcs.Data.([]*model.TeamMember)
|
tempMembers := rtcs.Data.([]*model.TeamMember)
|
||||||
|
session.TeamMembers = make([]*model.TeamMember, 0, len(tempMembers))
|
||||||
|
for _, tm := range tempMembers {
|
||||||
|
if tm.DeleteAt == 0 {
|
||||||
|
session.TeamMembers = append(session.TeamMembers, tm)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ func NewSqlTeamStore(sqlStore *SqlStore) TeamStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s SqlTeamStore) UpgradeSchemaIfNeeded() {
|
func (s SqlTeamStore) UpgradeSchemaIfNeeded() {
|
||||||
|
s.CreateColumnIfNotExists("TeamMembers", "DeleteAt", "bigint(20)", "bigint", "0")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s SqlTeamStore) CreateIndexesIfNotExists() {
|
func (s SqlTeamStore) CreateIndexesIfNotExists() {
|
||||||
|
|||||||
@@ -288,6 +288,13 @@ export function showInviteMemberModal() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function showLeaveTeamModal() {
|
||||||
|
AppDispatcher.handleViewAction({
|
||||||
|
type: ActionTypes.TOGGLE_LEAVE_TEAM_MODAL,
|
||||||
|
value: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export function showRegisterAppModal() {
|
export function showRegisterAppModal() {
|
||||||
AppDispatcher.handleViewAction({
|
AppDispatcher.handleViewAction({
|
||||||
type: ActionTypes.TOGGLE_REGISTER_APP_MODAL,
|
type: ActionTypes.TOGGLE_REGISTER_APP_MODAL,
|
||||||
|
|||||||
@@ -135,6 +135,10 @@ function handleMessage(msg) {
|
|||||||
handleNewUserEvent();
|
handleNewUserEvent();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case SocketEvents.LEAVE_TEAM:
|
||||||
|
handleLeaveTeamEvent(msg);
|
||||||
|
break;
|
||||||
|
|
||||||
case SocketEvents.USER_ADDED:
|
case SocketEvents.USER_ADDED:
|
||||||
handleUserAddedEvent(msg);
|
handleUserAddedEvent(msg);
|
||||||
break;
|
break;
|
||||||
@@ -219,6 +223,19 @@ function handleNewUserEvent() {
|
|||||||
AsyncClient.getChannelExtraInfo();
|
AsyncClient.getChannelExtraInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleLeaveTeamEvent(msg) {
|
||||||
|
if (UserStore.getCurrentId() === msg.user_id) {
|
||||||
|
TeamStore.removeTeamMember(msg.team_id);
|
||||||
|
|
||||||
|
// if the are on the team begin removed redirect them to the root
|
||||||
|
if (TeamStore.getCurrentId() === msg.team_id) {
|
||||||
|
browserHistory.push('/');
|
||||||
|
}
|
||||||
|
} else if (TeamStore.getCurrentId() === msg.team_id) {
|
||||||
|
GlobalActions.emitProfilesForDmList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function handleDirectAddedEvent(msg) {
|
function handleDirectAddedEvent(msg) {
|
||||||
AsyncClient.getChannel(msg.channel_id);
|
AsyncClient.getChannel(msg.channel_id);
|
||||||
AsyncClient.getDirectProfiles();
|
AsyncClient.getDirectProfiles();
|
||||||
|
|||||||
@@ -186,6 +186,10 @@ export default class UserList extends React.Component {
|
|||||||
var memberList = this.state.users.map((user) => {
|
var memberList = this.state.users.map((user) => {
|
||||||
var teamMember = this.getTeamMemberForUser(user.id);
|
var teamMember = this.getTeamMemberForUser(user.id);
|
||||||
|
|
||||||
|
if (teamMember.delete_at > 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<UserItem
|
<UserItem
|
||||||
team={this.state.team}
|
team={this.state.team}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ export default class UserItem extends React.Component {
|
|||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
this.handleMakeMember = this.handleMakeMember.bind(this);
|
this.handleMakeMember = this.handleMakeMember.bind(this);
|
||||||
|
this.handleRemoveFromTeam = this.handleRemoveFromTeam.bind(this);
|
||||||
this.handleMakeActive = this.handleMakeActive.bind(this);
|
this.handleMakeActive = this.handleMakeActive.bind(this);
|
||||||
this.handleMakeNotActive = this.handleMakeNotActive.bind(this);
|
this.handleMakeNotActive = this.handleMakeNotActive.bind(this);
|
||||||
this.handleMakeAdmin = this.handleMakeAdmin.bind(this);
|
this.handleMakeAdmin = this.handleMakeAdmin.bind(this);
|
||||||
@@ -56,6 +57,19 @@ export default class UserItem extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleRemoveFromTeam() {
|
||||||
|
Client.removeUserFromTeam(
|
||||||
|
this.props.team.id,
|
||||||
|
this.props.user.id,
|
||||||
|
() => {
|
||||||
|
this.props.refreshProfiles();
|
||||||
|
},
|
||||||
|
(err) => {
|
||||||
|
this.setState({serverError: err.message});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
handleMakeActive(e) {
|
handleMakeActive(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
Client.updateActive(this.props.user.id, true,
|
Client.updateActive(this.props.user.id, true,
|
||||||
@@ -222,6 +236,7 @@ export default class UserItem extends React.Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const me = UserStore.getCurrentUser();
|
||||||
const email = user.email;
|
const email = user.email;
|
||||||
let showMakeMember = teamMember.roles === 'admin' || user.roles === 'system_admin';
|
let showMakeMember = teamMember.roles === 'admin' || user.roles === 'system_admin';
|
||||||
let showMakeAdmin = teamMember.roles === '' && user.roles !== 'system_admin';
|
let showMakeAdmin = teamMember.roles === '' && user.roles !== 'system_admin';
|
||||||
@@ -299,6 +314,24 @@ export default class UserItem extends React.Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let removeFromTeam = null;
|
||||||
|
if (this.props.user.id !== me.id) {
|
||||||
|
removeFromTeam = (
|
||||||
|
<li role='presentation'>
|
||||||
|
<a
|
||||||
|
role='menuitem'
|
||||||
|
href='#'
|
||||||
|
onClick={this.handleRemoveFromTeam}
|
||||||
|
>
|
||||||
|
<FormattedMessage
|
||||||
|
id='team_members_dropdown.leave_team'
|
||||||
|
defaultMessage='Remove From Team'
|
||||||
|
/>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
let makeActive = null;
|
let makeActive = null;
|
||||||
if (showMakeActive) {
|
if (showMakeActive) {
|
||||||
makeActive = (
|
makeActive = (
|
||||||
@@ -428,7 +461,6 @@ export default class UserItem extends React.Component {
|
|||||||
passwordReset = null;
|
passwordReset = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const me = UserStore.getCurrentUser();
|
|
||||||
let makeDemoteModal = null;
|
let makeDemoteModal = null;
|
||||||
if (this.props.user.id === me.id) {
|
if (this.props.user.id === me.id) {
|
||||||
const title = (
|
const title = (
|
||||||
@@ -511,6 +543,7 @@ export default class UserItem extends React.Component {
|
|||||||
className='dropdown-menu member-menu'
|
className='dropdown-menu member-menu'
|
||||||
role='menu'
|
role='menu'
|
||||||
>
|
>
|
||||||
|
{removeFromTeam}
|
||||||
{makeAdmin}
|
{makeAdmin}
|
||||||
{makeMember}
|
{makeMember}
|
||||||
{makeActive}
|
{makeActive}
|
||||||
|
|||||||
@@ -39,17 +39,24 @@ class FilteredUserList extends React.Component {
|
|||||||
this.state = {
|
this.state = {
|
||||||
filter: '',
|
filter: '',
|
||||||
users: this.filterUsers(props.teamMembers, props.users),
|
users: this.filterUsers(props.teamMembers, props.users),
|
||||||
selected: 'team'
|
selected: 'team',
|
||||||
|
teamMembers: props.teamMembers
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUpdate(nextProps) {
|
componentWillReceiveProps(nextProps) {
|
||||||
// assume the user list is immutable
|
// assume the user list is immutable
|
||||||
if (this.props.users !== nextProps.users) {
|
if (this.props.users !== nextProps.users) {
|
||||||
this.setState({
|
this.setState({
|
||||||
users: this.filterUsers(nextProps.teamMembers, nextProps.users)
|
users: this.filterUsers(nextProps.teamMembers, nextProps.users)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.props.teamMembers !== nextProps.teamMembers) {
|
||||||
|
this.setState({
|
||||||
|
users: this.filterUsers(nextProps.teamMembers, nextProps.users)
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
@@ -70,6 +77,10 @@ class FilteredUserList extends React.Component {
|
|||||||
var filteredUsers = users.filter((user) => {
|
var filteredUsers = users.filter((user) => {
|
||||||
for (const index in teamMembers) {
|
for (const index in teamMembers) {
|
||||||
if (teamMembers.hasOwnProperty(index) && teamMembers[index].user_id === user.id) {
|
if (teamMembers.hasOwnProperty(index) && teamMembers[index].user_id === user.id) {
|
||||||
|
if (teamMembers[index].delete_at > 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
115
webapp/components/leave_team_modal.jsx
Обычный файл
115
webapp/components/leave_team_modal.jsx
Обычный файл
@@ -0,0 +1,115 @@
|
|||||||
|
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
|
||||||
|
// See License.txt for license information.
|
||||||
|
|
||||||
|
import Constants from 'utils/constants.jsx';
|
||||||
|
const ActionTypes = Constants.ActionTypes;
|
||||||
|
import * as GlobalActions from 'actions/global_actions.jsx';
|
||||||
|
import ModalStore from 'stores/modal_store.jsx';
|
||||||
|
import UserStore from 'stores/user_store.jsx';
|
||||||
|
|
||||||
|
import {intlShape, injectIntl, FormattedMessage} from 'react-intl';
|
||||||
|
|
||||||
|
import {Modal} from 'react-bootstrap';
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
class LeaveTeamModal extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.handleToggle = this.handleToggle.bind(this);
|
||||||
|
this.handleSubmit = this.handleSubmit.bind(this);
|
||||||
|
this.handleHide = this.handleHide.bind(this);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
show: false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
ModalStore.addModalListener(ActionTypes.TOGGLE_LEAVE_TEAM_MODAL, this.handleToggle);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
ModalStore.removeModalListener(ActionTypes.TOGGLE_LEAVE_TEAM_MODAL, this.handleToggle);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleToggle(value) {
|
||||||
|
this.setState({
|
||||||
|
show: value
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
handleSubmit() {
|
||||||
|
GlobalActions.emitLeaveTeam();
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
show: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
handleHide() {
|
||||||
|
this.setState({
|
||||||
|
show: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
var currentUser = UserStore.getCurrentUser();
|
||||||
|
|
||||||
|
if (currentUser != null) {
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
className='modal-confirm'
|
||||||
|
show={this.state.show}
|
||||||
|
onHide={this.handleHide}
|
||||||
|
>
|
||||||
|
<Modal.Header closeButton={false}>
|
||||||
|
<Modal.Title>
|
||||||
|
<FormattedMessage
|
||||||
|
id='leave_team_modal.title'
|
||||||
|
defaultMessage='Leave the team?'
|
||||||
|
/>
|
||||||
|
</Modal.Title>
|
||||||
|
</Modal.Header>
|
||||||
|
<Modal.Body>
|
||||||
|
<FormattedMessage
|
||||||
|
id='leave_team_modal.desc'
|
||||||
|
defaultMessage='You will be removed from all public channels and private groups. If the team is private you will not be able to rejoin the team. Are you sure?'
|
||||||
|
/>
|
||||||
|
</Modal.Body>
|
||||||
|
<Modal.Footer>
|
||||||
|
<button
|
||||||
|
type='button'
|
||||||
|
className='btn btn-default'
|
||||||
|
onClick={this.handleHide}
|
||||||
|
>
|
||||||
|
<FormattedMessage
|
||||||
|
id='leave_team_modal.no'
|
||||||
|
defaultMessage='No'
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type='button'
|
||||||
|
className='btn btn-danger'
|
||||||
|
onClick={this.handleSubmit}
|
||||||
|
>
|
||||||
|
<FormattedMessage
|
||||||
|
id='leave_team_modal.yes'
|
||||||
|
defaultMessage='Yes'
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
</Modal.Footer>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LeaveTeamModal.propTypes = {
|
||||||
|
intl: intlShape.isRequired
|
||||||
|
};
|
||||||
|
|
||||||
|
export default injectIntl(LeaveTeamModal);
|
||||||
@@ -236,6 +236,20 @@ export default class NavbarDropdown extends React.Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
teams.push(
|
||||||
|
<li key='leaveTeam_li'>
|
||||||
|
<a
|
||||||
|
href='#'
|
||||||
|
onClick={GlobalActions.showLeaveTeamModal}
|
||||||
|
>
|
||||||
|
<FormattedMessage
|
||||||
|
id='navbar_dropdown.leave'
|
||||||
|
defaultMessage='Leave Team'
|
||||||
|
/>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
|
||||||
if (this.state.teamMembers && this.state.teamMembers.length > 1) {
|
if (this.state.teamMembers && this.state.teamMembers.length > 1) {
|
||||||
teams.push(
|
teams.push(
|
||||||
<li
|
<li
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import RemovedFromChannelModal from 'components/removed_from_channel_modal.jsx';
|
|||||||
import RegisterAppModal from 'components/register_app_modal.jsx';
|
import RegisterAppModal from 'components/register_app_modal.jsx';
|
||||||
import ImportThemeModal from 'components/user_settings/import_theme_modal.jsx';
|
import ImportThemeModal from 'components/user_settings/import_theme_modal.jsx';
|
||||||
import InviteMemberModal from 'components/invite_member_modal.jsx';
|
import InviteMemberModal from 'components/invite_member_modal.jsx';
|
||||||
|
import LeaveTeamModal from 'components/leave_team_modal.jsx';
|
||||||
import SelectTeamModal from 'components/admin_console/select_team_modal.jsx';
|
import SelectTeamModal from 'components/admin_console/select_team_modal.jsx';
|
||||||
|
|
||||||
export default class NeedsTeam extends React.Component {
|
export default class NeedsTeam extends React.Component {
|
||||||
@@ -129,6 +130,7 @@ export default class NeedsTeam extends React.Component {
|
|||||||
<GetPublicLinkModal/>
|
<GetPublicLinkModal/>
|
||||||
<GetTeamInviteLinkModal/>
|
<GetTeamInviteLinkModal/>
|
||||||
<InviteMemberModal/>
|
<InviteMemberModal/>
|
||||||
|
<LeaveTeamModal/>
|
||||||
<ImportThemeModal/>
|
<ImportThemeModal/>
|
||||||
<TeamSettingsModal/>
|
<TeamSettingsModal/>
|
||||||
<MoreChannelsModal/>
|
<MoreChannelsModal/>
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ export default class TeamMembersDropdown extends React.Component {
|
|||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
this.handleMakeMember = this.handleMakeMember.bind(this);
|
this.handleMakeMember = this.handleMakeMember.bind(this);
|
||||||
|
this.handleRemoveFromTeam = this.handleRemoveFromTeam.bind(this);
|
||||||
this.handleMakeActive = this.handleMakeActive.bind(this);
|
this.handleMakeActive = this.handleMakeActive.bind(this);
|
||||||
this.handleMakeNotActive = this.handleMakeNotActive.bind(this);
|
this.handleMakeNotActive = this.handleMakeNotActive.bind(this);
|
||||||
this.handleMakeAdmin = this.handleMakeAdmin.bind(this);
|
this.handleMakeAdmin = this.handleMakeAdmin.bind(this);
|
||||||
@@ -52,6 +53,19 @@ export default class TeamMembersDropdown extends React.Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
handleRemoveFromTeam() {
|
||||||
|
Client.removeUserFromTeam(
|
||||||
|
'',
|
||||||
|
this.props.user.id,
|
||||||
|
() => {
|
||||||
|
AsyncClient.getTeamMembers(TeamStore.getCurrentId());
|
||||||
|
AsyncClient.getProfiles();
|
||||||
|
},
|
||||||
|
(err) => {
|
||||||
|
this.setState({serverError: err.message});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
handleMakeActive() {
|
handleMakeActive() {
|
||||||
Client.updateActive(this.props.user.id, true,
|
Client.updateActive(this.props.user.id, true,
|
||||||
() => {
|
() => {
|
||||||
@@ -171,6 +185,7 @@ export default class TeamMembersDropdown extends React.Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const me = UserStore.getCurrentUser();
|
||||||
let showMakeMember = teamMember.roles === 'admin' || user.roles === 'system_admin';
|
let showMakeMember = teamMember.roles === 'admin' || user.roles === 'system_admin';
|
||||||
let showMakeAdmin = teamMember.roles === '' && user.roles !== 'system_admin';
|
let showMakeAdmin = teamMember.roles === '' && user.roles !== 'system_admin';
|
||||||
let showMakeActive = false;
|
let showMakeActive = false;
|
||||||
@@ -225,6 +240,24 @@ export default class TeamMembersDropdown extends React.Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let removeFromTeam = null;
|
||||||
|
if (this.props.user.id !== me.id) {
|
||||||
|
removeFromTeam = (
|
||||||
|
<li role='presentation'>
|
||||||
|
<a
|
||||||
|
role='menuitem'
|
||||||
|
href='#'
|
||||||
|
onClick={this.handleRemoveFromTeam}
|
||||||
|
>
|
||||||
|
<FormattedMessage
|
||||||
|
id='team_members_dropdown.leave_team'
|
||||||
|
defaultMessage='Remove From Team'
|
||||||
|
/>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
let makeActive = null;
|
let makeActive = null;
|
||||||
if (showMakeActive) {
|
if (showMakeActive) {
|
||||||
// makeActive = (
|
// makeActive = (
|
||||||
@@ -260,7 +293,7 @@ export default class TeamMembersDropdown extends React.Component {
|
|||||||
// </li>
|
// </li>
|
||||||
// );
|
// );
|
||||||
}
|
}
|
||||||
const me = UserStore.getCurrentUser();
|
|
||||||
let makeDemoteModal = null;
|
let makeDemoteModal = null;
|
||||||
if (this.props.user.id === me.id) {
|
if (this.props.user.id === me.id) {
|
||||||
const title = (
|
const title = (
|
||||||
@@ -321,6 +354,7 @@ export default class TeamMembersDropdown extends React.Component {
|
|||||||
className='dropdown-menu member-menu'
|
className='dropdown-menu member-menu'
|
||||||
role='menu'
|
role='menu'
|
||||||
>
|
>
|
||||||
|
{removeFromTeam}
|
||||||
{makeAdmin}
|
{makeAdmin}
|
||||||
{makeMember}
|
{makeMember}
|
||||||
{makeActive}
|
{makeActive}
|
||||||
|
|||||||
@@ -1202,6 +1202,7 @@
|
|||||||
"navbar_dropdown.accountSettings": "Account Settings",
|
"navbar_dropdown.accountSettings": "Account Settings",
|
||||||
"navbar_dropdown.console": "System Console",
|
"navbar_dropdown.console": "System Console",
|
||||||
"navbar_dropdown.create": "Create a New Team",
|
"navbar_dropdown.create": "Create a New Team",
|
||||||
|
"navbar_dropdown.leave": "Leave Team",
|
||||||
"navbar_dropdown.emoji": "Custom Emoji",
|
"navbar_dropdown.emoji": "Custom Emoji",
|
||||||
"navbar_dropdown.help": "Help",
|
"navbar_dropdown.help": "Help",
|
||||||
"navbar_dropdown.integrations": "Integrations",
|
"navbar_dropdown.integrations": "Integrations",
|
||||||
@@ -1414,6 +1415,7 @@
|
|||||||
"team_members_dropdown.makeAdmin": "Make Team Admin",
|
"team_members_dropdown.makeAdmin": "Make Team Admin",
|
||||||
"team_members_dropdown.makeInactive": "Make Inactive",
|
"team_members_dropdown.makeInactive": "Make Inactive",
|
||||||
"team_members_dropdown.makeMember": "Make Member",
|
"team_members_dropdown.makeMember": "Make Member",
|
||||||
|
"team_members_dropdown.leave_team": "Remove From Team",
|
||||||
"team_members_dropdown.member": "Member",
|
"team_members_dropdown.member": "Member",
|
||||||
"team_members_dropdown.systemAdmin": "System Admin",
|
"team_members_dropdown.systemAdmin": "System Admin",
|
||||||
"team_members_dropdown.teamAdmin": "Team Admin",
|
"team_members_dropdown.teamAdmin": "Team Admin",
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
"keymirror": "0.1.1",
|
"keymirror": "0.1.1",
|
||||||
"marked": "mattermost/marked#12d2be4cdf54d4ec95fead934e18840b6a2c1a7b",
|
"marked": "mattermost/marked#12d2be4cdf54d4ec95fead934e18840b6a2c1a7b",
|
||||||
"match-at": "0.1.0",
|
"match-at": "0.1.0",
|
||||||
"mattermost": "mattermost/mattermost-javascript#18527e6c4a9aea69aa7845a62d9618b357faa4e7",
|
"mattermost": "mattermost/mattermost-javascript#c72a75ca4ac135e2d476fc048ef7adc450e6739f",
|
||||||
"object-assign": "4.1.0",
|
"object-assign": "4.1.0",
|
||||||
"perfect-scrollbar": "0.6.11",
|
"perfect-scrollbar": "0.6.11",
|
||||||
"react": "15.0.2",
|
"react": "15.0.2",
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ class ModalStoreClass extends EventEmitter {
|
|||||||
switch (type) {
|
switch (type) {
|
||||||
case ActionTypes.TOGGLE_IMPORT_THEME_MODAL:
|
case ActionTypes.TOGGLE_IMPORT_THEME_MODAL:
|
||||||
case ActionTypes.TOGGLE_INVITE_MEMBER_MODAL:
|
case ActionTypes.TOGGLE_INVITE_MEMBER_MODAL:
|
||||||
|
case ActionTypes.TOGGLE_LEAVE_TEAM_MODAL:
|
||||||
case ActionTypes.TOGGLE_DELETE_POST_MODAL:
|
case ActionTypes.TOGGLE_DELETE_POST_MODAL:
|
||||||
case ActionTypes.TOGGLE_GET_POST_LINK_MODAL:
|
case ActionTypes.TOGGLE_GET_POST_LINK_MODAL:
|
||||||
case ActionTypes.TOGGLE_GET_TEAM_INVITE_LINK_MODAL:
|
case ActionTypes.TOGGLE_GET_TEAM_INVITE_LINK_MODAL:
|
||||||
|
|||||||
@@ -139,6 +139,16 @@ class TeamStoreClass extends EventEmitter {
|
|||||||
this.team_members.push(member);
|
this.team_members.push(member);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
removeTeamMember(teamId) {
|
||||||
|
for (var index in this.team_members) {
|
||||||
|
if (this.team_members.hasOwnProperty(index)) {
|
||||||
|
if (this.team_members[index].team_id === teamId) {
|
||||||
|
Reflect.deleteProperty(this.team_members, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
getTeamMembers() {
|
getTeamMembers() {
|
||||||
return this.team_members;
|
return this.team_members;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -113,6 +113,7 @@ export default {
|
|||||||
|
|
||||||
TOGGLE_IMPORT_THEME_MODAL: null,
|
TOGGLE_IMPORT_THEME_MODAL: null,
|
||||||
TOGGLE_INVITE_MEMBER_MODAL: null,
|
TOGGLE_INVITE_MEMBER_MODAL: null,
|
||||||
|
TOGGLE_LEAVE_TEAM_MODAL: null,
|
||||||
TOGGLE_DELETE_POST_MODAL: null,
|
TOGGLE_DELETE_POST_MODAL: null,
|
||||||
TOGGLE_GET_POST_LINK_MODAL: null,
|
TOGGLE_GET_POST_LINK_MODAL: null,
|
||||||
TOGGLE_GET_TEAM_INVITE_LINK_MODAL: null,
|
TOGGLE_GET_TEAM_INVITE_LINK_MODAL: null,
|
||||||
@@ -160,6 +161,7 @@ export default {
|
|||||||
CHANNEL_VIEWED: 'channel_viewed',
|
CHANNEL_VIEWED: 'channel_viewed',
|
||||||
DIRECT_ADDED: 'direct_added',
|
DIRECT_ADDED: 'direct_added',
|
||||||
NEW_USER: 'new_user',
|
NEW_USER: 'new_user',
|
||||||
|
LEAVE_TEAM: 'leave_team',
|
||||||
USER_ADDED: 'user_added',
|
USER_ADDED: 'user_added',
|
||||||
USER_REMOVED: 'user_removed',
|
USER_REMOVED: 'user_removed',
|
||||||
TYPING: 'typing',
|
TYPING: 'typing',
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user