diff --git a/mattermost-plugin/webapp/src/index.tsx b/mattermost-plugin/webapp/src/index.tsx index 77eec4588..5e50d5b79 100644 --- a/mattermost-plugin/webapp/src/index.tsx +++ b/mattermost-plugin/webapp/src/index.tsx @@ -55,7 +55,6 @@ import wsClient, { ACTION_UPDATE_CATEGORY, ACTION_UPDATE_BOARD_CATEGORY, ACTION_UPDATE_BOARD, - ACTION_REORDER_CATEGORIES, } from './../../../webapp/src/wsclient' import manifest from './manifest' @@ -210,8 +209,6 @@ export default class Plugin { this.registry?.registerWebSocketEventHandler(`custom_${productID}_${ACTION_UPDATE_CLIENT_CONFIG}`, (e: any) => wsClient.updateClientConfigHandler(e.data)) this.registry?.registerWebSocketEventHandler(`custom_${productID}_${ACTION_UPDATE_CARD_LIMIT_TIMESTAMP}`, (e: any) => wsClient.updateCardLimitTimestampHandler(e.data)) this.registry?.registerWebSocketEventHandler(`custom_${productID}_${ACTION_UPDATE_SUBSCRIPTION}`, (e: any) => wsClient.updateSubscriptionHandler(e.data)) - this.registry?.registerWebSocketEventHandler(`custom_${productID}_${ACTION_REORDER_CATEGORIES}`, (e) => wsClient.updateHandler(e.data)) - this.registry?.registerWebSocketEventHandler('plugin_statuses_changed', (e: any) => wsClient.pluginStatusesChangedHandler(e.data)) this.registry?.registerPostTypeComponent('custom_cloud_upgrade_nudge', CloudUpgradeNudge) this.registry?.registerWebSocketEventHandler('preferences_changed', (e: any) => { diff --git a/server/api/categories.go b/server/api/categories.go index 9181c42d5..369b94e40 100644 --- a/server/api/categories.go +++ b/server/api/categories.go @@ -14,11 +14,9 @@ import ( func (a *API) registerCategoriesRoutes(r *mux.Router) { // Category APIs r.HandleFunc("/teams/{teamID}/categories", a.sessionRequired(a.handleCreateCategory)).Methods(http.MethodPost) - r.HandleFunc("/teams/{teamID}/categories/reorder", a.sessionRequired(a.handleReorderCategories)).Methods(http.MethodPut) r.HandleFunc("/teams/{teamID}/categories/{categoryID}", a.sessionRequired(a.handleUpdateCategory)).Methods(http.MethodPut) r.HandleFunc("/teams/{teamID}/categories/{categoryID}", a.sessionRequired(a.handleDeleteCategory)).Methods(http.MethodDelete) r.HandleFunc("/teams/{teamID}/categories", a.sessionRequired(a.handleGetUserCategoryBoards)).Methods(http.MethodGet) - r.HandleFunc("/teams/{teamID}/categories/{categoryID}/boards/reorder", a.sessionRequired(a.handleReorderCategoryBoards)).Methods(http.MethodPut) r.HandleFunc("/teams/{teamID}/categories/{categoryID}/boards/{boardID}", a.sessionRequired(a.handleUpdateCategoryBoard)).Methods(http.MethodPost) } @@ -355,7 +353,7 @@ func (a *API) handleUpdateCategoryBoard(w http.ResponseWriter, r *http.Request) userID := session.UserID // TODO: Check the category and the team matches - err := a.app.AddUpdateUserCategoryBoard(teamID, userID, map[string]string{boardID: categoryID}) + err := a.app.AddUpdateUserCategoryBoard(teamID, userID, categoryID, boardID) if err != nil { a.errorResponse(w, r, err) return @@ -364,160 +362,3 @@ func (a *API) handleUpdateCategoryBoard(w http.ResponseWriter, r *http.Request) jsonBytesResponse(w, http.StatusOK, []byte("ok")) auditRec.Success() } - -func (a *API) handleReorderCategories(w http.ResponseWriter, r *http.Request) { - // swagger:operation PUT /teams/{teamID}/categories/reorder handleReorderCategories - // - // Updated sidebar category order - // - // --- - // produces: - // - application/json - // parameters: - // - name: teamID - // in: path - // description: Team ID - // required: true - // type: string - // security: - // - BearerAuth: [] - // responses: - // '200': - // description: success - // default: - // description: internal error - // schema: - // "$ref": "#/definitions/ErrorResponse" - - vars := mux.Vars(r) - teamID := vars["teamID"] - - ctx := r.Context() - session := ctx.Value(sessionContextKey).(*model.Session) - userID := session.UserID - - if !a.permissions.HasPermissionToTeam(userID, teamID, model.PermissionViewTeam) { - a.errorResponse(w, r, model.NewErrPermission("access denied to category")) - return - } - - requestBody, err := io.ReadAll(r.Body) - if err != nil { - a.errorResponse(w, r, err) - return - } - - var newCategoryOrder []string - - err = json.Unmarshal(requestBody, &newCategoryOrder) - if err != nil { - a.errorResponse(w, r, err) - return - } - - auditRec := a.makeAuditRecord(r, "reorderCategories", audit.Fail) - defer a.audit.LogRecord(audit.LevelModify, auditRec) - - auditRec.AddMeta("TeamID", teamID) - auditRec.AddMeta("CategoryCount", len(newCategoryOrder)) - - updatedCategoryOrder, err := a.app.ReorderCategories(userID, teamID, newCategoryOrder) - if err != nil { - a.errorResponse(w, r, err) - return - } - - data, err := json.Marshal(updatedCategoryOrder) - if err != nil { - a.errorResponse(w, r, err) - return - } - - jsonBytesResponse(w, http.StatusOK, data) - auditRec.Success() -} - -func (a *API) handleReorderCategoryBoards(w http.ResponseWriter, r *http.Request) { - // swagger:operation PUT /teams/{teamID}/categories/{categoryID}/boards/reorder handleReorderCategoryBoards - // - // Updates order of boards inside a sidebar category - // - // --- - // produces: - // - application/json - // parameters: - // - name: teamID - // in: path - // description: Team ID - // required: true - // type: string - // - name: categoryID - // in: path - // description: Category ID - // required: true - // type: string - // security: - // - BearerAuth: [] - // responses: - // '200': - // description: success - // default: - // description: internal error - // schema: - // "$ref": "#/definitions/ErrorResponse" - - vars := mux.Vars(r) - teamID := vars["teamID"] - categoryID := vars["categoryID"] - - ctx := r.Context() - session := ctx.Value(sessionContextKey).(*model.Session) - userID := session.UserID - - if !a.permissions.HasPermissionToTeam(userID, teamID, model.PermissionViewTeam) { - a.errorResponse(w, r, model.NewErrPermission("access denied to category")) - return - } - - category, err := a.app.GetCategory(categoryID) - if err != nil { - a.errorResponse(w, r, err) - return - } - - if category.UserID != userID { - a.errorResponse(w, r, model.NewErrPermission("access denied to category")) - return - } - - requestBody, err := io.ReadAll(r.Body) - if err != nil { - a.errorResponse(w, r, err) - return - } - - var newBoardsOrder []string - err = json.Unmarshal(requestBody, &newBoardsOrder) - if err != nil { - a.errorResponse(w, r, err) - return - } - - auditRec := a.makeAuditRecord(r, "reorderCategoryBoards", audit.Fail) - defer a.audit.LogRecord(audit.LevelModify, auditRec) - - updatedBoardsOrder, err := a.app.ReorderCategoryBoards(userID, teamID, categoryID, newBoardsOrder) - if err != nil { - a.errorResponse(w, r, err) - return - } - - data, err := json.Marshal(updatedBoardsOrder) - if err != nil { - a.errorResponse(w, r, err) - return - } - - jsonBytesResponse(w, http.StatusOK, data) - auditRec.Success() -} diff --git a/server/app/boards.go b/server/app/boards.go index 533c74320..c65720ea6 100644 --- a/server/app/boards.go +++ b/server/app/boards.go @@ -175,7 +175,7 @@ func (a *App) setBoardCategoryFromSource(sourceBoardID, destinationBoardID, user // now that we have source board's category, // we send destination board to the same category - return a.AddUpdateUserCategoryBoard(teamID, userID, map[string]string{destinationBoardID: destinationCategoryID}) + return a.AddUpdateUserCategoryBoard(teamID, userID, destinationCategoryID, destinationBoardID) } func (a *App) DuplicateBoard(boardID, userID, toTeam string, asTemplate bool) (*model.BoardsAndBlocks, []*model.BoardMember, error) { @@ -327,13 +327,10 @@ func (a *App) addBoardsToDefaultCategory(userID, teamID string, boards []*model. return fmt.Errorf("%w userID: %s", errNoDefaultCategoryFound, userID) } - boardCategoryMapping := map[string]string{} for _, board := range boards { - boardCategoryMapping[board.ID] = defaultCategoryID - } - - if err := a.AddUpdateUserCategoryBoard(teamID, userID, boardCategoryMapping); err != nil { - return err + if err := a.AddUpdateUserCategoryBoard(teamID, userID, defaultCategoryID, board.ID); err != nil { + return err + } } return nil diff --git a/server/app/boards_test.go b/server/app/boards_test.go index 1ff160477..bac838d05 100644 --- a/server/app/boards_test.go +++ b/server/app/boards_test.go @@ -52,7 +52,7 @@ func TestAddMemberToBoard(t *testing.T) { }, }, }, nil) - th.Store.EXPECT().AddUpdateCategoryBoard("user_id_1", map[string]string{"board_id_1": "default_category_id"}).Return(nil) + th.Store.EXPECT().AddUpdateCategoryBoard("user_id_1", "default_category_id", "board_id_1").Return(nil) addedBoardMember, err := th.App.AddMemberToBoard(boardMember) require.NoError(t, err) @@ -126,7 +126,7 @@ func TestAddMemberToBoard(t *testing.T) { }, }, }, nil) - th.Store.EXPECT().AddUpdateCategoryBoard("user_id_1", map[string]string{"board_id_1": "default_category_id"}).Return(nil) + th.Store.EXPECT().AddUpdateCategoryBoard("user_id_1", "default_category_id", "board_id_1").Return(nil) addedBoardMember, err := th.App.AddMemberToBoard(boardMember) require.NoError(t, err) @@ -434,12 +434,9 @@ func TestBoardCategory(t *testing.T) { Name: "Boards", }, nil) th.Store.EXPECT().GetMembersForUser("user_id").Return([]*model.BoardMember{}, nil) - th.Store.EXPECT().GetBoardsForUserAndTeam("user_id", "team_id", false).Return([]*model.Board{}, nil) - th.Store.EXPECT().AddUpdateCategoryBoard("user_id", map[string]string{ - "board_id_1": "default_category_id", - "board_id_2": "default_category_id", - "board_id_3": "default_category_id", - }).Return(nil) + th.Store.EXPECT().AddUpdateCategoryBoard("user_id", "default_category_id", "board_id_1").Return(nil) + th.Store.EXPECT().AddUpdateCategoryBoard("user_id", "default_category_id", "board_id_2").Return(nil) + th.Store.EXPECT().AddUpdateCategoryBoard("user_id", "default_category_id", "board_id_3").Return(nil) boards := []*model.Board{ {ID: "board_id_1"}, @@ -452,55 +449,3 @@ func TestBoardCategory(t *testing.T) { }) }) } - -func TestDuplicateBoard(t *testing.T) { - th, tearDown := SetupTestHelper(t) - defer tearDown() - - t.Run("base case", func(t *testing.T) { - board := &model.Board{ - ID: "board_id_2", - Title: "Duplicated Board", - } - - block := &model.Block{ - ID: "block_id_1", - Type: "image", - } - - th.Store.EXPECT().DuplicateBoard("board_id_1", "user_id_1", "team_id_1", false).Return( - &model.BoardsAndBlocks{ - Boards: []*model.Board{ - board, - }, - Blocks: []*model.Block{ - block, - }, - }, - []*model.BoardMember{}, - nil, - ) - - th.Store.EXPECT().GetBoard("board_id_1").Return(&model.Board{}, nil) - - th.Store.EXPECT().GetUserCategoryBoards("user_id_1", "team_id_1").Return([]model.CategoryBoards{ - { - Category: model.Category{ - ID: "category_id_1", - Name: "Boards", - Type: "system", - }, - }, - }, nil).Times(2) - - th.Store.EXPECT().AddUpdateCategoryBoard("user_id_1", utils.Anything).Return(nil) - - // for WS change broadcast - th.Store.EXPECT().GetMembersForBoard(utils.Anything).Return([]*model.BoardMember{}, nil).Times(2) - - bab, members, err := th.App.DuplicateBoard("board_id_1", "user_id_1", "team_id_1", false) - assert.NoError(t, err) - assert.NotNil(t, bab) - assert.NotNil(t, members) - }) -} diff --git a/server/app/category.go b/server/app/category.go index 6fbd0bb10..032ded73b 100644 --- a/server/app/category.go +++ b/server/app/category.go @@ -2,21 +2,15 @@ package app import ( "errors" - "fmt" + "strings" "github.com/mattermost/focalboard/server/model" "github.com/mattermost/focalboard/server/utils" ) -var errCategoryNotFound = errors.New("category ID specified in input does not exist for user") -var errCategoriesLengthMismatch = errors.New("cannot update category order, passed list of categories different size than in database") var ErrCannotDeleteSystemCategory = errors.New("cannot delete a system category") var ErrCannotUpdateSystemCategory = errors.New("cannot update a system category") -func (a *App) GetCategory(categoryID string) (*model.Category, error) { - return a.store.GetCategory(categoryID) -} - func (a *App) CreateCategory(category *model.Category) (*model.Category, error) { category.Hydrate() if err := category.IsValid(); err != nil { @@ -40,8 +34,10 @@ func (a *App) CreateCategory(category *model.Category) (*model.Category, error) } func (a *App) UpdateCategory(category *model.Category) (*model.Category, error) { - category.Hydrate() - + // set to default category, UI doesn't create with Type + if strings.TrimSpace(category.Type) == "" { + category.Type = model.CategoryTypeCustom + } if err := category.IsValid(); err != nil { return nil, err } @@ -119,10 +115,6 @@ func (a *App) DeleteCategory(categoryID, userID, teamID string) (*model.Category return nil, ErrCannotDeleteSystemCategory } - if err = a.moveBoardsToDefaultCategory(userID, teamID, categoryID); err != nil { - return nil, err - } - if err = a.store.DeleteCategory(categoryID, userID, teamID); err != nil { return nil, err } @@ -138,109 +130,3 @@ func (a *App) DeleteCategory(categoryID, userID, teamID string) (*model.Category return deletedCategory, nil } - -func (a *App) moveBoardsToDefaultCategory(userID, teamID, sourceCategoryID string) error { - // we need a list of boards associated to this category - // so we can move them to user's default Boards category - categoryBoards, err := a.GetUserCategoryBoards(userID, teamID) - if err != nil { - return err - } - - var sourceCategoryBoards *model.CategoryBoards - defaultCategoryID := "" - - // iterate user's categories to find the source category - // and the default category. - // We need source category to get the list of its board - // and the default category to know its ID to - // move source category's boards to. - for i := range categoryBoards { - if categoryBoards[i].ID == sourceCategoryID { - sourceCategoryBoards = &categoryBoards[i] - } - - if categoryBoards[i].Name == defaultCategoryBoards { - defaultCategoryID = categoryBoards[i].ID - } - - // if both categories are found, no need to iterate furthur. - if sourceCategoryBoards != nil && defaultCategoryID != "" { - break - } - } - - if sourceCategoryBoards == nil { - return errCategoryNotFound - } - - if defaultCategoryID == "" { - return fmt.Errorf("moveBoardsToDefaultCategory: %w", errNoDefaultCategoryFound) - } - - boardCategoryMapping := map[string]string{} - - for _, boardID := range sourceCategoryBoards.BoardIDs { - boardCategoryMapping[boardID] = defaultCategoryID - } - - if err := a.AddUpdateUserCategoryBoard(teamID, userID, boardCategoryMapping); err != nil { - return fmt.Errorf("moveBoardsToDefaultCategory: %w", err) - } - - return nil -} - -func (a *App) ReorderCategories(userID, teamID string, newCategoryOrder []string) ([]string, error) { - if err := a.verifyNewCategoriesMatchExisting(userID, teamID, newCategoryOrder); err != nil { - return nil, err - } - - newOrder, err := a.store.ReorderCategories(userID, teamID, newCategoryOrder) - if err != nil { - return nil, err - } - - go func() { - a.wsAdapter.BroadcastCategoryReorder(teamID, userID, newOrder) - }() - - return newOrder, nil -} - -func (a *App) verifyNewCategoriesMatchExisting(userID, teamID string, newCategoryOrder []string) error { - existingCategories, err := a.store.GetUserCategories(userID, teamID) - if err != nil { - return err - } - - if len(newCategoryOrder) != len(existingCategories) { - return fmt.Errorf( - "%w length new categories: %d, length existing categories: %d, userID: %s, teamID: %s", - errCategoriesLengthMismatch, - len(newCategoryOrder), - len(existingCategories), - userID, - teamID, - ) - } - - existingCategoriesMap := map[string]bool{} - for _, category := range existingCategories { - existingCategoriesMap[category.ID] = true - } - - for _, newCategoryID := range newCategoryOrder { - if _, found := existingCategoriesMap[newCategoryID]; !found { - return fmt.Errorf( - "%w specified category ID: %s, userID: %s, teamID: %s", - errCategoryNotFound, - newCategoryID, - userID, - teamID, - ) - } - } - - return nil -} diff --git a/server/app/category_boards.go b/server/app/category_boards.go index 79728716f..39e68686a 100644 --- a/server/app/category_boards.go +++ b/server/app/category_boards.go @@ -1,7 +1,6 @@ package app import ( - "errors" "fmt" "github.com/mattermost/focalboard/server/model" @@ -9,10 +8,6 @@ import ( const defaultCategoryBoards = "Boards" -var errCategoryBoardsLengthMismatch = errors.New("cannot update category boards order, passed list of categories boards different size than in database") -var errBoardNotFoundInCategory = errors.New("specified board ID not found in specified category ID") -var errBoardMembershipNotFound = errors.New("board membership not found for user's board") - func (a *App) GetUserCategoryBoards(userID, teamID string) ([]model.CategoryBoards, error) { categoryBoards, err := a.store.GetUserCategoryBoards(userID, teamID) if err != nil { @@ -58,7 +53,6 @@ func (a *App) createBoardsCategory(userID, teamID string, existingCategoryBoards TeamID: teamID, Collapsed: false, Type: model.CategoryTypeSystem, - SortOrder: len(existingCategoryBoards) * model.CategoryBoardsSortOrderGap, } createdCategory, err := a.CreateCategory(&category) if err != nil { @@ -67,40 +61,23 @@ func (a *App) createBoardsCategory(userID, teamID string, existingCategoryBoards // once the category is created, we need to move all boards which do not // belong to any category, into this category. - boardMembers, err := a.GetMembersForUser(userID) if err != nil { return nil, fmt.Errorf("createBoardsCategory error fetching user's board memberships: %w", err) } - boardMemberByBoardID := map[string]*model.BoardMember{} - for _, boardMember := range boardMembers { - boardMemberByBoardID[boardMember.BoardID] = boardMember - } - createdCategoryBoards := &model.CategoryBoards{ Category: *createdCategory, BoardIDs: []string{}, } - // get user's current team's baords - userTeamBoards, err := a.GetBoardsForUserAndTeam(userID, teamID, false) - if err != nil { - return nil, fmt.Errorf("createBoardsCategory error fetching user's team's boards: %w", err) - } - - for _, board := range userTeamBoards { - boardMembership, ok := boardMemberByBoardID[board.ID] - if !ok { - return nil, fmt.Errorf("createBoardsCategory: %w", errBoardMembershipNotFound) - } - + for _, bm := range boardMembers { // boards with implicit access (aka synthetic membership), // should show up in LHS only when openign them explicitelly. // So we don't process any synthetic membership boards // and only add boards with explicit access to, to the the LHS, // for example, if a user explicitelly added another user to a board. - if boardMembership.Synthetic { + if bm.Synthetic { continue } @@ -108,7 +85,7 @@ func (a *App) createBoardsCategory(userID, teamID string, existingCategoryBoards for _, categoryBoard := range existingCategoryBoards { for _, boardID := range categoryBoard.BoardIDs { - if boardID == board.ID { + if boardID == bm.BoardID { belongsToCategory = true break } @@ -122,111 +99,36 @@ func (a *App) createBoardsCategory(userID, teamID string, existingCategoryBoards } if !belongsToCategory { - if err := a.AddUpdateUserCategoryBoard(teamID, userID, map[string]string{board.ID: createdCategory.ID}); err != nil { + if err := a.AddUpdateUserCategoryBoard(teamID, userID, createdCategory.ID, bm.BoardID); err != nil { + // ToDo: por siaca + // if err := a.AddUpdateUserCategoryBoard(teamID, userID, createdCategory.ID, board.ID); err != nil { + // --- return nil, fmt.Errorf("createBoardsCategory failed to add category-less board to the default category, defaultCategoryID: %s, error: %w", createdCategory.ID, err) } - createdCategoryBoards.BoardIDs = append(createdCategoryBoards.BoardIDs, board.ID) + createdCategoryBoards.BoardIDs = append(createdCategoryBoards.BoardIDs, bm.BoardID) } } return createdCategoryBoards, nil } -func (a *App) AddUpdateUserCategoryBoard(teamID, userID string, boardCategoryMapping map[string]string) error { - err := a.store.AddUpdateCategoryBoard(userID, boardCategoryMapping) +func (a *App) AddUpdateUserCategoryBoard(teamID, userID, categoryID, boardID string) error { + err := a.store.AddUpdateCategoryBoard(userID, categoryID, boardID) if err != nil { return err } - wsPayload := make([]*model.BoardCategoryWebsocketData, len(boardCategoryMapping)) - i := 0 - for boardID, categoryID := range boardCategoryMapping { - wsPayload[i] = &model.BoardCategoryWebsocketData{ - BoardID: boardID, - CategoryID: categoryID, - } - i++ - } - a.blockChangeNotifier.Enqueue(func() error { a.wsAdapter.BroadcastCategoryBoardChange( teamID, userID, - wsPayload, - ) + model.BoardCategoryWebsocketData{ + BoardID: boardID, + CategoryID: categoryID, + }) return nil }) return nil } - -func (a *App) ReorderCategoryBoards(userID, teamID, categoryID string, newBoardsOrder []string) ([]string, error) { - if err := a.verifyNewCategoryBoardsMatchExisting(userID, teamID, categoryID, newBoardsOrder); err != nil { - return nil, err - } - - newOrder, err := a.store.ReorderCategoryBoards(categoryID, newBoardsOrder) - if err != nil { - return nil, err - } - - go func() { - a.wsAdapter.BroadcastCategoryBoardsReorder(teamID, userID, categoryID, newOrder) - }() - - return newOrder, nil -} - -func (a *App) verifyNewCategoryBoardsMatchExisting(userID, teamID, categoryID string, newBoardsOrder []string) error { - // this function is to ensure that we don't miss specifying - // all boards of the category while reordering. - existingCategoryBoards, err := a.GetUserCategoryBoards(userID, teamID) - if err != nil { - return err - } - - var targetCategoryBoards *model.CategoryBoards - for i := range existingCategoryBoards { - if existingCategoryBoards[i].Category.ID == categoryID { - targetCategoryBoards = &existingCategoryBoards[i] - break - } - } - - if targetCategoryBoards == nil { - return fmt.Errorf("%w categoryID: %s", errCategoryNotFound, categoryID) - } - - if len(targetCategoryBoards.BoardIDs) != len(newBoardsOrder) { - return fmt.Errorf( - "%w length new category boards: %d, length existing category boards: %d, userID: %s, teamID: %s, categoryID: %s", - errCategoryBoardsLengthMismatch, - len(newBoardsOrder), - len(targetCategoryBoards.BoardIDs), - userID, - teamID, - categoryID, - ) - } - - existingBoardMap := map[string]bool{} - for _, boardID := range targetCategoryBoards.BoardIDs { - existingBoardMap[boardID] = true - } - - for _, boardID := range newBoardsOrder { - if _, found := existingBoardMap[boardID]; !found { - return fmt.Errorf( - "%w board ID: %s, category ID: %s, userID: %s, teamID: %s", - errBoardNotFoundInCategory, - boardID, - categoryID, - userID, - teamID, - ) - } - } - - return nil -} diff --git a/server/app/category_boards_test.go b/server/app/category_boards_test.go index e495a8ff2..7544a856d 100644 --- a/server/app/category_boards_test.go +++ b/server/app/category_boards_test.go @@ -21,20 +21,6 @@ func TestGetUserCategoryBoards(t *testing.T) { Name: "Boards", }, nil) - board1 := &model.Board{ - ID: "board_id_1", - } - - board2 := &model.Board{ - ID: "board_id_2", - } - - board3 := &model.Board{ - ID: "board_id_3", - } - - th.Store.EXPECT().GetBoardsForUserAndTeam("user_id", "team_id", false).Return([]*model.Board{board1, board2, board3}, nil) - th.Store.EXPECT().GetMembersForUser("user_id").Return([]*model.BoardMember{ { BoardID: "board_id_1", @@ -49,9 +35,10 @@ func TestGetUserCategoryBoards(t *testing.T) { Synthetic: false, }, }, nil) - th.Store.EXPECT().AddUpdateCategoryBoard("user_id", map[string]string{"board_id_1": "boards_category_id"}).Return(nil) - th.Store.EXPECT().AddUpdateCategoryBoard("user_id", map[string]string{"board_id_2": "boards_category_id"}).Return(nil) - th.Store.EXPECT().AddUpdateCategoryBoard("user_id", map[string]string{"board_id_3": "boards_category_id"}).Return(nil) + + th.Store.EXPECT().AddUpdateCategoryBoard("user_id", "boards_category_id", "board_id_1").Return(nil) + th.Store.EXPECT().AddUpdateCategoryBoard("user_id", "boards_category_id", "board_id_2").Return(nil) + th.Store.EXPECT().AddUpdateCategoryBoard("user_id", "boards_category_id", "board_id_3").Return(nil) categoryBoards, err := th.App.GetUserCategoryBoards("user_id", "team_id") assert.NoError(t, err) @@ -72,7 +59,6 @@ func TestGetUserCategoryBoards(t *testing.T) { }, nil) th.Store.EXPECT().GetMembersForUser("user_id").Return([]*model.BoardMember{}, nil) - th.Store.EXPECT().GetBoardsForUserAndTeam("user_id", "team_id", false).Return([]*model.Board{}, nil) categoryBoards, err := th.App.GetUserCategoryBoards("user_id", "team_id") assert.NoError(t, err) @@ -108,7 +94,6 @@ func TestCreateBoardsCategory(t *testing.T) { Type: "system", Name: "Boards", }, nil) - th.Store.EXPECT().GetBoardsForUserAndTeam("user_id", "team_id", false).Return([]*model.Board{}, nil) th.Store.EXPECT().GetMembersForUser("user_id").Return([]*model.BoardMember{}, nil) existingCategoryBoards := []model.CategoryBoards{} @@ -126,7 +111,6 @@ func TestCreateBoardsCategory(t *testing.T) { Type: "system", Name: "Boards", }, nil) - th.Store.EXPECT().GetBoardsForUserAndTeam("user_id", "team_id", false).Return([]*model.Board{}, nil) th.Store.EXPECT().GetMembersForUser("user_id").Return([]*model.BoardMember{ { BoardID: "board_id_1", @@ -160,17 +144,6 @@ func TestCreateBoardsCategory(t *testing.T) { Type: "system", Name: "Boards", }, nil) - - board1 := &model.Board{ - ID: "board_id_1", - } - board2 := &model.Board{ - ID: "board_id_2", - } - board3 := &model.Board{ - ID: "board_id_3", - } - th.Store.EXPECT().GetBoardsForUserAndTeam("user_id", "team_id", false).Return([]*model.Board{board1, board2, board3}, nil) th.Store.EXPECT().GetMembersForUser("user_id").Return([]*model.BoardMember{ { BoardID: "board_id_1", @@ -185,9 +158,9 @@ func TestCreateBoardsCategory(t *testing.T) { Synthetic: false, }, }, nil) - th.Store.EXPECT().AddUpdateCategoryBoard("user_id", map[string]string{"board_id_1": "boards_category_id"}).Return(nil) - th.Store.EXPECT().AddUpdateCategoryBoard("user_id", map[string]string{"board_id_2": "boards_category_id"}).Return(nil) - th.Store.EXPECT().AddUpdateCategoryBoard("user_id", map[string]string{"board_id_3": "boards_category_id"}).Return(nil) + th.Store.EXPECT().AddUpdateCategoryBoard("user_id", "boards_category_id", "board_id_1").Return(nil) + th.Store.EXPECT().AddUpdateCategoryBoard("user_id", "boards_category_id", "board_id_2").Return(nil) + th.Store.EXPECT().AddUpdateCategoryBoard("user_id", "boards_category_id", "board_id_3").Return(nil) existingCategoryBoards := []model.CategoryBoards{} boardsCategory, err := th.App.createBoardsCategory("user_id", "team_id", existingCategoryBoards) @@ -207,11 +180,6 @@ func TestCreateBoardsCategory(t *testing.T) { Type: "system", Name: "Boards", }, nil) - - board1 := &model.Board{ - ID: "board_id_1", - } - th.Store.EXPECT().GetBoardsForUserAndTeam("user_id", "team_id", false).Return([]*model.Board{board1}, nil) th.Store.EXPECT().GetMembersForUser("user_id").Return([]*model.BoardMember{ { BoardID: "board_id_1", @@ -226,7 +194,7 @@ func TestCreateBoardsCategory(t *testing.T) { Synthetic: true, }, }, nil) - th.Store.EXPECT().AddUpdateCategoryBoard("user_id", map[string]string{"board_id_1": "boards_category_id"}).Return(nil) + th.Store.EXPECT().AddUpdateCategoryBoard("user_id", "boards_category_id", "board_id_1").Return(nil) existingCategoryBoards := []model.CategoryBoards{} boardsCategory, err := th.App.createBoardsCategory("user_id", "team_id", existingCategoryBoards) @@ -240,54 +208,3 @@ func TestCreateBoardsCategory(t *testing.T) { assert.Equal(t, 1, len(boardsCategory.BoardIDs)) }) } - -func TestReorderCategoryBoards(t *testing.T) { - th, tearDown := SetupTestHelper(t) - defer tearDown() - - t.Run("base case", func(t *testing.T) { - th.Store.EXPECT().GetUserCategoryBoards("user_id", "team_id").Return([]model.CategoryBoards{ - { - Category: model.Category{ID: "category_id_1", Name: "Category 1"}, - BoardIDs: []string{"board_id_1", "board_id_2"}, - }, - { - Category: model.Category{ID: "category_id_2", Name: "Boards", Type: "system"}, - BoardIDs: []string{"board_id_3"}, - }, - { - Category: model.Category{ID: "category_id_3", Name: "Category 3"}, - BoardIDs: []string{}, - }, - }, nil) - - th.Store.EXPECT().ReorderCategoryBoards("category_id_1", []string{"board_id_2", "board_id_1"}).Return([]string{"board_id_2", "board_id_1"}, nil) - - newOrder, err := th.App.ReorderCategoryBoards("user_id", "team_id", "category_id_1", []string{"board_id_2", "board_id_1"}) - assert.NoError(t, err) - assert.Equal(t, 2, len(newOrder)) - assert.Equal(t, "board_id_2", newOrder[0]) - assert.Equal(t, "board_id_1", newOrder[1]) - }) - - t.Run("not specifying all boards", func(t *testing.T) { - th.Store.EXPECT().GetUserCategoryBoards("user_id", "team_id").Return([]model.CategoryBoards{ - { - Category: model.Category{ID: "category_id_1", Name: "Category 1"}, - BoardIDs: []string{"board_id_1", "board_id_2", "board_id_3"}, - }, - { - Category: model.Category{ID: "category_id_2", Name: "Boards", Type: "system"}, - BoardIDs: []string{"board_id_3"}, - }, - { - Category: model.Category{ID: "category_id_3", Name: "Category 3"}, - BoardIDs: []string{}, - }, - }, nil) - - newOrder, err := th.App.ReorderCategoryBoards("user_id", "team_id", "category_id_1", []string{"board_id_2", "board_id_1"}) - assert.Error(t, err) - assert.Nil(t, newOrder) - }) -} diff --git a/server/app/category_test.go b/server/app/category_test.go index 34588aad5..191b18363 100644 --- a/server/app/category_test.go +++ b/server/app/category_test.go @@ -92,14 +92,6 @@ func TestUpdateCategory(t *testing.T) { }) t.Run("updating invalid category", func(t *testing.T) { - th.Store.EXPECT().GetCategory(utils.Anything).Return(&model.Category{ - ID: "category_id_1", - Name: "Category", - TeamID: "team_id_1", - UserID: "user_id_1", - Type: "custom", - }, nil) - category := &model.Category{ ID: "category_id_1", Name: "Name", @@ -268,33 +260,6 @@ func TestDeleteCategory(t *testing.T) { DeleteAt: 10000, }, nil) - th.Store.EXPECT().GetUserCategoryBoards("user_id_1", "team_id_1").Return([]model.CategoryBoards{ - { - Category: model.Category{ - ID: "category_id_default", - DeleteAt: 0, - UserID: "user_id_1", - TeamID: "team_id_1", - Type: "default", - Name: "Boards", - }, - BoardIDs: []string{}, - }, - { - Category: model.Category{ - ID: "category_id_1", - DeleteAt: 0, - UserID: "user_id_1", - TeamID: "team_id_1", - Type: "custom", - Name: "Category 1", - }, - BoardIDs: []string{}, - }, - }, nil) - - th.Store.EXPECT().AddUpdateCategoryBoard("user_id_1", utils.Anything).Return(nil) - deletedCategory, err := th.App.DeleteCategory("category_id_1", "user_id_1", "team_id_1") assert.NotNil(t, deletedCategory) assert.NoError(t, err) @@ -328,171 +293,3 @@ func TestDeleteCategory(t *testing.T) { assert.Error(t, err) }) } - -func TestMoveBoardsToDefaultCategory(t *testing.T) { - th, tearDown := SetupTestHelper(t) - defer tearDown() - - t.Run("When default category already exists", func(t *testing.T) { - th.Store.EXPECT().GetUserCategoryBoards("user_id", "team_id").Return([]model.CategoryBoards{ - { - Category: model.Category{ - ID: "category_id_1", - Name: "Boards", - Type: "system", - }, - }, - { - Category: model.Category{ - ID: "category_id_2", - Name: "Custom Category 1", - Type: "custom", - }, - }, - }, nil) - - th.Store.EXPECT().AddUpdateCategoryBoard("user_id", utils.Anything).Return(nil) - - err := th.App.moveBoardsToDefaultCategory("user_id", "team_id", "category_id_2") - assert.NoError(t, err) - }) - - t.Run("When default category doesn't already exists", func(t *testing.T) { - th.Store.EXPECT().GetUserCategoryBoards("user_id", "team_id").Return([]model.CategoryBoards{ - { - Category: model.Category{ - ID: "category_id_2", - Name: "Custom Category 1", - Type: "custom", - }, - }, - }, nil) - - th.Store.EXPECT().CreateCategory(utils.Anything).Return(nil) - th.Store.EXPECT().GetCategory(utils.Anything).Return(&model.Category{ - ID: "default_category_id", - Name: "Boards", - Type: "system", - }, nil) - th.Store.EXPECT().GetMembersForUser("user_id").Return([]*model.BoardMember{}, nil) - th.Store.EXPECT().GetBoardsForUserAndTeam("user_id", "team_id", false).Return([]*model.Board{}, nil) - th.Store.EXPECT().AddUpdateCategoryBoard("user_id", utils.Anything).Return(nil) - - err := th.App.moveBoardsToDefaultCategory("user_id", "team_id", "category_id_2") - assert.NoError(t, err) - }) -} - -func TestReorderCategories(t *testing.T) { - th, tearDown := SetupTestHelper(t) - defer tearDown() - - t.Run("base case", func(t *testing.T) { - th.Store.EXPECT().GetUserCategories("user_id", "team_id").Return([]model.Category{ - { - ID: "category_id_1", - Name: "Boards", - Type: "system", - }, - { - ID: "category_id_2", - Name: "Category 2", - Type: "custom", - }, - { - ID: "category_id_3", - Name: "Category 3", - Type: "custom", - }, - }, nil) - - th.Store.EXPECT().ReorderCategories("user_id", "team_id", []string{"category_id_2", "category_id_3", "category_id_1"}). - Return([]string{"category_id_2", "category_id_3", "category_id_1"}, nil) - - newOrder, err := th.App.ReorderCategories("user_id", "team_id", []string{"category_id_2", "category_id_3", "category_id_1"}) - assert.NoError(t, err) - assert.Equal(t, 3, len(newOrder)) - }) - - t.Run("not specifying all categories should fail", func(t *testing.T) { - th.Store.EXPECT().GetUserCategories("user_id", "team_id").Return([]model.Category{ - { - ID: "category_id_1", - Name: "Boards", - Type: "system", - }, - { - ID: "category_id_2", - Name: "Category 2", - Type: "custom", - }, - { - ID: "category_id_3", - Name: "Category 3", - Type: "custom", - }, - }, nil) - - newOrder, err := th.App.ReorderCategories("user_id", "team_id", []string{"category_id_2", "category_id_3"}) - assert.Error(t, err) - assert.Nil(t, newOrder) - }) -} - -func TestVerifyNewCategoriesMatchExisting(t *testing.T) { - th, tearDown := SetupTestHelper(t) - defer tearDown() - - t.Run("base case", func(t *testing.T) { - th.Store.EXPECT().GetUserCategories("user_id", "team_id").Return([]model.Category{ - { - ID: "category_id_1", - Name: "Boards", - Type: "system", - }, - { - ID: "category_id_2", - Name: "Category 2", - Type: "custom", - }, - { - ID: "category_id_3", - Name: "Category 3", - Type: "custom", - }, - }, nil) - - err := th.App.verifyNewCategoriesMatchExisting("user_id", "team_id", []string{ - "category_id_2", - "category_id_3", - "category_id_1", - }) - assert.NoError(t, err) - }) - - t.Run("different category counts", func(t *testing.T) { - th.Store.EXPECT().GetUserCategories("user_id", "team_id").Return([]model.Category{ - { - ID: "category_id_1", - Name: "Boards", - Type: "system", - }, - { - ID: "category_id_2", - Name: "Category 2", - Type: "custom", - }, - { - ID: "category_id_3", - Name: "Category 3", - Type: "custom", - }, - }, nil) - - err := th.App.verifyNewCategoriesMatchExisting("user_id", "team_id", []string{ - "category_id_2", - "category_id_3", - }) - assert.Error(t, err) - }) -} diff --git a/server/app/import_test.go b/server/app/import_test.go index 6ec7e63de..de256e643 100644 --- a/server/app/import_test.go +++ b/server/app/import_test.go @@ -55,9 +55,8 @@ func TestApp_ImportArchive(t *testing.T) { ID: "boards_category_id", Name: "Boards", }, nil) - th.Store.EXPECT().GetBoardsForUserAndTeam("user", "test-team", false).Return([]*model.Board{}, nil) th.Store.EXPECT().GetMembersForUser("user").Return([]*model.BoardMember{}, nil) - th.Store.EXPECT().AddUpdateCategoryBoard("user", utils.Anything).Return(nil) + th.Store.EXPECT().AddUpdateCategoryBoard("user", "boards_category_id", utils.Anything).Return(nil) err := th.App.ImportArchive(r, opts) require.NoError(t, err, "import archive should not fail") diff --git a/server/app/onboarding_test.go b/server/app/onboarding_test.go index 29c2597e2..ed95fa85a 100644 --- a/server/app/onboarding_test.go +++ b/server/app/onboarding_test.go @@ -77,8 +77,7 @@ func TestPrepareOnboardingTour(t *testing.T) { ID: "boards_category", Name: "Boards", }, nil) - th.Store.EXPECT().GetBoardsForUserAndTeam("user_id_1", teamID, false).Return([]*model.Board{}, nil) - th.Store.EXPECT().AddUpdateCategoryBoard("user_id_1", map[string]string{"board_id_2": "boards_category_id"}).Return(nil) + th.Store.EXPECT().AddUpdateCategoryBoard("user_id_1", "boards_category_id", "board_id_2").Return(nil) teamID, boardID, err := th.App.PrepareOnboardingTour(userID, teamID) assert.NoError(t, err) @@ -121,7 +120,7 @@ func TestCreateWelcomeBoard(t *testing.T) { Category: model.Category{ID: "boards_category_id", Name: "Boards"}, }, }, nil).Times(2) - th.Store.EXPECT().AddUpdateCategoryBoard("user_id_1", map[string]string{"board_id_1": "boards_category_id"}).Return(nil) + th.Store.EXPECT().AddUpdateCategoryBoard("user_id_1", "boards_category_id", "board_id_1").Return(nil) boardID, err := th.App.createWelcomeBoard(userID, teamID) assert.Nil(t, err) diff --git a/server/client/client.go b/server/client/client.go index 3a7ff2487..b28aa39fd 100644 --- a/server/client/client.go +++ b/server/client/client.go @@ -443,15 +443,6 @@ func (c *Client) CreateCategory(category model.Category) (*model.Category, *Resp return model.CategoryFromJSON(r.Body), BuildResponse(r) } -func (c *Client) DeleteCategory(teamID, categoryID string) *Response { - r, err := c.DoAPIDelete(c.GetTeamRoute(teamID)+"/categories/"+categoryID, "") - if err != nil { - return BuildErrorResponse(r, err) - } - - return BuildResponse(r) -} - func (c *Client) UpdateCategoryBoard(teamID, categoryID, boardID string) *Response { r, err := c.DoAPIPost(fmt.Sprintf("%s/categories/%s/boards/%s", c.GetTeamRoute(teamID), categoryID, boardID), "") if err != nil { @@ -474,30 +465,6 @@ func (c *Client) GetUserCategoryBoards(teamID string) ([]model.CategoryBoards, * return categoryBoards, BuildResponse(r) } -func (c *Client) ReorderCategories(teamID string, newOrder []string) ([]string, *Response) { - r, err := c.DoAPIPut(c.GetTeamRoute(teamID)+"/categories/reorder", toJSON(newOrder)) - if err != nil { - return nil, BuildErrorResponse(r, err) - } - defer closeBody(r) - - var updatedCategoryOrder []string - _ = json.NewDecoder(r.Body).Decode(&updatedCategoryOrder) - return updatedCategoryOrder, BuildResponse(r) -} - -func (c *Client) ReorderCategoryBoards(teamID, categoryID string, newOrder []string) ([]string, *Response) { - r, err := c.DoAPIPut(c.GetTeamRoute(teamID)+"/categories/"+categoryID+"/reorder", toJSON(newOrder)) - if err != nil { - return nil, BuildErrorResponse(r, err) - } - defer closeBody(r) - - var updatedBoardsOrder []string - _ = json.NewDecoder(r.Body).Decode(&updatedBoardsOrder) - return updatedBoardsOrder, BuildResponse(r) -} - func (c *Client) PatchBoardsAndBlocks(pbab *model.PatchBoardsAndBlocks) (*model.BoardsAndBlocks, *Response) { r, err := c.DoAPIPatch(c.GetBoardsAndBlocksRoute(), toJSON(pbab)) if err != nil { diff --git a/server/integrationtests/clienttestlib.go b/server/integrationtests/clienttestlib.go index 46607e38c..a26f62b73 100644 --- a/server/integrationtests/clienttestlib.go +++ b/server/integrationtests/clienttestlib.go @@ -457,17 +457,6 @@ func (th *TestHelper) CreateBoard(teamID string, boardType model.BoardType) *mod return board } -func (th *TestHelper) CreateCategory(category model.Category) *model.Category { - cat, resp := th.Client.CreateCategory(category) - th.CheckOK(resp) - return cat -} - -func (th *TestHelper) UpdateCategoryBoard(teamID, categoryID, boardID string) { - response := th.Client.UpdateCategoryBoard(teamID, categoryID, boardID) - th.CheckOK(response) -} - func (th *TestHelper) CreateBoardAndCards(teamdID string, boardType model.BoardType, numCards int) (*model.Board, []*model.Card) { board := th.CreateBoard(teamdID, boardType) cards := make([]*model.Card, 0, numCards) @@ -493,17 +482,6 @@ func (th *TestHelper) MakeCardProps(count int) map[string]any { return props } -func (th *TestHelper) GetUserCategoryBoards(teamID string) []model.CategoryBoards { - categoryBoards, response := th.Client.GetUserCategoryBoards(teamID) - th.CheckOK(response) - return categoryBoards -} - -func (th *TestHelper) DeleteCategory(teamID, categoryID string) { - response := th.Client.DeleteCategory(teamID, categoryID) - th.CheckOK(response) -} - func (th *TestHelper) GetUser1() *model.User { return th.Me(th.Client) } diff --git a/server/integrationtests/sidebar_test.go b/server/integrationtests/sidebar_test.go deleted file mode 100644 index 976f1aa9c..000000000 --- a/server/integrationtests/sidebar_test.go +++ /dev/null @@ -1,54 +0,0 @@ -package integrationtests - -import ( - "testing" - - "github.com/mattermost/focalboard/server/model" - "github.com/stretchr/testify/require" -) - -func TestSidebar(t *testing.T) { - th := SetupTestHelperWithToken(t).Start() - defer th.TearDown() - - // we'll create a new board. - // The board should end up in a default "Boards" category - board := th.CreateBoard("team-id", "O") - - categoryBoards := th.GetUserCategoryBoards("team-id") - require.Equal(t, 1, len(categoryBoards)) - require.Equal(t, "Boards", categoryBoards[0].Name) - require.Equal(t, 1, len(categoryBoards[0].BoardIDs)) - require.Equal(t, board.ID, categoryBoards[0].BoardIDs[0]) - - // create a new category, a new board - // and move that board into the new category - board2 := th.CreateBoard("team-id", "O") - category := th.CreateCategory(model.Category{ - Name: "Category 2", - TeamID: "team-id", - UserID: "single-user", - }) - th.UpdateCategoryBoard("team-id", category.ID, board2.ID) - - categoryBoards = th.GetUserCategoryBoards("team-id") - // now there should be two categories - boards and the one - // we created just now - require.Equal(t, 2, len(categoryBoards)) - - // the newly created category should be the first one array - // as new categories end up on top in LHS - require.Equal(t, "Category 2", categoryBoards[0].Name) - require.Equal(t, 1, len(categoryBoards[0].BoardIDs)) - require.Equal(t, board2.ID, categoryBoards[0].BoardIDs[0]) - - // now we'll delete the custom category we created, "Category 2" - // and all it's boards should get moved to the Boards category - th.DeleteCategory("team-id", category.ID) - categoryBoards = th.GetUserCategoryBoards("team-id") - require.Equal(t, 1, len(categoryBoards)) - require.Equal(t, "Boards", categoryBoards[0].Name) - require.Equal(t, 2, len(categoryBoards[0].BoardIDs)) - require.Contains(t, categoryBoards[0].BoardIDs, board.ID) - require.Contains(t, categoryBoards[0].BoardIDs, board2.ID) -} diff --git a/server/model/category.go b/server/model/category.go index 0a3dd903d..73c372e13 100644 --- a/server/model/category.go +++ b/server/model/category.go @@ -49,37 +49,16 @@ type Category struct { // required: true Collapsed bool `json:"collapsed"` - // Inter-category sort order per user - // required: true - SortOrder int `json:"sortOrder"` - - // The sorting method applied on this category - // required: true - Sorting string `json:"sorting"` - // Category's type // required: true Type string `json:"type"` } func (c *Category) Hydrate() { - if c.ID == "" { - c.ID = utils.NewID(utils.IDTypeNone) - } - - if c.CreateAt == 0 { - c.CreateAt = utils.GetMillis() - } - - if c.UpdateAt == 0 { - c.UpdateAt = c.CreateAt - } - - if c.SortOrder < 0 { - c.SortOrder = 0 - } - - if strings.TrimSpace(c.Type) == "" { + c.ID = utils.NewID(utils.IDTypeNone) + c.CreateAt = utils.GetMillis() + c.UpdateAt = c.CreateAt + if c.Type == "" { c.Type = CategoryTypeCustom } } diff --git a/server/model/category_boards.go b/server/model/category_boards.go index 81cd568a5..6f0fe5cfd 100644 --- a/server/model/category_boards.go +++ b/server/model/category_boards.go @@ -1,7 +1,5 @@ package model -const CategoryBoardsSortOrderGap = 10 - // CategoryBoards is a board category and associated boards // swagger:model type CategoryBoards struct { @@ -10,10 +8,6 @@ type CategoryBoards struct { // The IDs of boards in this category // required: true BoardIDs []string `json:"boardIDs"` - - // The relative sort order of this board in its category - // required: true - SortOrder int `json:"sortOrder"` } type BoardCategoryWebsocketData struct { diff --git a/server/services/store/mockstore/mockstore.go b/server/services/store/mockstore/mockstore.go index 8ddc03315..0b9174ab6 100644 --- a/server/services/store/mockstore/mockstore.go +++ b/server/services/store/mockstore/mockstore.go @@ -37,17 +37,17 @@ func (m *MockStore) EXPECT() *MockStoreMockRecorder { } // AddUpdateCategoryBoard mocks base method. -func (m *MockStore) AddUpdateCategoryBoard(arg0 string, arg1 map[string]string) error { +func (m *MockStore) AddUpdateCategoryBoard(arg0, arg1, arg2 string) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "AddUpdateCategoryBoard", arg0, arg1) + ret := m.ctrl.Call(m, "AddUpdateCategoryBoard", arg0, arg1, arg2) ret0, _ := ret[0].(error) return ret0 } // AddUpdateCategoryBoard indicates an expected call of AddUpdateCategoryBoard. -func (mr *MockStoreMockRecorder) AddUpdateCategoryBoard(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockStoreMockRecorder) AddUpdateCategoryBoard(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddUpdateCategoryBoard", reflect.TypeOf((*MockStore)(nil).AddUpdateCategoryBoard), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddUpdateCategoryBoard", reflect.TypeOf((*MockStore)(nil).AddUpdateCategoryBoard), arg0, arg1, arg2) } // CanSeeUser mocks base method. @@ -1133,21 +1133,6 @@ func (mr *MockStoreMockRecorder) GetUserByUsername(arg0 interface{}) *gomock.Cal return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUserByUsername", reflect.TypeOf((*MockStore)(nil).GetUserByUsername), arg0) } -// GetUserCategories mocks base method. -func (m *MockStore) GetUserCategories(arg0, arg1 string) ([]model.Category, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetUserCategories", arg0, arg1) - ret0, _ := ret[0].([]model.Category) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetUserCategories indicates an expected call of GetUserCategories. -func (mr *MockStoreMockRecorder) GetUserCategories(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUserCategories", reflect.TypeOf((*MockStore)(nil).GetUserCategories), arg0, arg1) -} - // GetUserCategoryBoards mocks base method. func (m *MockStore) GetUserCategoryBoards(arg0, arg1 string) ([]model.CategoryBoards, error) { m.ctrl.T.Helper() @@ -1397,36 +1382,6 @@ func (mr *MockStoreMockRecorder) RemoveDefaultTemplates(arg0 interface{}) *gomoc return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoveDefaultTemplates", reflect.TypeOf((*MockStore)(nil).RemoveDefaultTemplates), arg0) } -// ReorderCategories mocks base method. -func (m *MockStore) ReorderCategories(arg0, arg1 string, arg2 []string) ([]string, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ReorderCategories", arg0, arg1, arg2) - ret0, _ := ret[0].([]string) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// ReorderCategories indicates an expected call of ReorderCategories. -func (mr *MockStoreMockRecorder) ReorderCategories(arg0, arg1, arg2 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReorderCategories", reflect.TypeOf((*MockStore)(nil).ReorderCategories), arg0, arg1, arg2) -} - -// ReorderCategoryBoards mocks base method. -func (m *MockStore) ReorderCategoryBoards(arg0 string, arg1 []string) ([]string, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ReorderCategoryBoards", arg0, arg1) - ret0, _ := ret[0].([]string) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// ReorderCategoryBoards indicates an expected call of ReorderCategoryBoards. -func (mr *MockStoreMockRecorder) ReorderCategoryBoards(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReorderCategoryBoards", reflect.TypeOf((*MockStore)(nil).ReorderCategoryBoards), arg0, arg1) -} - // RunDataRetention mocks base method. func (m *MockStore) RunDataRetention(arg0, arg1 int64) (int64, error) { m.ctrl.T.Helper() diff --git a/server/services/store/sqlstore/category.go b/server/services/store/sqlstore/category.go index 847c3d3d9..23272ae05 100644 --- a/server/services/store/sqlstore/category.go +++ b/server/services/store/sqlstore/category.go @@ -2,7 +2,6 @@ package sqlstore import ( "database/sql" - "fmt" sq "github.com/Masterminds/squirrel" "github.com/mattermost/focalboard/server/model" @@ -11,11 +10,9 @@ import ( "github.com/mattermost/mattermost-server/v6/shared/mlog" ) -const categorySortOrderGap = 10 - func (s *SQLStore) getCategory(db sq.BaseRunner, id string) (*model.Category, error) { query := s.getQueryBuilder(db). - Select("id", "name", "user_id", "team_id", "create_at", "update_at", "delete_at", "collapsed", "sort_order", "type"). + Select("id", "name", "user_id", "team_id", "create_at", "update_at", "delete_at", "collapsed", "type"). From(s.tablePrefix + "categories"). Where(sq.Eq{"id": id}) @@ -39,11 +36,6 @@ func (s *SQLStore) getCategory(db sq.BaseRunner, id string) (*model.Category, er } func (s *SQLStore) createCategory(db sq.BaseRunner, category model.Category) error { - // A new category should always end up at the top. - // So we first insert the provided category, then bump up - // existing user-team categories' order - - // creating provided category query := s.getQueryBuilder(db). Insert(s.tablePrefix+"categories"). Columns( @@ -55,7 +47,6 @@ func (s *SQLStore) createCategory(db sq.BaseRunner, category model.Category) err "update_at", "delete_at", "collapsed", - "sort_order", "type", ). Values( @@ -67,7 +58,6 @@ func (s *SQLStore) createCategory(db sq.BaseRunner, category model.Category) err category.UpdateAt, category.DeleteAt, category.Collapsed, - category.SortOrder, category.Type, ) @@ -76,30 +66,6 @@ func (s *SQLStore) createCategory(db sq.BaseRunner, category model.Category) err s.logger.Error("Error creating category", mlog.String("category name", category.Name), mlog.Err(err)) return err } - - // bumping up order of existing categories - updateQuery := s.getQueryBuilder(db). - Update(s.tablePrefix+"categories"). - Set("sort_order", sq.Expr(fmt.Sprintf("sort_order + %d", categorySortOrderGap))). - Where( - sq.Eq{ - "user_id": category.UserID, - "team_id": category.TeamID, - "delete_at": 0, - }, - ) - - if _, err := updateQuery.Exec(); err != nil { - s.logger.Error( - "createCategory failed to update sort order of existing user-team categories", - mlog.String("user_id", category.UserID), - mlog.String("team_id", category.TeamID), - mlog.Err(err), - ) - - return err - } - return nil } @@ -149,14 +115,13 @@ func (s *SQLStore) deleteCategory(db sq.BaseRunner, categoryID, userID, teamID s func (s *SQLStore) getUserCategories(db sq.BaseRunner, userID, teamID string) ([]model.Category, error) { query := s.getQueryBuilder(db). - Select("id", "name", "user_id", "team_id", "create_at", "update_at", "delete_at", "collapsed", "sort_order", "type"). - From(s.tablePrefix+"categories"). + Select("id", "name", "user_id", "team_id", "create_at", "update_at", "delete_at", "collapsed", "type"). + From(s.tablePrefix + "categories"). Where(sq.Eq{ "user_id": userID, "team_id": teamID, "delete_at": 0, - }). - OrderBy("sort_order", "name") + }) rows, err := query.Query() if err != nil { @@ -181,7 +146,6 @@ func (s *SQLStore) categoriesFromRows(rows *sql.Rows) ([]model.Category, error) &category.UpdateAt, &category.DeleteAt, &category.Collapsed, - &category.SortOrder, &category.Type, ) @@ -195,36 +159,3 @@ func (s *SQLStore) categoriesFromRows(rows *sql.Rows) ([]model.Category, error) return categories, nil } - -func (s *SQLStore) reorderCategories(db sq.BaseRunner, userID, teamID string, newCategoryOrder []string) ([]string, error) { - if len(newCategoryOrder) == 0 { - return nil, nil - } - - updateCase := sq.Case("id") - for i, categoryID := range newCategoryOrder { - updateCase = updateCase.When("'"+categoryID+"'", sq.Expr(fmt.Sprintf("%d", i*categorySortOrderGap))) - } - updateCase = updateCase.Else("sort_order") - - query := s.getQueryBuilder(db). - Update(s.tablePrefix+"categories"). - Set("sort_order", updateCase). - Where(sq.Eq{ - "user_id": userID, - "team_id": teamID, - }) - - if _, err := query.Exec(); err != nil { - s.logger.Error( - "reorderCategories failed to update category order", - mlog.String("user_id", userID), - mlog.String("team_id", teamID), - mlog.Err(err), - ) - - return nil, err - } - - return newCategoryOrder, nil -} diff --git a/server/services/store/sqlstore/category_boards.go b/server/services/store/sqlstore/category_boards.go index 6a8415c67..8a0e36172 100644 --- a/server/services/store/sqlstore/category_boards.go +++ b/server/services/store/sqlstore/category_boards.go @@ -2,7 +2,6 @@ package sqlstore import ( "database/sql" - "fmt" sq "github.com/Masterminds/squirrel" "github.com/mattermost/focalboard/server/model" @@ -42,8 +41,7 @@ func (s *SQLStore) getCategoryBoardAttributes(db sq.BaseRunner, categoryID strin Where(sq.Eq{ "category_id": categoryID, "delete_at": 0, - }). - OrderBy("sort_order") + }) rows, err := query.Query() if err != nil { @@ -54,25 +52,23 @@ func (s *SQLStore) getCategoryBoardAttributes(db sq.BaseRunner, categoryID strin return s.categoryBoardsFromRows(rows) } -func (s *SQLStore) addUpdateCategoryBoard(db sq.BaseRunner, userID string, boardCategoryMapping map[string]string) error { - boardIDs := []string{} - for boardID := range boardCategoryMapping { - boardIDs = append(boardIDs, boardID) - } - - if err := s.deleteUserCategoryBoards(db, userID, boardIDs); err != nil { +func (s *SQLStore) addUpdateCategoryBoard(db sq.BaseRunner, userID, categoryID, boardID string) error { + if err := s.deleteUserCategoryBoard(db, userID, boardID); err != nil { return err } - return s.addUserCategoryBoard(db, userID, boardCategoryMapping) -} - -func (s *SQLStore) addUserCategoryBoard(db sq.BaseRunner, userID string, boardCategoryMapping map[string]string) error { - if len(boardCategoryMapping) == 0 { + if categoryID == "0" { + // category ID "0" means user wants to move board out of + // the custom category. Deleting the user-board-category + // mapping achieves this. return nil } - query := s.getQueryBuilder(db). + return s.addUserCategoryBoard(db, userID, categoryID, boardID) +} + +func (s *SQLStore) addUserCategoryBoard(db sq.BaseRunner, userID, categoryID, boardID string) error { + _, err := s.getQueryBuilder(db). Insert(s.tablePrefix+"category_boards"). Columns( "id", @@ -82,50 +78,39 @@ func (s *SQLStore) addUserCategoryBoard(db sq.BaseRunner, userID string, boardCa "create_at", "update_at", "delete_at", - "sort_order", - ) + ). + Values( + utils.NewID(utils.IDTypeNone), + userID, + categoryID, + boardID, + utils.GetMillis(), + utils.GetMillis(), + 0, + ).Exec() - now := utils.GetMillis() - for boardID, categoryID := range boardCategoryMapping { - query = query. - Values( - utils.NewID(utils.IDTypeNone), - userID, - categoryID, - boardID, - now, - now, - 0, - 0, - ) - } - - if _, err := query.Exec(); err != nil { + if err != nil { s.logger.Error("addUserCategoryBoard error", mlog.Err(err)) return err } return nil } -func (s *SQLStore) deleteUserCategoryBoards(db sq.BaseRunner, userID string, boardIDs []string) error { - if len(boardIDs) == 0 { - return nil - } - +func (s *SQLStore) deleteUserCategoryBoard(db sq.BaseRunner, userID, boardID string) error { _, err := s.getQueryBuilder(db). Update(s.tablePrefix+"category_boards"). Set("delete_at", utils.GetMillis()). Where(sq.Eq{ "user_id": userID, - "board_id": boardIDs, + "board_id": boardID, "delete_at": 0, }).Exec() if err != nil { s.logger.Error( - "deleteUserCategoryBoards delete error", + "deleteUserCategoryBoard delete error", mlog.String("userID", userID), - mlog.Array("boardID", boardIDs), + mlog.String("boardID", boardID), mlog.Err(err), ) return err @@ -149,35 +134,3 @@ func (s *SQLStore) categoryBoardsFromRows(rows *sql.Rows) ([]string, error) { return blocks, nil } - -func (s *SQLStore) reorderCategoryBoards(db sq.BaseRunner, categoryID string, newBoardsOrder []string) ([]string, error) { - if len(newBoardsOrder) == 0 { - return nil, nil - } - - updateCase := sq.Case("board_id") - for i, boardID := range newBoardsOrder { - updateCase = updateCase.When("'"+boardID+"'", sq.Expr(fmt.Sprintf("%d", i+model.CategoryBoardsSortOrderGap))) - } - updateCase.Else("sort_order") - - query := s.getQueryBuilder(db). - Update(s.tablePrefix+"category_boards"). - Set("sort_order", updateCase). - Where(sq.Eq{ - "category_id": categoryID, - "delete_at": 0, - }) - - if _, err := query.Exec(); err != nil { - s.logger.Error( - "reorderCategoryBoards failed to update category board order", - mlog.String("category_id", categoryID), - mlog.Err(err), - ) - - return nil, err - } - - return newBoardsOrder, nil -} diff --git a/server/services/store/sqlstore/migrations/000030_add_category_sort_order.down.sql b/server/services/store/sqlstore/migrations/000030_add_category_sort_order.down.sql deleted file mode 100644 index 027b7d63f..000000000 --- a/server/services/store/sqlstore/migrations/000030_add_category_sort_order.down.sql +++ /dev/null @@ -1 +0,0 @@ -SELECT 1; \ No newline at end of file diff --git a/server/services/store/sqlstore/migrations/000030_add_category_sort_order.up.sql b/server/services/store/sqlstore/migrations/000030_add_category_sort_order.up.sql deleted file mode 100644 index f8a1bf0cd..000000000 --- a/server/services/store/sqlstore/migrations/000030_add_category_sort_order.up.sql +++ /dev/null @@ -1 +0,0 @@ -ALTER TABLE {{.prefix}}categories ADD COLUMN sort_order BIGINT DEFAULT 0; diff --git a/server/services/store/sqlstore/migrations/000031_add_category_boards_sort_order.down.sql b/server/services/store/sqlstore/migrations/000031_add_category_boards_sort_order.down.sql deleted file mode 100644 index 027b7d63f..000000000 --- a/server/services/store/sqlstore/migrations/000031_add_category_boards_sort_order.down.sql +++ /dev/null @@ -1 +0,0 @@ -SELECT 1; \ No newline at end of file diff --git a/server/services/store/sqlstore/migrations/000031_add_category_boards_sort_order.up.sql b/server/services/store/sqlstore/migrations/000031_add_category_boards_sort_order.up.sql deleted file mode 100644 index fc023e724..000000000 --- a/server/services/store/sqlstore/migrations/000031_add_category_boards_sort_order.up.sql +++ /dev/null @@ -1 +0,0 @@ -ALTER TABLE {{.prefix}}category_boards ADD COLUMN sort_order BIGINT DEFAULT 0; diff --git a/server/services/store/sqlstore/migrations/000032_move_boards_category_to_end.down.sql b/server/services/store/sqlstore/migrations/000032_move_boards_category_to_end.down.sql deleted file mode 100644 index 027b7d63f..000000000 --- a/server/services/store/sqlstore/migrations/000032_move_boards_category_to_end.down.sql +++ /dev/null @@ -1 +0,0 @@ -SELECT 1; \ No newline at end of file diff --git a/server/services/store/sqlstore/migrations/000032_move_boards_category_to_end.up.sql b/server/services/store/sqlstore/migrations/000032_move_boards_category_to_end.up.sql deleted file mode 100644 index 5b333a09e..000000000 --- a/server/services/store/sqlstore/migrations/000032_move_boards_category_to_end.up.sql +++ /dev/null @@ -1,15 +0,0 @@ -{{- /* To move Boards category to to the last value, we just need a relatively large value. */ -}} -{{- /* Assigning 10x total number of categories works perfectly. The sort_order is anyways updated */ -}} -{{- /* when the user manually DNDs a category. */ -}} - -{{if or .postgres .sqlite}} -UPDATE {{.prefix}}categories SET sort_order = (10 * (SELECT COUNT(*) FROM {{.prefix}}categories)) WHERE lower(name) = 'boards'; -{{end}} - -{{if .mysql}} -{{- /* MySQL doesn't allow referencing the same table in subquery and update query like Postgres, */ -}} -{{- /* So we save the subquery result in a variable to use later. */ -}} -SET @focalboad_numCategories = (SELECT COUNT(*) FROM {{.prefix}}categories); -UPDATE {{.prefix}}categories SET sort_order = (10 * @focalboad_numCategories) WHERE lower(name) = 'boards'; -SET @focalboad_numCategories = NULL; -{{end}} \ No newline at end of file diff --git a/server/services/store/sqlstore/public_methods.go b/server/services/store/sqlstore/public_methods.go index fcc83202b..7cba92307 100644 --- a/server/services/store/sqlstore/public_methods.go +++ b/server/services/store/sqlstore/public_methods.go @@ -22,15 +22,15 @@ import ( "github.com/mattermost/mattermost-server/v6/shared/mlog" ) -func (s *SQLStore) AddUpdateCategoryBoard(userID string, boardCategoryMapping map[string]string) error { +func (s *SQLStore) AddUpdateCategoryBoard(userID string, categoryID string, blockID string) error { if s.dbType == model.SqliteDBType { - return s.addUpdateCategoryBoard(s.db, userID, boardCategoryMapping) + return s.addUpdateCategoryBoard(s.db, userID, categoryID, blockID) } tx, txErr := s.db.BeginTx(context.Background(), nil) if txErr != nil { return txErr } - err := s.addUpdateCategoryBoard(tx, userID, boardCategoryMapping) + err := s.addUpdateCategoryBoard(tx, userID, categoryID, blockID) if err != nil { if rollbackErr := tx.Rollback(); rollbackErr != nil { s.logger.Error("transaction rollback error", mlog.Err(rollbackErr), mlog.String("methodName", "AddUpdateCategoryBoard")) @@ -105,26 +105,7 @@ func (s *SQLStore) CreateBoardsAndBlocksWithAdmin(bab *model.BoardsAndBlocks, us } func (s *SQLStore) CreateCategory(category model.Category) error { - if s.dbType == model.SqliteDBType { - return s.createCategory(s.db, category) - } - tx, txErr := s.db.BeginTx(context.Background(), nil) - if txErr != nil { - return txErr - } - err := s.createCategory(tx, category) - if err != nil { - if rollbackErr := tx.Rollback(); rollbackErr != nil { - s.logger.Error("transaction rollback error", mlog.Err(rollbackErr), mlog.String("methodName", "CreateCategory")) - } - return err - } - - if err := tx.Commit(); err != nil { - return err - } - - return nil + return s.createCategory(s.db, category) } @@ -558,11 +539,6 @@ func (s *SQLStore) GetUserByUsername(username string) (*model.User, error) { } -func (s *SQLStore) GetUserCategories(userID string, teamID string) ([]model.Category, error) { - return s.getUserCategories(s.db, userID, teamID) - -} - func (s *SQLStore) GetUserCategoryBoards(userID string, teamID string) ([]model.CategoryBoards, error) { return s.getUserCategoryBoards(s.db, userID, teamID) @@ -781,16 +757,6 @@ func (s *SQLStore) RemoveDefaultTemplates(boards []*model.Board) error { } -func (s *SQLStore) ReorderCategories(userID string, teamID string, newCategoryOrder []string) ([]string, error) { - return s.reorderCategories(s.db, userID, teamID, newCategoryOrder) - -} - -func (s *SQLStore) ReorderCategoryBoards(categoryID string, newBoardsOrder []string) ([]string, error) { - return s.reorderCategoryBoards(s.db, categoryID, newBoardsOrder) - -} - func (s *SQLStore) RunDataRetention(globalRetentionDate int64, batchSize int64) (int64, error) { if s.dbType == model.SqliteDBType { return s.runDataRetention(s.db, globalRetentionDate, batchSize) diff --git a/server/services/store/sqlstore/sqlstore_test.go b/server/services/store/sqlstore/sqlstore_test.go index e802655c7..0fc9aff4c 100644 --- a/server/services/store/sqlstore/sqlstore_test.go +++ b/server/services/store/sqlstore/sqlstore_test.go @@ -6,9 +6,8 @@ package sqlstore import ( "testing" - "github.com/mattermost/focalboard/server/services/store/storetests" - "github.com/mattermost/focalboard/server/model" + "github.com/mattermost/focalboard/server/services/store/storetests" "github.com/stretchr/testify/require" ) diff --git a/server/services/store/store.go b/server/services/store/store.go index 4a8ae7948..a072a0e86 100644 --- a/server/services/store/store.go +++ b/server/services/store/store.go @@ -117,13 +117,9 @@ type Store interface { DeleteBoardsAndBlocks(dbab *model.DeleteBoardsAndBlocks, userID string) error GetCategory(id string) (*model.Category, error) - - GetUserCategories(userID, teamID string) ([]model.Category, error) - // @withTransaction CreateCategory(category model.Category) error UpdateCategory(category model.Category) error DeleteCategory(categoryID, userID, teamID string) error - ReorderCategories(userID, teamID string, newCategoryOrder []string) ([]string, error) GetUserCategoryBoards(userID, teamID string) ([]model.CategoryBoards, error) @@ -131,8 +127,7 @@ type Store interface { SaveFileInfo(fileInfo *mmModel.FileInfo) error // @withTransaction - AddUpdateCategoryBoard(userID string, boardCategoryMapping map[string]string) error - ReorderCategoryBoards(categoryID string, newBoardsOrder []string) ([]string, error) + AddUpdateCategoryBoard(userID, categoryID, blockID string) error CreateSubscription(sub *model.Subscription) (*model.Subscription, error) DeleteSubscription(blockID string, subscriberID string) error diff --git a/server/services/store/storetests/category.go b/server/services/store/storetests/category.go index 113e13b2b..e9d2db1a7 100644 --- a/server/services/store/storetests/category.go +++ b/server/services/store/storetests/category.go @@ -9,25 +9,27 @@ import ( "github.com/stretchr/testify/assert" ) -type testFunc func(t *testing.T, store store.Store) - func StoreTestCategoryStore(t *testing.T, setup func(t *testing.T) (store.Store, func())) { - tests := map[string]testFunc{ - "CreateCategory": testGetCreateCategory, - "UpdateCategory": testUpdateCategory, - "DeleteCategory": testDeleteCategory, - "GetUserCategories": testGetUserCategories, - "ReorderCategories": testReorderCategories, - "ReorderCategoriesBoards": testReorderCategoryBoards, - } - - for name, f := range tests { - t.Run(name, func(t *testing.T) { - store, tearDown := setup(t) - defer tearDown() - f(t, store) - }) - } + t.Run("CreateCategory", func(t *testing.T) { + store, tearDown := setup(t) + defer tearDown() + testGetCreateCategory(t, store) + }) + t.Run("UpdateCategory", func(t *testing.T) { + store, tearDown := setup(t) + defer tearDown() + testUpdateCategory(t, store) + }) + t.Run("DeleteCategory", func(t *testing.T) { + store, tearDown := setup(t) + defer tearDown() + testDeleteCategory(t, store) + }) + t.Run("GetUserCategories", func(t *testing.T) { + store, tearDown := setup(t) + defer tearDown() + testGetUserCategories(t, store) + }) } func testGetCreateCategory(t *testing.T, store store.Store) { @@ -209,129 +211,3 @@ func testGetUserCategories(t *testing.T, store store.Store) { assert.NoError(t, err) assert.Equal(t, 3, len(userCategories)) } - -func testReorderCategories(t *testing.T, store store.Store) { - // setup - err := store.CreateCategory(model.Category{ - ID: "category_id_1", - Name: "Category 1", - Type: "custom", - UserID: "user_id", - TeamID: "team_id", - }) - assert.NoError(t, err) - - err = store.CreateCategory(model.Category{ - ID: "category_id_2", - Name: "Category 2", - Type: "custom", - UserID: "user_id", - TeamID: "team_id", - }) - assert.NoError(t, err) - - err = store.CreateCategory(model.Category{ - ID: "category_id_3", - Name: "Category 3", - Type: "custom", - UserID: "user_id", - TeamID: "team_id", - }) - assert.NoError(t, err) - - // verify the current order - categories, err := store.GetUserCategories("user_id", "team_id") - assert.NoError(t, err) - assert.Equal(t, 3, len(categories)) - - // the categories should show up in reverse insertion order (latest one first) - assert.Equal(t, "category_id_3", categories[0].ID) - assert.Equal(t, "category_id_2", categories[1].ID) - assert.Equal(t, "category_id_1", categories[2].ID) - - // re-ordering categories normally - _, err = store.ReorderCategories("user_id", "team_id", []string{ - "category_id_2", - "category_id_3", - "category_id_1", - }) - assert.NoError(t, err) - - // verify the board order - categories, err = store.GetUserCategories("user_id", "team_id") - assert.NoError(t, err) - assert.Equal(t, 3, len(categories)) - assert.Equal(t, "category_id_2", categories[0].ID) - assert.Equal(t, "category_id_3", categories[1].ID) - assert.Equal(t, "category_id_1", categories[2].ID) - - // lets try specifying a non existing category ID. - // It shouldn't cause any problem - _, err = store.ReorderCategories("user_id", "team_id", []string{ - "category_id_1", - "category_id_2", - "category_id_3", - "non-existing-category-id", - }) - assert.NoError(t, err) - - categories, err = store.GetUserCategories("user_id", "team_id") - assert.NoError(t, err) - assert.Equal(t, 3, len(categories)) - assert.Equal(t, "category_id_1", categories[0].ID) - assert.Equal(t, "category_id_2", categories[1].ID) - assert.Equal(t, "category_id_3", categories[2].ID) -} - -func testReorderCategoryBoards(t *testing.T, store store.Store) { - // setup - err := store.CreateCategory(model.Category{ - ID: "category_id_1", - Name: "Category 1", - Type: "custom", - UserID: "user_id", - TeamID: "team_id", - }) - assert.NoError(t, err) - - err = store.AddUpdateCategoryBoard("user_id", map[string]string{ - "board_id_1": "category_id_1", - "board_id_2": "category_id_1", - "board_id_3": "category_id_1", - "board_id_4": "category_id_1", - }) - assert.NoError(t, err) - - // verify current order - categoryBoards, err := store.GetUserCategoryBoards("user_id", "team_id") - assert.NoError(t, err) - assert.Equal(t, 1, len(categoryBoards)) - assert.Equal(t, 4, len(categoryBoards[0].BoardIDs)) - assert.Contains(t, categoryBoards[0].BoardIDs, "board_id_1") - assert.Contains(t, categoryBoards[0].BoardIDs, "board_id_2") - assert.Contains(t, categoryBoards[0].BoardIDs, "board_id_3") - assert.Contains(t, categoryBoards[0].BoardIDs, "board_id_4") - - // reordering - newOrder, err := store.ReorderCategoryBoards("category_id_1", []string{ - "board_id_3", - "board_id_1", - "board_id_2", - "board_id_4", - }) - assert.NoError(t, err) - assert.Equal(t, "board_id_3", newOrder[0]) - assert.Equal(t, "board_id_1", newOrder[1]) - assert.Equal(t, "board_id_2", newOrder[2]) - assert.Equal(t, "board_id_4", newOrder[3]) - - // verify new order - categoryBoards, err = store.GetUserCategoryBoards("user_id", "team_id") - assert.NoError(t, err) - assert.Equal(t, 1, len(categoryBoards)) - assert.Equal(t, 4, len(categoryBoards[0].BoardIDs)) - assert.Equal(t, "board_id_3", categoryBoards[0].BoardIDs[0]) - assert.Equal(t, "board_id_1", categoryBoards[0].BoardIDs[1]) - assert.Equal(t, "board_id_2", categoryBoards[0].BoardIDs[2]) - assert.Equal(t, "board_id_4", categoryBoards[0].BoardIDs[3]) -} diff --git a/server/services/store/storetests/categoryBoards.go b/server/services/store/storetests/categoryBoards.go index 2cc83b197..0cc5f4bf9 100644 --- a/server/services/store/storetests/categoryBoards.go +++ b/server/services/store/storetests/categoryBoards.go @@ -60,14 +60,14 @@ func testGetUserCategoryBoards(t *testing.T, store store.Store) { // Adding Board 1 and Board 2 to Category 1 // The boards don't need to exists in DB for this test - err = store.AddUpdateCategoryBoard("user_id_1", map[string]string{"board_1": "category_id_1"}) + err = store.AddUpdateCategoryBoard("user_id_1", "category_id_1", "board_1") assert.NoError(t, err) - err = store.AddUpdateCategoryBoard("user_id_1", map[string]string{"board_2": "category_id_1"}) + err = store.AddUpdateCategoryBoard("user_id_1", "category_id_1", "board_2") assert.NoError(t, err) // Adding Board 3 to Category 2 - err = store.AddUpdateCategoryBoard("user_id_1", map[string]string{"board_3": "category_id_2"}) + err = store.AddUpdateCategoryBoard("user_id_1", "category_id_2", "board_3") assert.NoError(t, err) // we'll leave category 3 empty diff --git a/server/services/store/storetests/data_retention.go b/server/services/store/storetests/data_retention.go index a73d40afa..e89beed3b 100644 --- a/server/services/store/storetests/data_retention.go +++ b/server/services/store/storetests/data_retention.go @@ -92,7 +92,7 @@ func LoadData(t *testing.T, store store.Store) { err = store.UpsertSharing(sharing) require.NoError(t, err) - err = store.AddUpdateCategoryBoard(testUserID, map[string]string{boardID: categoryID}) + err = store.AddUpdateCategoryBoard(testUserID, categoryID, boardID) require.NoError(t, err) } diff --git a/server/ws/adapter.go b/server/ws/adapter.go index 21a351f6f..e283c64e6 100644 --- a/server/ws/adapter.go +++ b/server/ws/adapter.go @@ -20,8 +20,6 @@ const ( websocketActionUpdateCategoryBoard = "UPDATE_BOARD_CATEGORY" websocketActionUpdateSubscription = "UPDATE_SUBSCRIPTION" websocketActionUpdateCardLimitTimestamp = "UPDATE_CARD_LIMIT_TIMESTAMP" - websocketActionReorderCategories = "REORDER_CATEGORIES" - websocketActionReorderCategoryBoards = "REORDER_CATEGORY_BOARDS" ) type Store interface { @@ -38,9 +36,7 @@ type Adapter interface { BroadcastMemberDelete(teamID, boardID, userID string) BroadcastConfigChange(clientConfig model.ClientConfig) BroadcastCategoryChange(category model.Category) - BroadcastCategoryBoardChange(teamID, userID string, blockCategory []*model.BoardCategoryWebsocketData) + BroadcastCategoryBoardChange(teamID, userID string, blockCategory model.BoardCategoryWebsocketData) BroadcastCardLimitTimestampChange(cardLimitTimestamp int64) BroadcastSubscriptionChange(teamID string, subscription *model.Subscription) - BroadcastCategoryReorder(teamID, userID string, categoryOrder []string) - BroadcastCategoryBoardsReorder(teamID, userID, categoryID string, boardsOrder []string) } diff --git a/server/ws/common.go b/server/ws/common.go index c21adc285..8941628c0 100644 --- a/server/ws/common.go +++ b/server/ws/common.go @@ -6,10 +6,10 @@ import ( // UpdateCategoryMessage is sent on block updates. type UpdateCategoryMessage struct { - Action string `json:"action"` - TeamID string `json:"teamId"` - Category *model.Category `json:"category,omitempty"` - BoardCategories []*model.BoardCategoryWebsocketData `json:"blockCategories,omitempty"` + Action string `json:"action"` + TeamID string `json:"teamId"` + Category *model.Category `json:"category,omitempty"` + BoardCategories *model.BoardCategoryWebsocketData `json:"blockCategories,omitempty"` } // UpdateBlockMsg is sent on block updates. @@ -59,16 +59,3 @@ type WebsocketCommand struct { ReadToken string `json:"readToken"` BlockIDs []string `json:"blockIds"` } - -type CategoryReorderMessage struct { - Action string `json:"action"` - CategoryOrder []string `json:"categoryOrder"` - TeamID string `json:"teamId"` -} - -type CategoryBoardReorderMessage struct { - Action string `json:"action"` - CategoryID string `json:"CategoryId"` - BoardOrder []string `json:"BoardOrder"` - TeamID string `json:"teamId"` -} diff --git a/server/ws/plugin_adapter.go b/server/ws/plugin_adapter.go index f45cae629..dcb26ce98 100644 --- a/server/ws/plugin_adapter.go +++ b/server/ws/plugin_adapter.go @@ -496,68 +496,19 @@ func (pa *PluginAdapter) BroadcastCategoryChange(category model.Category) { pa.sendUserMessageSkipCluster(websocketActionUpdateCategory, payload, category.UserID) } -func (pa *PluginAdapter) BroadcastCategoryReorder(teamID, userID string, categoryOrder []string) { - pa.logger.Debug("BroadcastCategoryReorder", - mlog.String("userID", userID), - mlog.String("teamID", teamID), - ) - - message := CategoryReorderMessage{ - Action: websocketActionReorderCategories, - CategoryOrder: categoryOrder, - TeamID: teamID, - } - payload := utils.StructToMap(message) - go func() { - clusterMessage := &ClusterMessage{ - Payload: payload, - UserID: userID, - } - - pa.sendMessageToCluster("websocket_message", clusterMessage) - }() - - pa.sendUserMessageSkipCluster(message.Action, payload, userID) -} - -func (pa *PluginAdapter) BroadcastCategoryBoardsReorder(teamID, userID, categoryID string, boardsOrder []string) { - pa.logger.Debug("BroadcastCategoryBoardsReorder", - mlog.String("userID", userID), - mlog.String("teamID", teamID), - mlog.String("categoryID", categoryID), - ) - - message := CategoryBoardReorderMessage{ - Action: websocketActionReorderCategoryBoards, - CategoryID: categoryID, - BoardOrder: boardsOrder, - TeamID: teamID, - } - payload := utils.StructToMap(message) - go func() { - clusterMessage := &ClusterMessage{ - Payload: payload, - UserID: userID, - } - - pa.sendMessageToCluster("websocket_message", clusterMessage) - }() - - pa.sendUserMessageSkipCluster(message.Action, payload, userID) -} - -func (pa *PluginAdapter) BroadcastCategoryBoardChange(teamID, userID string, boardCategories []*model.BoardCategoryWebsocketData) { +func (pa *PluginAdapter) BroadcastCategoryBoardChange(teamID, userID string, boardCategory model.BoardCategoryWebsocketData) { pa.logger.Debug( "BroadcastCategoryBoardChange", mlog.String("userID", userID), mlog.String("teamID", teamID), - mlog.Int("numEntries", len(boardCategories)), + mlog.String("categoryID", boardCategory.CategoryID), + mlog.String("blockID", boardCategory.BoardID), ) message := UpdateCategoryMessage{ Action: websocketActionUpdateCategoryBoard, TeamID: teamID, - BoardCategories: boardCategories, + BoardCategories: &boardCategory, } payload := utils.StructToMap(message) diff --git a/server/ws/server.go b/server/ws/server.go index 9df1b1f6e..044e1f09e 100644 --- a/server/ws/server.go +++ b/server/ws/server.go @@ -589,80 +589,27 @@ func (ws *Server) BroadcastCategoryChange(category model.Category) { } } -func (ws *Server) BroadcastCategoryReorder(teamID, userID string, categoryOrder []string) { - message := CategoryReorderMessage{ - Action: websocketActionReorderCategories, - CategoryOrder: categoryOrder, - TeamID: teamID, - } - - listeners := ws.getListenersForTeam(teamID) - ws.logger.Debug("listener(s) for teamID", - mlog.Int("listener_count", len(listeners)), - mlog.String("teamID", teamID), - ) - - for _, listener := range listeners { - ws.logger.Debug("Broadcast category order change", - mlog.Int("listener_count", len(listeners)), - mlog.String("teamID", teamID), - mlog.Stringer("remoteAddr", listener.conn.RemoteAddr()), - ) - - if err := listener.WriteJSON(message); err != nil { - ws.logger.Error("broadcast category order change error", mlog.Err(err)) - listener.conn.Close() - } - } -} - -func (ws *Server) BroadcastCategoryBoardsReorder(teamID, userID, categoryID string, boardOrder []string) { - message := CategoryBoardReorderMessage{ - Action: websocketActionReorderCategoryBoards, - CategoryID: categoryID, - BoardOrder: boardOrder, - TeamID: teamID, - } - - listeners := ws.getListenersForTeam(teamID) - ws.logger.Debug("listener(s) for teamID", - mlog.Int("listener_count", len(listeners)), - mlog.String("teamID", teamID), - ) - - for _, listener := range listeners { - ws.logger.Debug("Broadcast board category order change", - mlog.Int("listener_count", len(listeners)), - mlog.String("teamID", teamID), - mlog.Stringer("remoteAddr", listener.conn.RemoteAddr()), - ) - - if err := listener.WriteJSON(message); err != nil { - ws.logger.Error("broadcast category order change error", mlog.Err(err)) - listener.conn.Close() - } - } -} - -func (ws *Server) BroadcastCategoryBoardChange(teamID, userID string, boardCategories []*model.BoardCategoryWebsocketData) { +func (ws *Server) BroadcastCategoryBoardChange(teamID, userID string, boardCategory model.BoardCategoryWebsocketData) { message := UpdateCategoryMessage{ Action: websocketActionUpdateCategoryBoard, TeamID: teamID, - BoardCategories: boardCategories, + BoardCategories: &boardCategory, } listeners := ws.getListenersForTeam(teamID) ws.logger.Debug("listener(s) for teamID", mlog.Int("listener_count", len(listeners)), mlog.String("teamID", teamID), - mlog.Int("numEntries", len(boardCategories)), + mlog.String("categoryID", boardCategory.CategoryID), + mlog.String("blockID", boardCategory.BoardID), ) for _, listener := range listeners { ws.logger.Debug("Broadcast block change", mlog.Int("listener_count", len(listeners)), mlog.String("teamID", teamID), - mlog.Int("numEntries", len(boardCategories)), + mlog.String("categoryID", boardCategory.CategoryID), + mlog.String("blockID", boardCategory.BoardID), mlog.Stringer("remoteAddr", listener.conn.RemoteAddr()), ) diff --git a/webapp/i18n/en.json b/webapp/i18n/en.json index 403efc569..87943c745 100644 --- a/webapp/i18n/en.json +++ b/webapp/i18n/en.json @@ -257,8 +257,6 @@ "Sidebar.template-from-board": "New template from board", "Sidebar.untitled-board": "(Untitled Board)", "Sidebar.untitled-view": "(Untitled View)", - "Sidebar.new-category.badge": "New", - "Sidebar.new-category.drag-boards-cta": "Drag boards here...", "SidebarCategories.BlocksMenu.Move": "Move To...", "SidebarCategories.CategoryMenu.CreateNew": "Create New Category", "SidebarCategories.CategoryMenu.Delete": "Delete Category", diff --git a/webapp/package-lock.json b/webapp/package-lock.json index 7bcd4666d..37bbcf00b 100644 --- a/webapp/package-lock.json +++ b/webapp/package-lock.json @@ -35,7 +35,6 @@ "moment": "^2.29.1", "nanoevents": "^5.1.13", "react": "^16.13.0", - "react-beautiful-dnd": "^13.1.1", "react-day-picker": "^7.4.10", "react-dnd": "^14.0.2", "react-dnd-html5-backend": "^14.0.0", @@ -66,7 +65,6 @@ "@types/marked": "^4.0.3", "@types/nanoevents": "^1.0.0", "@types/react": "^17.0.43", - "@types/react-beautiful-dnd": "^13.1.2", "@types/react-dom": "^17.0.14", "@types/react-intl": "^3.0.0", "@types/react-redux": "^7.1.23", @@ -2717,15 +2715,6 @@ "csstype": "^3.0.2" } }, - "node_modules/@types/react-beautiful-dnd": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/@types/react-beautiful-dnd/-/react-beautiful-dnd-13.1.2.tgz", - "integrity": "sha512-+OvPkB8CdE/bGdXKyIhc/Lm2U7UAYCCJgsqmopFmh9gbAudmslkI8eOrPDjg4JhwSE6wytz4a3/wRjKtovHVJg==", - "dev": true, - "dependencies": { - "@types/react": "*" - } - }, "node_modules/@types/react-dom": { "version": "17.0.17", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.17.tgz", @@ -5640,14 +5629,6 @@ "source-map-resolve": "^0.6.0" } }, - "node_modules/css-box-model": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/css-box-model/-/css-box-model-1.2.1.tgz", - "integrity": "sha512-a7Vr4Q/kd/aw96bnJG332W9V9LkJO69JRcaCYDUqjp6/z0w6VcZjgAcTbgFxEPfBgdnAwlh3iwu+hLopa+flJw==", - "dependencies": { - "tiny-invariant": "^1.0.6" - } - }, "node_modules/css-functions-list": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.1.0.tgz", @@ -13689,11 +13670,6 @@ "performance-now": "^2.1.0" } }, - "node_modules/raf-schd": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/raf-schd/-/raf-schd-4.0.3.tgz", - "integrity": "sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ==" - }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -13749,24 +13725,6 @@ "node": ">=0.10.0" } }, - "node_modules/react-beautiful-dnd": { - "version": "13.1.1", - "resolved": "https://registry.npmjs.org/react-beautiful-dnd/-/react-beautiful-dnd-13.1.1.tgz", - "integrity": "sha512-0Lvs4tq2VcrEjEgDXHjT98r+63drkKEgqyxdA7qD3mvKwga6a5SscbdLPO2IExotU1jW8L0Ksdl0Cj2AF67nPQ==", - "dependencies": { - "@babel/runtime": "^7.9.2", - "css-box-model": "^1.2.0", - "memoize-one": "^5.1.1", - "raf-schd": "^4.0.2", - "react-redux": "^7.2.0", - "redux": "^4.0.4", - "use-memo-one": "^1.1.1" - }, - "peerDependencies": { - "react": "^16.8.5 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.5 || ^17.0.0 || ^18.0.0" - } - }, "node_modules/react-custom-scrollbars-2": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/react-custom-scrollbars-2/-/react-custom-scrollbars-2-4.5.0.tgz", @@ -16718,14 +16676,6 @@ "node": ">= 4" } }, - "node_modules/use-memo-one": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/use-memo-one/-/use-memo-one-1.1.3.tgz", - "integrity": "sha512-g66/K7ZQGYrI6dy8GLpVcMsBp4s17xNkYJVSMvTEevGy3nDxHOfE6z8BVE22+5G5x7t3+bhzrlTDB7ObrEE0cQ==", - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -19514,15 +19464,6 @@ "csstype": "^3.0.2" } }, - "@types/react-beautiful-dnd": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/@types/react-beautiful-dnd/-/react-beautiful-dnd-13.1.2.tgz", - "integrity": "sha512-+OvPkB8CdE/bGdXKyIhc/Lm2U7UAYCCJgsqmopFmh9gbAudmslkI8eOrPDjg4JhwSE6wytz4a3/wRjKtovHVJg==", - "dev": true, - "requires": { - "@types/react": "*" - } - }, "@types/react-dom": { "version": "17.0.17", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.17.tgz", @@ -21785,14 +21726,6 @@ "source-map-resolve": "^0.6.0" } }, - "css-box-model": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/css-box-model/-/css-box-model-1.2.1.tgz", - "integrity": "sha512-a7Vr4Q/kd/aw96bnJG332W9V9LkJO69JRcaCYDUqjp6/z0w6VcZjgAcTbgFxEPfBgdnAwlh3iwu+hLopa+flJw==", - "requires": { - "tiny-invariant": "^1.0.6" - } - }, "css-functions-list": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.1.0.tgz", @@ -27822,11 +27755,6 @@ "performance-now": "^2.1.0" } }, - "raf-schd": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/raf-schd/-/raf-schd-4.0.3.tgz", - "integrity": "sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ==" - }, "randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -27872,20 +27800,6 @@ "prop-types": "^15.6.2" } }, - "react-beautiful-dnd": { - "version": "13.1.1", - "resolved": "https://registry.npmjs.org/react-beautiful-dnd/-/react-beautiful-dnd-13.1.1.tgz", - "integrity": "sha512-0Lvs4tq2VcrEjEgDXHjT98r+63drkKEgqyxdA7qD3mvKwga6a5SscbdLPO2IExotU1jW8L0Ksdl0Cj2AF67nPQ==", - "requires": { - "@babel/runtime": "^7.9.2", - "css-box-model": "^1.2.0", - "memoize-one": "^5.1.1", - "raf-schd": "^4.0.2", - "react-redux": "^7.2.0", - "redux": "^4.0.4", - "use-memo-one": "^1.1.1" - } - }, "react-custom-scrollbars-2": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/react-custom-scrollbars-2/-/react-custom-scrollbars-2-4.5.0.tgz", @@ -30154,12 +30068,6 @@ "resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz", "integrity": "sha512-0kQLIzG4fdk/G5NONku64rSH/x32NOA39LVQqlK8Le6lvTF6GGRJpqaQFGgU+CLwySIqBSMdwYM0sYcW9f6P4A==" }, - "use-memo-one": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/use-memo-one/-/use-memo-one-1.1.3.tgz", - "integrity": "sha512-g66/K7ZQGYrI6dy8GLpVcMsBp4s17xNkYJVSMvTEevGy3nDxHOfE6z8BVE22+5G5x7t3+bhzrlTDB7ObrEE0cQ==", - "requires": {} - }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", diff --git a/webapp/package.json b/webapp/package.json index baac1d3ea..137cd899d 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -52,7 +52,6 @@ "moment": "^2.29.1", "nanoevents": "^5.1.13", "react": "^16.13.0", - "react-beautiful-dnd": "^13.1.1", "react-day-picker": "^7.4.10", "react-dnd": "^14.0.2", "react-dnd-html5-backend": "^14.0.0", @@ -107,7 +106,6 @@ "@types/marked": "^4.0.3", "@types/nanoevents": "^1.0.0", "@types/react": "^17.0.43", - "@types/react-beautiful-dnd": "^13.1.2", "@types/react-dom": "^17.0.14", "@types/react-intl": "^3.0.0", "@types/react-redux": "^7.1.23", diff --git a/webapp/src/components/__snapshots__/workspace.test.tsx.snap b/webapp/src/components/__snapshots__/workspace.test.tsx.snap index c1e09cb06..e06582101 100644 --- a/webapp/src/components/__snapshots__/workspace.test.tsx.snap +++ b/webapp/src/components/__snapshots__/workspace.test.tsx.snap @@ -110,129 +110,102 @@ exports[`src/components/workspace return workspace and showcard 1`] = `
+ + Category 1 +
+
+
-
- Category 1 -
-
-
- -
+
+
+
+
+
+ i +
+
+ board title +
+
+
+ + Category 1 +
+
+
-
- Category 1 -
-
-
- -
+
+
+
+
+
+ i +
+
+ board title +
+
+