296 lines
9.1 KiB
Go
296 lines
9.1 KiB
Go
package api
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
"openreplay/backend/pkg/analytics/api/models"
|
|
"openreplay/backend/pkg/server/api"
|
|
"openreplay/backend/pkg/server/user"
|
|
"strconv"
|
|
"time"
|
|
|
|
"github.com/go-playground/validator/v10"
|
|
)
|
|
|
|
func (e *handlersImpl) createCard(w http.ResponseWriter, r *http.Request) {
|
|
startTime := time.Now()
|
|
bodySize := 0
|
|
|
|
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)
|
|
return
|
|
}
|
|
bodySize = len(bodyBytes)
|
|
|
|
req := &models.CardCreateRequest{}
|
|
if err := json.Unmarshal(bodyBytes, req); err != nil {
|
|
e.responser.ResponseWithError(e.log, r.Context(), w, http.StatusBadRequest, err, startTime, r.URL.Path, bodySize)
|
|
return
|
|
}
|
|
|
|
validate := validator.New()
|
|
err = validate.Struct(req)
|
|
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
|
|
}
|
|
|
|
currentUser := r.Context().Value("userData").(*user.User)
|
|
resp, err := e.service.CreateCard(projectID, currentUser.ID, req)
|
|
if err != nil {
|
|
e.responser.ResponseWithError(e.log, r.Context(), w, http.StatusInternalServerError, err, startTime, r.URL.Path, bodySize)
|
|
return
|
|
}
|
|
|
|
e.responser.ResponseWithJSON(e.log, r.Context(), w, resp, startTime, r.URL.Path, bodySize)
|
|
}
|
|
|
|
// getCard
|
|
func (e *handlersImpl) getCard(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
|
|
}
|
|
|
|
id, err := getIDFromRequest(r, "id")
|
|
if err != nil {
|
|
e.responser.ResponseWithError(e.log, r.Context(), w, http.StatusBadRequest, err, startTime, r.URL.Path, bodySize)
|
|
return
|
|
}
|
|
|
|
resp, err := e.service.GetCardWithSeries(projectID, id)
|
|
if err != nil {
|
|
e.responser.ResponseWithError(e.log, r.Context(), w, http.StatusInternalServerError, err, startTime, r.URL.Path, bodySize)
|
|
return
|
|
}
|
|
|
|
e.responser.ResponseWithJSON(e.log, r.Context(), w, resp, startTime, r.URL.Path, bodySize)
|
|
}
|
|
|
|
func (e *handlersImpl) getCards(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
|
|
}
|
|
|
|
//currentUser := r.Context().Value("userData").(*user.User)
|
|
resp, err := e.service.GetCards(projectID)
|
|
if err != nil {
|
|
e.responser.ResponseWithError(e.log, r.Context(), w, http.StatusInternalServerError, err, startTime, r.URL.Path, bodySize)
|
|
return
|
|
}
|
|
|
|
e.responser.ResponseWithJSON(e.log, r.Context(), w, resp, startTime, r.URL.Path, bodySize)
|
|
}
|
|
|
|
func (e *handlersImpl) getCardsPaginated(w http.ResponseWriter, r *http.Request) {
|
|
startTime := time.Now()
|
|
bodySize := 0
|
|
|
|
// Extract projectID from request
|
|
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
|
|
}
|
|
|
|
// Parse query parameters
|
|
query := r.URL.Query()
|
|
|
|
// Filters
|
|
filters := models.CardListFilter{
|
|
Filters: make(map[string]interface{}),
|
|
}
|
|
|
|
if name := query.Get("name"); name != "" {
|
|
filters.Filters["name"] = name
|
|
}
|
|
if metricType := query.Get("metric_type"); metricType != "" {
|
|
filters.Filters["metric_type"] = metricType
|
|
}
|
|
if dashboardIDs := query["dashboard_ids"]; len(dashboardIDs) > 0 {
|
|
// Parse dashboard_ids into []int
|
|
var ids []int
|
|
for _, id := range dashboardIDs {
|
|
if val, err := strconv.Atoi(id); err == nil {
|
|
ids = append(ids, val)
|
|
}
|
|
}
|
|
filters.Filters["dashboard_ids"] = ids
|
|
}
|
|
|
|
// Sorting
|
|
sort := models.CardListSort{
|
|
Field: query.Get("sort_field"),
|
|
Order: query.Get("sort_order"),
|
|
}
|
|
if sort.Field == "" {
|
|
sort.Field = "created_at" // Default sort field
|
|
}
|
|
if sort.Order == "" {
|
|
sort.Order = "desc" // Default sort order
|
|
}
|
|
|
|
// Pagination
|
|
limit := 10 // Default limit
|
|
page := 1 // Default page number
|
|
if val := query.Get("limit"); val != "" {
|
|
if l, err := strconv.Atoi(val); err == nil && l > 0 {
|
|
limit = l
|
|
}
|
|
}
|
|
if val := query.Get("page"); val != "" {
|
|
if p, err := strconv.Atoi(val); err == nil && p > 0 {
|
|
page = p
|
|
}
|
|
}
|
|
offset := (page - 1) * limit
|
|
|
|
// Validate inputs
|
|
if err := models.ValidateStruct(filters); err != nil {
|
|
e.responser.ResponseWithError(e.log, r.Context(), w, http.StatusBadRequest, fmt.Errorf("invalid filters: %w", err), startTime, r.URL.Path, bodySize)
|
|
return
|
|
}
|
|
if err := models.ValidateStruct(sort); err != nil {
|
|
e.responser.ResponseWithError(e.log, r.Context(), w, http.StatusBadRequest, fmt.Errorf("invalid sort: %w", err), startTime, r.URL.Path, bodySize)
|
|
return
|
|
}
|
|
|
|
// Call the service
|
|
resp, err := e.service.GetCardsPaginated(projectID, filters, sort, limit, offset)
|
|
if err != nil {
|
|
e.responser.ResponseWithError(e.log, r.Context(), w, http.StatusInternalServerError, err, startTime, r.URL.Path, bodySize)
|
|
return
|
|
}
|
|
|
|
// Respond with JSON
|
|
e.responser.ResponseWithJSON(e.log, r.Context(), w, resp, startTime, r.URL.Path, bodySize)
|
|
}
|
|
|
|
func (e *handlersImpl) updateCard(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
|
|
}
|
|
|
|
cardId, 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 {
|
|
e.responser.ResponseWithError(e.log, r.Context(), w, http.StatusRequestEntityTooLarge, err, startTime, r.URL.Path, bodySize)
|
|
return
|
|
}
|
|
bodySize = len(bodyBytes)
|
|
|
|
req := &models.CardUpdateRequest{}
|
|
if err := json.Unmarshal(bodyBytes, req); err != nil {
|
|
e.responser.ResponseWithError(e.log, r.Context(), w, http.StatusBadRequest, err, startTime, r.URL.Path, bodySize)
|
|
return
|
|
}
|
|
|
|
validate := validator.New()
|
|
err = validate.Struct(req)
|
|
if err != nil {
|
|
e.responser.ResponseWithError(e.log, r.Context(), w, http.StatusBadRequest, err, startTime, r.URL.Path, bodySize)
|
|
return
|
|
}
|
|
|
|
currentUser := r.Context().Value("userData").(*user.User)
|
|
resp, err := e.service.UpdateCard(projectID, int64(cardId), currentUser.ID, req)
|
|
if err != nil {
|
|
e.responser.ResponseWithError(e.log, r.Context(), w, http.StatusInternalServerError, err, startTime, r.URL.Path, bodySize)
|
|
return
|
|
}
|
|
|
|
e.responser.ResponseWithJSON(e.log, r.Context(), w, resp, startTime, r.URL.Path, bodySize)
|
|
}
|
|
|
|
func (e *handlersImpl) deleteCard(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
|
|
}
|
|
|
|
cardId, err := getIDFromRequest(r, "id")
|
|
if err != nil {
|
|
e.responser.ResponseWithError(e.log, r.Context(), w, http.StatusBadRequest, err, startTime, r.URL.Path, bodySize)
|
|
return
|
|
}
|
|
|
|
currentUser := r.Context().Value("userData").(*user.User)
|
|
err = e.service.DeleteCard(projectID, int64(cardId), currentUser.ID)
|
|
if err != nil {
|
|
e.responser.ResponseWithError(e.log, r.Context(), w, http.StatusInternalServerError, err, startTime, r.URL.Path, bodySize)
|
|
return
|
|
}
|
|
|
|
e.responser.ResponseWithJSON(e.log, r.Context(), w, nil, startTime, r.URL.Path, bodySize)
|
|
}
|
|
|
|
func (e *handlersImpl) getCardChartData(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)
|
|
return
|
|
}
|
|
bodySize = len(bodyBytes)
|
|
|
|
req := &models.GetCardChartDataRequest{}
|
|
if err := json.Unmarshal(bodyBytes, req); err != nil {
|
|
e.responser.ResponseWithError(e.log, r.Context(), w, http.StatusBadRequest, err, startTime, r.URL.Path, bodySize)
|
|
return
|
|
}
|
|
|
|
validate := validator.New()
|
|
err = validate.Struct(req)
|
|
if err != nil {
|
|
e.responser.ResponseWithError(e.log, r.Context(), w, http.StatusBadRequest, err, startTime, r.URL.Path, bodySize)
|
|
return
|
|
}
|
|
|
|
currentUser := r.Context().Value("userData").(*user.User)
|
|
resp, err := e.service.GetCardChartData(projectID, currentUser.ID, req)
|
|
if err != nil {
|
|
e.responser.ResponseWithError(e.log, r.Context(), w, http.StatusInternalServerError, err, startTime, r.URL.Path, bodySize)
|
|
return
|
|
}
|
|
|
|
e.responser.ResponseWithJSON(e.log, r.Context(), w, resp, startTime, r.URL.Path, bodySize)
|
|
}
|