Automatic channel category sorting (#30866)

* Automatic channel category sorting

* Fix types

* AIed

* Fix issue where categories are updated for all users

* Move all logic to server, clean up

* PR feedback

* Fix lint

---------

Co-authored-by: Mattermost Build <build@mattermost.com>
Этот коммит содержится в:
Devin Binnie
2025-06-11 14:29:36 -04:00
коммит произвёл GitHub
родитель c6a11763a8
Коммит 25a4839a9e
17 изменённых файлов: 289 добавлений и 30 удалений

Просмотреть файл

@@ -181,6 +181,8 @@ func (a *App) CreateChannelWithUser(c request.CTX, channel *model.Channel, userI
return nil, err
}
a.addChannelToDefaultCategory(c, userID, channel)
var user *model.User
if user, err = a.GetUser(userID); err != nil {
return nil, err
@@ -208,6 +210,10 @@ func (a *App) RenameChannel(c request.CTX, channel *model.Channel, newChannelNam
return nil, model.NewAppError("RenameChannel", "api.channel.rename_channel.cant_rename_group_messages.app_error", nil, "", http.StatusBadRequest)
}
// Clean up the channel name and display name
newChannelName = strings.TrimSpace(newChannelName)
newDisplayName = strings.TrimSpace(newDisplayName)
channel.Name = newChannelName
if newDisplayName != "" {
channel.DisplayName = newDisplayName
@@ -222,6 +228,8 @@ func (a *App) RenameChannel(c request.CTX, channel *model.Channel, newChannelNam
}
func (a *App) CreateChannel(c request.CTX, channel *model.Channel, addMember bool) (*model.Channel, *model.AppError) {
a.handleChannelCategoryName(channel)
channel.DisplayName = strings.TrimSpace(channel.DisplayName)
sc, nErr := a.Srv().Store().Channel().Save(c, channel, *a.Config().TeamSettings.MaxChannelsPerTeam)
if nErr != nil {
@@ -864,11 +872,14 @@ func (a *App) PatchChannel(c request.CTX, channel *model.Channel, patch *model.C
oldChannelPurpose := channel.Purpose
channel.Patch(patch)
a.handleChannelCategoryName(channel)
channel, err := a.UpdateChannel(c, channel)
if err != nil {
return nil, err
}
a.addChannelToDefaultCategory(c, userID, channel)
if oldChannelDisplayName != channel.DisplayName {
if err = a.PostUpdateChannelDisplayNameMessage(c, userID, channel, oldChannelDisplayName, channel.DisplayName); err != nil {
c.Logger().Warn(err.Error())
@@ -1665,6 +1676,8 @@ func (a *App) AddUserToChannel(c request.CTX, user *model.User, channel *model.C
return nil, err
}
a.addChannelToDefaultCategory(c, user.Id, channel)
// We are sending separate websocket events to the user added and to the channel
// This is to get around potential cluster syncing issues where other nodes may not receive the most up to date channel members
message := model.NewWebSocketEvent(model.WebsocketEventUserAdded, "", channel.Id, "", map[string]bool{user.Id: true}, "")
@@ -3878,3 +3891,56 @@ func (a *App) ChannelAccessControlled(c request.CTX, channelID string) (bool, *m
return true, nil
}
func (a *App) handleChannelCategoryName(channel *model.Channel) {
if *a.Config().ExperimentalSettings.ExperimentalChannelCategorySorting && strings.Contains(channel.DisplayName, "/") {
parts := strings.Split(channel.DisplayName, "/")
channel.DisplayName = strings.TrimSpace(strings.Join(parts[1:], "/"))
channel.DefaultCategoryName = strings.TrimSpace(parts[0])
}
}
func (a *App) addChannelToDefaultCategory(c request.CTX, userID string, channel *model.Channel) {
// Add channel to default category if specified
if channel.DefaultCategoryName != "" && *a.Config().ExperimentalSettings.ExperimentalChannelCategorySorting {
// Get user's categories for this team
categories, err := a.GetSidebarCategoriesForTeamForUser(c, userID, channel.TeamId)
if err != nil {
mlog.Error("Failed to get sidebar categories", mlog.String("user_id", userID), mlog.String("team_id", channel.TeamId), mlog.Err(err))
return
}
// Find or create the category
var targetCategory *model.SidebarCategoryWithChannels
for _, category := range categories.Categories {
if category.Type == model.SidebarCategoryCustom && strings.EqualFold(category.DisplayName, channel.DefaultCategoryName) {
targetCategory = category
break
}
}
if targetCategory == nil {
// Create new category if it doesn't exist
targetCategory = &model.SidebarCategoryWithChannels{
SidebarCategory: model.SidebarCategory{
UserId: userID,
TeamId: channel.TeamId,
Type: model.SidebarCategoryCustom,
DisplayName: channel.DefaultCategoryName,
Sorting: model.SidebarCategorySortDefault,
},
Channels: []string{channel.Id},
}
_, err = a.CreateSidebarCategory(c, userID, channel.TeamId, targetCategory)
if err != nil {
mlog.Error("Failed to create default category", mlog.String("user_id", userID), mlog.String("team_id", channel.TeamId), mlog.String("category_name", channel.DefaultCategoryName), mlog.Err(err))
}
} else {
// Add channel to existing category
targetCategory.Channels = append([]string{channel.Id}, targetCategory.Channels...)
_, err = a.UpdateSidebarCategories(c, userID, channel.TeamId, []*model.SidebarCategoryWithChannels{targetCategory})
if err != nil {
mlog.Error("Failed to update default category", mlog.String("user_id", userID), mlog.String("team_id", channel.TeamId), mlog.String("category_name", channel.DefaultCategoryName), mlog.Err(err))
}
}
}
}