feat: v1 API + frontend migration
Some checks failed
continuous-integration/drone/pr Build is failing
Some checks failed
continuous-integration/drone/pr Build is failing
This commit is contained in:
176
api/v1/activity.go
Normal file
176
api/v1/activity.go
Normal file
@@ -0,0 +1,176 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"reichard.io/antholume/database"
|
||||
)
|
||||
|
||||
// GET /activity
|
||||
func (s *Server) GetActivity(ctx context.Context, request GetActivityRequestObject) (GetActivityResponseObject, error) {
|
||||
auth, ok := s.getSessionFromContext(ctx)
|
||||
if !ok {
|
||||
return GetActivity401JSONResponse{Code: 401, Message: "Unauthorized"}, nil
|
||||
}
|
||||
|
||||
docFilter := false
|
||||
if request.Params.DocFilter != nil {
|
||||
docFilter = *request.Params.DocFilter
|
||||
}
|
||||
|
||||
documentID := ""
|
||||
if request.Params.DocumentId != nil {
|
||||
documentID = *request.Params.DocumentId
|
||||
}
|
||||
|
||||
page := int64(1)
|
||||
if request.Params.Page != nil {
|
||||
page = *request.Params.Page
|
||||
}
|
||||
|
||||
limit := int64(25)
|
||||
if request.Params.Limit != nil {
|
||||
limit = *request.Params.Limit
|
||||
}
|
||||
|
||||
activities, err := s.db.Queries.GetActivity(ctx, database.GetActivityParams{
|
||||
UserID: auth.UserName,
|
||||
DocFilter: docFilter,
|
||||
DocumentID: documentID,
|
||||
Offset: (page - 1) * limit,
|
||||
Limit: limit,
|
||||
})
|
||||
if err != nil {
|
||||
return GetActivity500JSONResponse{Code: 500, Message: err.Error()}, nil
|
||||
}
|
||||
|
||||
// Get Total Count
|
||||
total, err := s.db.Queries.GetActivityCount(ctx, database.GetActivityCountParams{
|
||||
UserID: auth.UserName,
|
||||
DocFilter: docFilter,
|
||||
DocumentID: documentID,
|
||||
})
|
||||
if err != nil {
|
||||
return GetActivity500JSONResponse{Code: 500, Message: err.Error()}, nil
|
||||
}
|
||||
|
||||
// Calculate Pagination
|
||||
var nextPage *int64
|
||||
var previousPage *int64
|
||||
if page*limit < total {
|
||||
nextPage = ptrOf(page + 1)
|
||||
}
|
||||
if page > 1 {
|
||||
previousPage = ptrOf(page - 1)
|
||||
}
|
||||
|
||||
apiActivities := make([]Activity, len(activities))
|
||||
for i, a := range activities {
|
||||
// Convert StartTime from interface{} to string
|
||||
startTimeStr := ""
|
||||
if a.StartTime != nil {
|
||||
if str, ok := a.StartTime.(string); ok {
|
||||
startTimeStr = str
|
||||
}
|
||||
}
|
||||
|
||||
apiActivities[i] = Activity{
|
||||
DocumentId: a.DocumentID,
|
||||
DeviceId: a.DeviceID,
|
||||
StartTime: startTimeStr,
|
||||
Title: a.Title,
|
||||
Author: a.Author,
|
||||
Duration: a.Duration,
|
||||
StartPercentage: float32(a.StartPercentage),
|
||||
EndPercentage: float32(a.EndPercentage),
|
||||
ReadPercentage: float32(a.ReadPercentage),
|
||||
}
|
||||
}
|
||||
|
||||
response := ActivityResponse{
|
||||
Activities: apiActivities,
|
||||
Page: page,
|
||||
Limit: limit,
|
||||
Total: total,
|
||||
NextPage: nextPage,
|
||||
PreviousPage: previousPage,
|
||||
}
|
||||
return GetActivity200JSONResponse(response), nil
|
||||
}
|
||||
|
||||
// POST /activity
|
||||
func (s *Server) CreateActivity(ctx context.Context, request CreateActivityRequestObject) (CreateActivityResponseObject, error) {
|
||||
auth, ok := s.getSessionFromContext(ctx)
|
||||
if !ok {
|
||||
return CreateActivity401JSONResponse{Code: 401, Message: "Unauthorized"}, nil
|
||||
}
|
||||
|
||||
if request.Body == nil {
|
||||
return CreateActivity400JSONResponse{Code: 400, Message: "Request body is required"}, nil
|
||||
}
|
||||
|
||||
tx, err := s.db.DB.Begin()
|
||||
if err != nil {
|
||||
log.Error("Transaction Begin DB Error:", err)
|
||||
return CreateActivity500JSONResponse{Code: 500, Message: "Database error"}, nil
|
||||
}
|
||||
committed := false
|
||||
defer func() {
|
||||
if committed {
|
||||
return
|
||||
}
|
||||
if rollbackErr := tx.Rollback(); rollbackErr != nil {
|
||||
log.Debug("Transaction Rollback DB Error:", rollbackErr)
|
||||
}
|
||||
}()
|
||||
|
||||
qtx := s.db.Queries.WithTx(tx)
|
||||
|
||||
allDocumentsMap := make(map[string]struct{})
|
||||
for _, item := range request.Body.Activity {
|
||||
allDocumentsMap[item.DocumentId] = struct{}{}
|
||||
}
|
||||
|
||||
for documentID := range allDocumentsMap {
|
||||
if _, err := qtx.UpsertDocument(ctx, database.UpsertDocumentParams{ID: documentID}); err != nil {
|
||||
log.Error("UpsertDocument DB Error:", err)
|
||||
return CreateActivity400JSONResponse{Code: 400, Message: "Invalid document"}, nil
|
||||
}
|
||||
}
|
||||
|
||||
if _, err := qtx.UpsertDevice(ctx, database.UpsertDeviceParams{
|
||||
ID: request.Body.DeviceId,
|
||||
UserID: auth.UserName,
|
||||
DeviceName: request.Body.DeviceName,
|
||||
LastSynced: time.Now().UTC().Format(time.RFC3339),
|
||||
}); err != nil {
|
||||
log.Error("UpsertDevice DB Error:", err)
|
||||
return CreateActivity400JSONResponse{Code: 400, Message: "Invalid device"}, nil
|
||||
}
|
||||
|
||||
for _, item := range request.Body.Activity {
|
||||
if _, err := qtx.AddActivity(ctx, database.AddActivityParams{
|
||||
UserID: auth.UserName,
|
||||
DocumentID: item.DocumentId,
|
||||
DeviceID: request.Body.DeviceId,
|
||||
StartTime: time.Unix(item.StartTime, 0).UTC().Format(time.RFC3339),
|
||||
Duration: item.Duration,
|
||||
StartPercentage: float64(item.Page) / float64(item.Pages),
|
||||
EndPercentage: float64(item.Page+1) / float64(item.Pages),
|
||||
}); err != nil {
|
||||
log.Error("AddActivity DB Error:", err)
|
||||
return CreateActivity400JSONResponse{Code: 400, Message: "Invalid activity"}, nil
|
||||
}
|
||||
}
|
||||
|
||||
if err := tx.Commit(); err != nil {
|
||||
log.Error("Transaction Commit DB Error:", err)
|
||||
return CreateActivity500JSONResponse{Code: 500, Message: "Database error"}, nil
|
||||
}
|
||||
committed = true
|
||||
|
||||
response := CreateActivityResponse{Added: int64(len(request.Body.Activity))}
|
||||
return CreateActivity200JSONResponse(response), nil
|
||||
}
|
||||
Reference in New Issue
Block a user