diff --git a/main.go b/main.go index 05a7a2a..4a3390d 100644 --- a/main.go +++ b/main.go @@ -183,7 +183,8 @@ func createServerDirectoriesIfNotExists() { cfg.LogsSystem, cfg.PublicStatic + "avatars/", cfg.PublicStatic + "grouptasks/", - cfg.PublicStatic + "sounds/"} + cfg.PublicStatic + "sounds/", + cfg.PublicStatic + "equipmentdocumentation/"} for _, path := range paths { _, err := os.Stat(path) diff --git a/modules/database/database.go b/modules/database/database.go index d4ec62f..4625cc2 100644 --- a/modules/database/database.go +++ b/modules/database/database.go @@ -43,6 +43,5 @@ func InitDatabase() { db.AutoMigrate(&structs.Role{}) db.AutoMigrate(&structs.RolePermission{}) db.AutoMigrate(&structs.UserApiKey{}) - db.AutoMigrate(&structs.Equipment{}) db.AutoMigrate(&structs.EquipmentDocumentation{}) } diff --git a/modules/equipment/equipment.go b/modules/equipment/equipment.go index 605db34..3245199 100644 --- a/modules/equipment/equipment.go +++ b/modules/equipment/equipment.go @@ -1,20 +1,25 @@ package equipment import ( - "encoding/json" - "errors" "jannex/admin-dashboard-backend/modules/database" "jannex/admin-dashboard-backend/modules/structs" "github.com/gofiber/fiber/v2" - "github.com/rs/zerolog/log" - "gorm.io/gorm" ) const Base = "https://inv.ex.umbach.dev" const apiBase = Base + "/api" const ApiToken = "1367f15d21935e4eb540f897946fb5cd98485c3f" +func GetEquipmentDocumentation(stockItemId string, c *fiber.Ctx) error { + var documentations []structs.EquipmentDocumentation + + database.DB.Where("stock_item_id = ?", stockItemId).Find(&documentations) + + return c.JSON(documentations) +} + +/* func GetEquipmentDocumentation(stockItemId string, c *fiber.Ctx) error { equipment := structs.Equipment{Id: stockItemId} @@ -79,14 +84,16 @@ func GetEquipmentDocumentation(stockItemId string, c *fiber.Ctx) error { return c.JSON([]structs.EquipmentDocumentation{}) } +*/ +/* func GetEquipment() []structs.Equipment { var equipments []structs.Equipment database.DB.Find(&equipments) return equipments -} +}*/ /* // return whether the scanned equipment is existing in the database diff --git a/modules/grouptasks/grouptasks.go b/modules/grouptasks/grouptasks.go index 917fd40..7b68f24 100644 --- a/modules/grouptasks/grouptasks.go +++ b/modules/grouptasks/grouptasks.go @@ -4,7 +4,6 @@ import ( "encoding/json" "errors" "fmt" - "io/ioutil" "jannex/admin-dashboard-backend/modules/cache" "jannex/admin-dashboard-backend/modules/config" "jannex/admin-dashboard-backend/modules/database" @@ -535,7 +534,7 @@ func RunGroupTask(args RunGroupTaskArgs) { log.Error().Msgf("Error reading file %s", err.Error()) } - err = ioutil.WriteFile(config.Cfg.FolderPaths.GroupTasksRunningTasks+groupTaskStep.GroupTasksId+"/"+info.Name(), bytesRead, 0644) + err = os.WriteFile(config.Cfg.FolderPaths.GroupTasksRunningTasks+groupTaskStep.GroupTasksId+"/"+info.Name(), bytesRead, 0644) if err != nil { log.Error().Msgf("Error writing file %s", err.Error()) diff --git a/modules/structs/equipment.go b/modules/structs/equipment.go index 1552cf3..b059fd5 100644 --- a/modules/structs/equipment.go +++ b/modules/structs/equipment.go @@ -1,22 +1,37 @@ package structs -import "time" +import ( + "encoding/json" + "time" +) +/* type Equipment struct { Id string // stock item id of invex system Name string Thumbnail string // url provided by invex system CreatedAt time.Time UpdatedAt time.Time -} +} */ type EquipmentDocumentation struct { - Id string // stock item id of invex system - Content string - CreatedAt time.Time - UpdatedAt time.Time + Id string + StockItemId string // stock item id of invex system + Type uint8 + Title string + Notes string + CreatedByUserId string + CreatedAt time.Time + UpdatedAt time.Time } type ApiEquipmentParamsRequest struct { StockItemId string `json:"stockItemId"` } + +type ApiCreateEquipmentDocumentationRequest struct { + StockItemId string `json:"stockItemId"` + Type uint8 `json:"type"` + Title string `json:"title"` + Notes json.RawMessage `json:"notes"` +} diff --git a/routers/router/api/v1/equipment/equipment.go b/routers/router/api/v1/equipment/equipment.go index febda87..638f5ac 100644 --- a/routers/router/api/v1/equipment/equipment.go +++ b/routers/router/api/v1/equipment/equipment.go @@ -1,16 +1,117 @@ package equipment import ( + "encoding/base64" + "encoding/json" + "jannex/admin-dashboard-backend/modules/config" + "jannex/admin-dashboard-backend/modules/database" "jannex/admin-dashboard-backend/modules/equipment" "jannex/admin-dashboard-backend/modules/structs" "jannex/admin-dashboard-backend/modules/utils" + "os" + "strings" "github.com/gofiber/fiber/v2" + "github.com/google/uuid" "github.com/rs/zerolog/log" ) -func GetEquipment(c *fiber.Ctx) error { - return c.JSON(equipment.GetEquipment()) +func getImageType(data string) string { + switch data { + case "data:image/png;base64": + return "png" + default: + return "jpeg" + } +} + +type Notes struct { + Image string + Description string +} + +func CreateEquipmentDocumentation(c *fiber.Ctx) error { + var body structs.ApiCreateEquipmentDocumentationRequest + + if err := c.BodyParser(&body); err != nil { + return c.Status(fiber.StatusBadRequest).JSON(err) + } + + var bodyNotes []map[string]string + + err := json.Unmarshal(body.Notes, &bodyNotes) + + if err != nil { + log.Error().Msgf("Failed to unmarshal json, err: %s", err) + return c.SendStatus(fiber.StatusInternalServerError) + } + + newEquipmentDocumentation := structs.EquipmentDocumentation{ + Id: uuid.New().String(), + StockItemId: body.StockItemId, + Type: body.Type, + Title: body.Title, + } + + // TODO: only create folder if there is an image + if err := os.Mkdir(config.Cfg.FolderPaths.PublicStatic+"/equipmentdocumentation/"+newEquipmentDocumentation.Id, os.ModePerm); err != nil { + log.Error().Msgf("Failed to create folder, err: %s", err) + return c.SendStatus(fiber.StatusInternalServerError) + } + + var notes []Notes + + // loop throught bodyNotes and save image to static folder under random name + for _, bodyNote := range bodyNotes { + log.Info().Msgf("bodyNote %s", bodyNote) + + var newFileName string + + if bodyNote["image"] != "" { + // image is sent as base64 string + // decode it and save it to the static folder + + // encoded base64 image structure is: data:image/jpeg;base64,/9j/4AA... + splittedImageData := strings.Split(bodyNote["image"], ",") + + decodedImage, err := base64.StdEncoding.DecodeString(splittedImageData[1]) + + if err != nil { + log.Error().Msgf("Failed to decode base64 string, err: %s", err) + return c.SendStatus(fiber.StatusInternalServerError) + + } + + newFileName = uuid.New().String() + "." + getImageType(splittedImageData[0]) + + err = os.WriteFile(config.Cfg.FolderPaths.PublicStatic+"/equipmentdocumentation/"+newEquipmentDocumentation.Id+"/"+newFileName, decodedImage, 0644) + + if err != nil { + log.Error().Msgf("Failed to save image, err: %s", err) + return c.SendStatus(fiber.StatusInternalServerError) + } + } + + notes = append(notes, Notes{ + Image: newFileName, + Description: bodyNote["description"], + }) + } + + log.Info().Msgf("bodyNotes %v", bodyNotes) + + marshaledNotes, err := json.Marshal(notes) + + if err != nil { + log.Error().Msgf("Failed to marshal notes, err: %s", err) + return c.SendStatus(fiber.StatusInternalServerError) + } + + newEquipmentDocumentation.Notes = string(marshaledNotes) + + database.DB.Create(&newEquipmentDocumentation) + + return c.JSON(fiber.Map{"message": "ok"}) } func GetEquipmentDocumentation(c *fiber.Ctx) error { @@ -48,13 +149,6 @@ func GetEquipmentThumbnail(c *fiber.Ctx) error { code, body, errs := a.Bytes() log.Info().Msgf("code %d %s", code, errs) - /* - resp := fiber.AcquireResponse() - - a.SetResponse(resp) - - fiber.ReleaseResponse(resp) - */ c.Set("Content-Type", "image/png") diff --git a/routers/router/router.go b/routers/router/router.go index ca5140a..a51d47f 100644 --- a/routers/router/router.go +++ b/routers/router/router.go @@ -40,8 +40,9 @@ func SetupRoutes(app *fiber.App) { e := v1.Group("/equipment") // TODO: add user session validation //e.Get("/scanned/:stockItemId", requestAccessValidation, equipment.EquipmentScanned) - e.Get("/", requestAccessValidation, equipment.GetEquipment) + //e.Get("/", requestAccessValidation, equipment.GetEquipment) e.Get("/documentation/:stockItemId", requestAccessValidation, equipment.GetEquipmentDocumentation) + e.Post("/documentation/create", requestAccessValidation, equipment.CreateEquipmentDocumentation) // access validation here implented as it would require to implement authorization on web client side on Avatar Component e.Get("/thumbnail/media/part_images/:stockItemThumbnail", equipment.GetEquipmentThumbnail)