diff --git a/backend/pkg/analytics/api/dashboard-handlers.go b/backend/pkg/analytics/api/dashboard-handlers.go index 7e94aa16b..161b46f24 100644 --- a/backend/pkg/analytics/api/dashboard-handlers.go +++ b/backend/pkg/analytics/api/dashboard-handlers.go @@ -31,6 +31,12 @@ func (e *handlersImpl) createDashboard(w http.ResponseWriter, r *http.Request) { startTime := time.Now() bodySize := 0 + projectID, err := getIDFromRequest(r, "projectId") + if err != nil { + e.responser.ResponseWithError(e.log, r.Context(), w, http.StatusBadRequest, err, startTime, r.URL.Path, bodySize) + return + } + bodyBytes, err := api.ReadBody(e.log, w, r, e.jsonSizeLimit) if err != nil { e.responser.ResponseWithError(e.log, r.Context(), w, http.StatusRequestEntityTooLarge, err, startTime, r.URL.Path, bodySize) @@ -44,18 +50,8 @@ func (e *handlersImpl) createDashboard(w http.ResponseWriter, r *http.Request) { return } - resp := &models.GetDashboardResponse{ - Dashboard: models.Dashboard{ - DashboardID: 1, - Name: req.Name, - Description: req.Description, - IsPublic: req.IsPublic, - IsPinned: req.IsPinned, - }, - } - currentUser := r.Context().Value("userData").(*user.User) - e.log.Info(r.Context(), "User ID: ", currentUser.ID) + resp, err := e.service.CreateDashboard(projectID, currentUser.ID, req) e.responser.ResponseWithJSON(e.log, r.Context(), w, resp, startTime, r.URL.Path, bodySize) } @@ -116,11 +112,17 @@ func (e *handlersImpl) updateDashboard(w http.ResponseWriter, r *http.Request) { startTime := time.Now() bodySize := 0 - //id, err := getDashboardId(r) - //if err != nil { - // e.responser.ResponseWithError(e.log, r.Context(), w, http.StatusBadRequest, err, startTime, r.URL.Path, bodySize) - // return - //} + projectID, err := getIDFromRequest(r, "projectId") + if err != nil { + e.responser.ResponseWithError(e.log, r.Context(), w, http.StatusBadRequest, err, startTime, r.URL.Path, bodySize) + return + } + + dashboardID, err := getIDFromRequest(r, "id") + if err != nil { + e.responser.ResponseWithError(e.log, r.Context(), w, http.StatusBadRequest, err, startTime, r.URL.Path, bodySize) + return + } bodyBytes, err := api.ReadBody(e.log, w, r, e.jsonSizeLimit) if err != nil { @@ -135,15 +137,8 @@ func (e *handlersImpl) updateDashboard(w http.ResponseWriter, r *http.Request) { return } - resp := &models.GetDashboardResponse{ - Dashboard: models.Dashboard{ - DashboardID: 1, - Name: req.Name, - Description: req.Description, - IsPublic: req.IsPublic, - IsPinned: req.IsPinned, - }, - } + currentUser := r.Context().Value("userData").(*user.User) + resp, err := e.service.UpdateDashboard(projectID, dashboardID, currentUser.ID, req) e.responser.ResponseWithJSON(e.log, r.Context(), w, resp, startTime, r.URL.Path, bodySize) } @@ -152,12 +147,24 @@ func (e *handlersImpl) deleteDashboard(w http.ResponseWriter, r *http.Request) { startTime := time.Now() bodySize := 0 - //id, err := getDashboardId(r) - //if err != nil { - // e.responser.ResponseWithError(e.log, r.Context(), w, http.StatusBadRequest, err, startTime, r.URL.Path, bodySize) - // return - //} - e.log.Info(r.Context(), "Dashboard deleted") + projectID, err := getIDFromRequest(r, "projectId") + if err != nil { + e.responser.ResponseWithError(e.log, r.Context(), w, http.StatusBadRequest, err, startTime, r.URL.Path, bodySize) + return + } + + dashboardID, err := getIDFromRequest(r, "id") + if err != nil { + e.responser.ResponseWithError(e.log, r.Context(), w, http.StatusBadRequest, err, startTime, r.URL.Path, bodySize) + return + } + + u := r.Context().Value("userData").(*user.User) + err = e.service.DeleteDashboard(projectID, dashboardID, u.ID) + if err != nil { + e.responser.ResponseWithError(e.log, r.Context(), w, http.StatusInternalServerError, err, startTime, r.URL.Path, bodySize) + return + } e.responser.ResponseOK(e.log, r.Context(), w, startTime, r.URL.Path, bodySize) } diff --git a/backend/pkg/analytics/api/models/model.go b/backend/pkg/analytics/api/models/model.go index f69b1684a..8dbdb1c32 100644 --- a/backend/pkg/analytics/api/models/model.go +++ b/backend/pkg/analytics/api/models/model.go @@ -1,12 +1,15 @@ package models type Dashboard struct { - DashboardID int `json:"dashboard_id"` - UserID int `json:"user_id"` + DashboardID int `json:"dashboardId"` + ProjectID int `json:"projectId"` + UserID int `json:"userId"` Name string `json:"name"` Description string `json:"description"` - IsPublic bool `json:"is_public"` - IsPinned bool `json:"is_pinned"` + IsPublic bool `json:"isPublic"` + IsPinned bool `json:"isPinned"` + OwnerEmail string `json:"ownerEmail"` + OwnerName string `json:"ownerName"` } type CreateDashboardResponse struct { @@ -29,7 +32,7 @@ type GetDashboardsResponse struct { // REQUESTS type CreateDashboardRequest struct { - Name string `json:"name"` + Name string `json:"name" validate:"required"` Description string `json:"description"` IsPublic bool `json:"is_public"` IsPinned bool `json:"is_pinned"` diff --git a/backend/pkg/analytics/service/analytics.go b/backend/pkg/analytics/service/analytics.go index ddb2aeee3..df0132ba1 100644 --- a/backend/pkg/analytics/service/analytics.go +++ b/backend/pkg/analytics/service/analytics.go @@ -11,6 +11,9 @@ import ( type Service interface { GetDashboard(projectId int, dashboardId int, userId uint64) (*models.GetDashboardResponse, error) GetDashboards(projectId int, userId uint64) (*models.GetDashboardsResponse, error) + CreateDashboard(projectId int, userId uint64, req *models.CreateDashboardRequest) (*models.GetDashboardResponse, error) + UpdateDashboard(projectId int, dashboardId int, userId uint64, req *models.UpdateDashboardRequest) (*models.GetDashboardResponse, error) + DeleteDashboard(projectId int, dashboardId int, userId uint64) error } type serviceImpl struct { diff --git a/backend/pkg/analytics/service/dashboard-service.go b/backend/pkg/analytics/service/dashboard-service.go index ab7d80ec2..33be80856 100644 --- a/backend/pkg/analytics/service/dashboard-service.go +++ b/backend/pkg/analytics/service/dashboard-service.go @@ -5,15 +5,39 @@ import ( "openreplay/backend/pkg/analytics/api/models" ) +func (s serviceImpl) CreateDashboard(projectId int, userID uint64, req *models.CreateDashboardRequest) (*models.GetDashboardResponse, error) { + sql := ` + INSERT INTO dashboards (project_id, user_id, name, description, is_public, is_pinned) + VALUES ($1, $2, $3, $4, $5, $6) + RETURNING dashboard_id, project_id, user_id, name, description, is_public, is_pinned` + + dashboard := &models.GetDashboardResponse{} + + err := s.pgconn.QueryRow(sql, projectId, userID, req.Name, req.Description, req.IsPublic, req.IsPinned).Scan( + &dashboard.DashboardID, + &dashboard.ProjectID, + &dashboard.UserID, + &dashboard.Name, + &dashboard.Description, + &dashboard.IsPublic, + &dashboard.IsPinned, + ) + if err != nil { + return nil, err + } + + return dashboard, nil +} + func (s serviceImpl) GetDashboard(projectId int, dashboardID int, userID uint64) (*models.GetDashboardResponse, error) { sql := ` - SELECT dashboard_id, name, description, is_public, is_pinned, user_id + SELECT dashboard_id, project_id, name, description, is_public, is_pinned, user_id FROM dashboards WHERE dashboard_id = $1 AND project_id = $2 AND deleted_at is null` dashboard := &models.GetDashboardResponse{} var ownerID int - err := s.pgconn.QueryRow(sql, dashboardID, projectId).Scan(&dashboard.DashboardID, &dashboard.Name, &dashboard.Description, &dashboard.IsPublic, &dashboard.IsPinned, &ownerID) + err := s.pgconn.QueryRow(sql, dashboardID, projectId).Scan(&dashboard.DashboardID, &dashboard.ProjectID, &dashboard.Name, &dashboard.Description, &dashboard.IsPublic, &dashboard.IsPinned, &ownerID) if err != nil { return nil, err } @@ -27,10 +51,11 @@ func (s serviceImpl) GetDashboard(projectId int, dashboardID int, userID uint64) func (s serviceImpl) GetDashboards(projectId int, userID uint64) (*models.GetDashboardsResponse, error) { sql := ` - SELECT dashboard_id, user_id, name, description, is_public, is_pinned - FROM dashboards - WHERE (is_public = true OR user_id = $1) AND user_id IS NOT NULL AND deleted_at IS NULL AND project_id = $2 - ORDER BY dashboard_id` + SELECT d.dashboard_id, d.user_id, d.project_id, d.name, d.description, d.is_public, d.is_pinned, u.email AS owner_email, u.name AS owner_name + FROM dashboards d + LEFT JOIN users u ON d.user_id = u.user_id + WHERE (d.is_public = true OR d.user_id = $1) AND d.user_id IS NOT NULL AND d.deleted_at IS NULL AND d.project_id = $2 + ORDER BY d.dashboard_id` rows, err := s.pgconn.Query(sql, userID, projectId) if err != nil { return nil, err @@ -41,7 +66,7 @@ func (s serviceImpl) GetDashboards(projectId int, userID uint64) (*models.GetDas for rows.Next() { var dashboard models.Dashboard - err := rows.Scan(&dashboard.DashboardID, &dashboard.UserID, &dashboard.Name, &dashboard.Description, &dashboard.IsPublic, &dashboard.IsPinned) + err := rows.Scan(&dashboard.DashboardID, &dashboard.UserID, &dashboard.ProjectID, &dashboard.Name, &dashboard.Description, &dashboard.IsPublic, &dashboard.IsPinned, &dashboard.OwnerEmail, &dashboard.OwnerName) if err != nil { return nil, err } @@ -57,3 +82,42 @@ func (s serviceImpl) GetDashboards(projectId int, userID uint64) (*models.GetDas Dashboards: dashboards, }, nil } + +func (s serviceImpl) UpdateDashboard(projectId int, dashboardID int, userID uint64, req *models.UpdateDashboardRequest) (*models.GetDashboardResponse, error) { + sql := ` + UPDATE dashboards + SET name = $1, description = $2, is_public = $3, is_pinned = $4 + WHERE dashboard_id = $5 AND project_id = $6 AND user_id = $7 + RETURNING dashboard_id, project_id, user_id, name, description, is_public, is_pinned` + + dashboard := &models.GetDashboardResponse{} + + err := s.pgconn.QueryRow(sql, req.Name, req.Description, req.IsPublic, req.IsPinned, dashboardID, projectId, userID).Scan( + &dashboard.DashboardID, + &dashboard.ProjectID, + &dashboard.UserID, + &dashboard.Name, + &dashboard.Description, + &dashboard.IsPublic, + &dashboard.IsPinned, + ) + if err != nil { + return nil, err + } + + return dashboard, nil +} + +func (s serviceImpl) DeleteDashboard(projectId int, dashboardID int, userID uint64) error { + sql := ` + UPDATE dashboards + SET deleted_at = now() + WHERE dashboard_id = $1 AND project_id = $2 AND user_id = $3 AND deleted_at IS NULL` + + err := s.pgconn.Exec(sql, dashboardID, projectId, userID) + if err != nil { + return err + } + + return nil +}