openreplay/backend/pkg/analytics/api/card-handlers.go
2024-12-16 10:36:25 +01:00

269 lines
6.6 KiB
Go

package api
import (
"encoding/json"
"fmt"
"github.com/gorilla/mux"
"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"
)
// getCardId returns the ID from the request
func getCardId(r *http.Request) (int64, error) {
vars := mux.Vars(r)
idStr := vars["id"]
if idStr == "" {
return 0, fmt.Errorf("invalid Card ID")
}
id, err := strconv.ParseInt(idStr, 10, 64)
if err != nil {
return 0, fmt.Errorf("invalid Card ID")
}
return id, nil
}
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
}
// TODO save card to DB
resp := &models.CardGetResponse{
Card: models.Card{
CardID: 1,
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
DeletedAt: nil,
EditedAt: nil,
ProjectID: 1,
UserID: 1,
CardBase: models.CardBase{
Name: req.Name,
IsPublic: req.IsPublic,
Thumbnail: req.Thumbnail,
MetricType: req.MetricType,
MetricOf: req.MetricOf,
Series: req.Series,
},
},
}
currentUser := r.Context().Value("userData").(*user.User)
e.log.Info(r.Context(), "User ID: ", currentUser.ID)
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
id, err := getCardId(r)
if err != nil {
e.responser.ResponseWithError(e.log, r.Context(), w, http.StatusBadRequest, err, startTime, r.URL.Path, bodySize)
return
}
thumbnail := "https://example.com/image.png"
// TODO get card from DB
resp := &models.CardGetResponse{
Card: models.Card{
CardID: id,
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
DeletedAt: nil,
EditedAt: nil,
ProjectID: 1,
UserID: 1,
CardBase: models.CardBase{
Name: "My Card",
IsPublic: true,
Thumbnail: &thumbnail,
MetricType: "timeseries",
MetricOf: "session_count",
},
},
}
e.responser.ResponseWithJSON(e.log, r.Context(), w, resp, startTime, r.URL.Path, bodySize)
}
// get cards paginated
func (e *handlersImpl) getCards(w http.ResponseWriter, r *http.Request) {
startTime := time.Now()
bodySize := 0
// TODO get cards from DB
thumbnail := "https://example.com/image.png"
resp := &models.GetCardsResponse{
Cards: []models.Card{
{
CardID: 1,
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
DeletedAt: nil,
EditedAt: nil,
ProjectID: 1,
UserID: 1,
CardBase: models.CardBase{
Name: "My Card",
IsPublic: true,
Thumbnail: &thumbnail,
MetricType: "timeseries",
MetricOf: "session_count",
},
},
},
Total: 10,
}
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
id, err := getCardId(r)
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
}
// TODO update card in DB
resp := &models.CardGetResponse{
Card: models.Card{
CardID: id,
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
DeletedAt: nil,
EditedAt: nil,
ProjectID: 1,
UserID: 1,
CardBase: models.CardBase{
Name: req.Name,
IsPublic: req.IsPublic,
Thumbnail: req.Thumbnail,
MetricType: req.MetricType,
MetricOf: req.MetricOf,
},
},
}
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
_, err := getCardId(r)
if err != nil {
e.responser.ResponseWithError(e.log, r.Context(), w, http.StatusBadRequest, err, startTime, r.URL.Path, bodySize)
return
}
// TODO delete card from DB
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
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)
// TODO get card chart data from ClickHouse
jsonInput := `
{
"data": [
{
"timestamp": 1733934939000,
"Series A": 100,
"Series B": 200
},
{
"timestamp": 1733935939000,
"Series A": 150,
"Series B": 250
}
]
}`
var resp models.GetCardChartDataResponse
err = json.Unmarshal([]byte(jsonInput), &resp)
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)
}