Compare commits
No commits in common. "154bc1228766a6dde060fcff767ee8ff0c97b744" and "0987814407305ace4c752de54cc00302613b05cd" have entirely different histories.
154bc12287
...
0987814407
|
|
@ -11,7 +11,8 @@ type AboutUsContentImage struct {
|
||||||
CreatedAt time.Time `json:"created_at" gorm:"default:now()"`
|
CreatedAt time.Time `json:"created_at" gorm:"default:now()"`
|
||||||
UpdatedAt time.Time `json:"updated_at" gorm:"default:now()"`
|
UpdatedAt time.Time `json:"updated_at" gorm:"default:now()"`
|
||||||
|
|
||||||
AboutUsContent AboutUsContent `json:"-" gorm:"foreignKey:AboutUsContentID"`
|
// relation (optional tapi bagus)
|
||||||
|
AboutUsContent AboutUsContent `json:"about_us_content" gorm:"foreignKey:AboutUsContentID"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (AboutUsContentImage) TableName() string {
|
func (AboutUsContentImage) TableName() string {
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,6 @@ type AboutUsContent struct {
|
||||||
IsActive *bool `json:"is_active" gorm:"type:bool;default:true"`
|
IsActive *bool `json:"is_active" gorm:"type:bool;default:true"`
|
||||||
CreatedAt time.Time `json:"created_at" gorm:"default:now()"`
|
CreatedAt time.Time `json:"created_at" gorm:"default:now()"`
|
||||||
UpdatedAt time.Time `json:"updated_at" gorm:"default:now()"`
|
UpdatedAt time.Time `json:"updated_at" gorm:"default:now()"`
|
||||||
|
|
||||||
Images []AboutUsContentImage `json:"images,omitempty" gorm:"foreignKey:AboutUsContentID"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (AboutUsContent) TableName() string {
|
func (AboutUsContent) TableName() string {
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type HeroContents struct {
|
type HeroContents struct {
|
||||||
ID uuid.UUID `json:"id" gorm:"primaryKey;type:uuid"`
|
ID uuid.UUID `json:"id" gorm:"primaryKey;type:uuid;default:uuid_generate_v4()"`
|
||||||
PrimaryTitle string `json:"primary_title" gorm:"type:varchar(255)"`
|
PrimaryTitle string `json:"primary_title" gorm:"type:varchar(255)"`
|
||||||
SecondaryTitle string `json:"secondary_title" gorm:"type:varchar(255)"`
|
SecondaryTitle string `json:"secondary_title" gorm:"type:varchar(255)"`
|
||||||
Description string `json:"description" gorm:"type:text"`
|
Description string `json:"description" gorm:"type:text"`
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type HeroContentImages struct {
|
type HeroContentImages struct {
|
||||||
ID uuid.UUID `json:"id" gorm:"primaryKey;type:uuid"`
|
ID uuid.UUID `json:"id" gorm:"primaryKey;type:uuid;default:uuid_generate_v4()"`
|
||||||
HeroContentID uuid.UUID `json:"hero_content_id" gorm:"type:uuid;not null"`
|
HeroContentID uuid.UUID `json:"hero_content_id" gorm:"type:uuid;not null"`
|
||||||
ImagePath string `json:"image_path" gorm:"type:text"`
|
ImagePath string `json:"image_path" gorm:"type:text"`
|
||||||
ImageURL string `json:"image_url" gorm:"type:text"`
|
ImageURL string `json:"image_url" gorm:"type:text"`
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type OurProductContentImage struct {
|
type OurProductContentImage struct {
|
||||||
ID uuid.UUID `json:"id" gorm:"primaryKey;type:uuid"`
|
ID uuid.UUID `json:"id" gorm:"primaryKey;type:uuid;default:uuid_generate_v4()"`
|
||||||
OurProductContentID uuid.UUID `json:"our_product_content_id" gorm:"type:uuid"`
|
OurProductContentID uuid.UUID `json:"our_product_content_id" gorm:"type:uuid"`
|
||||||
ImagePath string `json:"image_path" gorm:"type:varchar(255)"`
|
ImagePath string `json:"image_path" gorm:"type:varchar(255)"`
|
||||||
ImageURL string `json:"image_url" gorm:"type:text"`
|
ImageURL string `json:"image_url" gorm:"type:text"`
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type OurProductContent struct {
|
type OurProductContent struct {
|
||||||
ID uuid.UUID `json:"id" gorm:"primaryKey;type:uuid"`
|
ID uuid.UUID `json:"id" gorm:"primaryKey;type:uuid;default:uuid_generate_v4()"`
|
||||||
PrimaryTitle string `json:"primary_title" gorm:"type:varchar(255)"`
|
PrimaryTitle string `json:"primary_title" gorm:"type:varchar(255)"`
|
||||||
SecondaryTitle string `json:"secondary_title" gorm:"type:varchar(255)"`
|
SecondaryTitle string `json:"secondary_title" gorm:"type:varchar(255)"`
|
||||||
Description string `json:"description" gorm:"type:text"`
|
Description string `json:"description" gorm:"type:text"`
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type PartnerContent struct {
|
type PartnerContent struct {
|
||||||
ID uuid.UUID `json:"id" gorm:"primaryKey;type:uuid"`
|
ID uuid.UUID `json:"id" gorm:"primaryKey;type:uuid;default:uuid_generate_v4()"`
|
||||||
PrimaryTitle string `json:"primary_title" gorm:"type:varchar(255)"`
|
PrimaryTitle string `json:"primary_title" gorm:"type:varchar(255)"`
|
||||||
ImagePath string `json:"image_path" gorm:"type:varchar(255)"`
|
ImagePath string `json:"image_path" gorm:"type:varchar(255)"`
|
||||||
ImageURL string `json:"image_url" gorm:"type:text"`
|
ImageURL string `json:"image_url" gorm:"type:text"`
|
||||||
|
|
|
||||||
|
|
@ -103,13 +103,13 @@ func Models() []interface{} {
|
||||||
entity.Bookmarks{},
|
entity.Bookmarks{},
|
||||||
entity.Cities{},
|
entity.Cities{},
|
||||||
entity.Clients{},
|
entity.Clients{},
|
||||||
entity.HeroContents{},
|
|
||||||
entity.HeroContentImages{},
|
|
||||||
entity.ClientApprovalSettings{},
|
entity.ClientApprovalSettings{},
|
||||||
entity.CsrfTokenRecords{},
|
entity.CsrfTokenRecords{},
|
||||||
entity.CustomStaticPages{},
|
entity.CustomStaticPages{},
|
||||||
entity.Districts{},
|
entity.Districts{},
|
||||||
entity.Feedbacks{},
|
entity.Feedbacks{},
|
||||||
|
entity.HeroContents{},
|
||||||
|
entity.HeroContentImages{},
|
||||||
entity.ForgotPasswords{},
|
entity.ForgotPasswords{},
|
||||||
entity.Magazines{},
|
entity.Magazines{},
|
||||||
entity.MagazineFiles{},
|
entity.MagazineFiles{},
|
||||||
|
|
@ -121,11 +121,7 @@ func Models() []interface{} {
|
||||||
entity.OneTimePasswords{},
|
entity.OneTimePasswords{},
|
||||||
entity.OurProductContent{},
|
entity.OurProductContent{},
|
||||||
entity.OurProductContentImage{},
|
entity.OurProductContentImage{},
|
||||||
entity.OurServiceContent{},
|
|
||||||
entity.OurServiceContentImage{},
|
|
||||||
entity.PartnerContent{},
|
entity.PartnerContent{},
|
||||||
entity.PopupNewsContents{},
|
|
||||||
entity.PopupNewsContentImages{},
|
|
||||||
entity.Subscription{},
|
entity.Subscription{},
|
||||||
entity.Schedules{},
|
entity.Schedules{},
|
||||||
entity.UserLevels{},
|
entity.UserLevels{},
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,6 @@ func (_i *AboutUsContentImageRouter) RegisterAboutUsContentImageRoutes() {
|
||||||
_i.App.Route("/about-us-content-images", func(router fiber.Router) {
|
_i.App.Route("/about-us-content-images", func(router fiber.Router) {
|
||||||
|
|
||||||
router.Get("/", aboutUsContentImageController.All)
|
router.Get("/", aboutUsContentImageController.All)
|
||||||
router.Post("/url", aboutUsContentImageController.SaveRemote)
|
|
||||||
router.Get("/:id", aboutUsContentImageController.Show)
|
router.Get("/:id", aboutUsContentImageController.Show)
|
||||||
|
|
||||||
// upload image (pakai form-data)
|
// upload image (pakai form-data)
|
||||||
|
|
|
||||||
|
|
@ -3,14 +3,12 @@ package controller
|
||||||
import (
|
import (
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"web-qudo-be/app/module/about_us_content_images/request"
|
|
||||||
"web-qudo-be/app/module/about_us_content_images/service"
|
"web-qudo-be/app/module/about_us_content_images/service"
|
||||||
|
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
|
|
||||||
utilRes "web-qudo-be/utils/response"
|
utilRes "web-qudo-be/utils/response"
|
||||||
utilVal "web-qudo-be/utils/validator"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type aboutUsContentImageController struct {
|
type aboutUsContentImageController struct {
|
||||||
|
|
@ -22,7 +20,6 @@ type AboutUsContentImageController interface {
|
||||||
All(c *fiber.Ctx) error
|
All(c *fiber.Ctx) error
|
||||||
Show(c *fiber.Ctx) error
|
Show(c *fiber.Ctx) error
|
||||||
Save(c *fiber.Ctx) error
|
Save(c *fiber.Ctx) error
|
||||||
SaveRemote(c *fiber.Ctx) error
|
|
||||||
Delete(c *fiber.Ctx) error
|
Delete(c *fiber.Ctx) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -98,24 +95,6 @@ func (_i *aboutUsContentImageController) Save(c *fiber.Ctx) error {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// SaveRemote JSON: public URL for image or video (e.g. CDN .mp4)
|
|
||||||
func (_i *aboutUsContentImageController) SaveRemote(c *fiber.Ctx) error {
|
|
||||||
req := new(request.AboutUsContentImageRemoteRequest)
|
|
||||||
if err := utilVal.ParseAndValidate(c, req); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
result, err := _i.service.SaveRemoteURL(req.AboutUsContentID, req.MediaURL, req.MediaType)
|
|
||||||
if err != nil {
|
|
||||||
_i.Log.Error().Err(err).Msg("failed save remote about us media")
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return utilRes.Resp(c, utilRes.Response{
|
|
||||||
Success: true,
|
|
||||||
Messages: utilRes.Messages{"About us media URL saved"},
|
|
||||||
Data: result,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// DELETE
|
// DELETE
|
||||||
func (_i *aboutUsContentImageController) Delete(c *fiber.Ctx) error {
|
func (_i *aboutUsContentImageController) Delete(c *fiber.Ctx) error {
|
||||||
id, err := strconv.Atoi(c.Params("id"))
|
id, err := strconv.Atoi(c.Params("id"))
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,9 @@ func NewAboutUsContentImageRepository(db *database.Database, log zerolog.Logger)
|
||||||
|
|
||||||
// GET ALL
|
// GET ALL
|
||||||
func (_i *aboutUsContentImageRepository) GetAll() (images []*entity.AboutUsContentImage, err error) {
|
func (_i *aboutUsContentImageRepository) GetAll() (images []*entity.AboutUsContentImage, err error) {
|
||||||
err = _i.DB.DB.Find(&images).Error
|
err = _i.DB.DB.
|
||||||
|
Where("is_active = ?", true).
|
||||||
|
Find(&images).Error
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -50,7 +52,7 @@ func (_i *aboutUsContentImageRepository) FindOne(id uint) (image *entity.AboutUs
|
||||||
// GET BY ABOUT US CONTENT ID
|
// GET BY ABOUT US CONTENT ID
|
||||||
func (_i *aboutUsContentImageRepository) FindByContentID(contentID uint) (images []*entity.AboutUsContentImage, err error) {
|
func (_i *aboutUsContentImageRepository) FindByContentID(contentID uint) (images []*entity.AboutUsContentImage, err error) {
|
||||||
err = _i.DB.DB.
|
err = _i.DB.DB.
|
||||||
Where("about_us_content_id = ?", contentID).
|
Where("about_us_content_id = ? AND is_active = ?", contentID, true).
|
||||||
Find(&images).Error
|
Find(&images).Error
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
package request
|
|
||||||
|
|
||||||
type AboutUsContentImageRemoteRequest struct {
|
|
||||||
AboutUsContentID uint `json:"about_us_content_id" validate:"required"`
|
|
||||||
MediaURL string `json:"media_url" validate:"required"`
|
|
||||||
MediaType string `json:"media_type"`
|
|
||||||
}
|
|
||||||
|
|
@ -2,22 +2,19 @@ package service
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"mime"
|
|
||||||
"mime/multipart"
|
"mime/multipart"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"time"
|
||||||
|
|
||||||
"web-qudo-be/app/database/entity"
|
"web-qudo-be/app/database/entity"
|
||||||
"web-qudo-be/app/module/about_us_content_images/repository"
|
"web-qudo-be/app/module/about_us_content_images/repository"
|
||||||
minioStorage "web-qudo-be/config/config"
|
|
||||||
"web-qudo-be/utils/storage"
|
|
||||||
|
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
|
|
||||||
|
fileUtil "web-qudo-be/utils/file"
|
||||||
)
|
)
|
||||||
|
|
||||||
type aboutUsContentImageService struct {
|
type aboutUsContentImageService struct {
|
||||||
Repo repository.AboutUsContentImageRepository
|
Repo repository.AboutUsContentImageRepository
|
||||||
MinioStorage *minioStorage.MinioStorage
|
|
||||||
Log zerolog.Logger
|
Log zerolog.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -25,18 +22,15 @@ type AboutUsContentImageService interface {
|
||||||
All() (images []*entity.AboutUsContentImage, err error)
|
All() (images []*entity.AboutUsContentImage, err error)
|
||||||
Show(id uint) (image *entity.AboutUsContentImage, err error)
|
Show(id uint) (image *entity.AboutUsContentImage, err error)
|
||||||
Save(aboutUsContentId uint, file *multipart.FileHeader) (image *entity.AboutUsContentImage, err error)
|
Save(aboutUsContentId uint, file *multipart.FileHeader) (image *entity.AboutUsContentImage, err error)
|
||||||
SaveRemoteURL(aboutUsContentID uint, mediaURL, mediaType string) (image *entity.AboutUsContentImage, err error)
|
|
||||||
Delete(id uint) error
|
Delete(id uint) error
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAboutUsContentImageService(
|
func NewAboutUsContentImageService(
|
||||||
repo repository.AboutUsContentImageRepository,
|
repo repository.AboutUsContentImageRepository,
|
||||||
minio *minioStorage.MinioStorage,
|
|
||||||
log zerolog.Logger,
|
log zerolog.Logger,
|
||||||
) AboutUsContentImageService {
|
) AboutUsContentImageService {
|
||||||
return &aboutUsContentImageService{
|
return &aboutUsContentImageService{
|
||||||
Repo: repo,
|
Repo: repo,
|
||||||
MinioStorage: minio,
|
|
||||||
Log: log,
|
Log: log,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -54,28 +48,31 @@ func (_i *aboutUsContentImageService) Save(aboutUsContentId uint, file *multipar
|
||||||
_i.Log.Info().
|
_i.Log.Info().
|
||||||
Uint("aboutUsContentId", aboutUsContentId).
|
Uint("aboutUsContentId", aboutUsContentId).
|
||||||
Str("filename", file.Filename).
|
Str("filename", file.Filename).
|
||||||
Msg("upload about us media")
|
Msg("upload image")
|
||||||
|
|
||||||
key, url, err := storage.UploadCMSObject(_i.MinioStorage, "about-us", file, true)
|
// validasi file
|
||||||
if err != nil {
|
ext := filepath.Ext(file.Filename)
|
||||||
|
if ext != ".jpg" && ext != ".jpeg" && ext != ".png" {
|
||||||
|
return nil, fmt.Errorf("invalid file type")
|
||||||
|
}
|
||||||
|
|
||||||
|
// generate filename
|
||||||
|
filename := fmt.Sprintf("about_us_%d_%d%s", aboutUsContentId, time.Now().Unix(), ext)
|
||||||
|
|
||||||
|
filePath := fmt.Sprintf("./uploads/%s", filename)
|
||||||
|
|
||||||
|
// save file
|
||||||
|
if err := fileUtil.SaveFile(file, filePath); err != nil {
|
||||||
|
_i.Log.Error().Err(err).Msg("failed save file")
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
ext := strings.ToLower(filepath.Ext(file.Filename))
|
// save ke DB
|
||||||
mt := mime.TypeByExtension(ext)
|
|
||||||
if mt == "" {
|
|
||||||
if ext == ".mp4" || ext == ".webm" {
|
|
||||||
mt = "video/" + strings.TrimPrefix(ext, ".")
|
|
||||||
} else {
|
|
||||||
mt = "application/octet-stream"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
data := &entity.AboutUsContentImage{
|
data := &entity.AboutUsContentImage{
|
||||||
AboutUsContentID: aboutUsContentId,
|
AboutUsContentID: aboutUsContentId,
|
||||||
MediaPath: key,
|
MediaPath: filePath,
|
||||||
MediaType: mt,
|
MediaType: ext,
|
||||||
MediaURL: url,
|
MediaURL: "/uploads/" + filename,
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := _i.Repo.Create(data)
|
result, err := _i.Repo.Create(data)
|
||||||
|
|
@ -87,27 +84,6 @@ func (_i *aboutUsContentImageService) Save(aboutUsContentId uint, file *multipar
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (_i *aboutUsContentImageService) SaveRemoteURL(aboutUsContentID uint, mediaURL, mediaType string) (image *entity.AboutUsContentImage, err error) {
|
|
||||||
if strings.TrimSpace(mediaURL) == "" {
|
|
||||||
return nil, fmt.Errorf("media_url is required")
|
|
||||||
}
|
|
||||||
mt := mediaType
|
|
||||||
if mt == "" {
|
|
||||||
lower := strings.ToLower(mediaURL)
|
|
||||||
if strings.HasSuffix(lower, ".mp4") || strings.Contains(lower, "video") {
|
|
||||||
mt = "video/mp4"
|
|
||||||
} else {
|
|
||||||
mt = "image/url"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
data := &entity.AboutUsContentImage{
|
|
||||||
AboutUsContentID: aboutUsContentID,
|
|
||||||
MediaURL: mediaURL,
|
|
||||||
MediaType: mt,
|
|
||||||
}
|
|
||||||
return _i.Repo.Create(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (_i *aboutUsContentImageService) Delete(id uint) error {
|
func (_i *aboutUsContentImageService) Delete(id uint) error {
|
||||||
return _i.Repo.Delete(id)
|
return _i.Repo.Delete(id)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ package controller
|
||||||
import (
|
import (
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"web-qudo-be/app/module/about_us_contents/request"
|
|
||||||
"web-qudo-be/app/module/about_us_contents/service"
|
"web-qudo-be/app/module/about_us_contents/service"
|
||||||
|
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
|
|
@ -72,13 +71,13 @@ func (_i *aboutUsContentController) Show(c *fiber.Ctx) error {
|
||||||
|
|
||||||
// CREATE
|
// CREATE
|
||||||
func (_i *aboutUsContentController) Save(c *fiber.Ctx) error {
|
func (_i *aboutUsContentController) Save(c *fiber.Ctx) error {
|
||||||
req := new(request.AboutUsContentCreateRequest)
|
req := new(map[string]interface{})
|
||||||
|
|
||||||
if err := utilVal.ParseAndValidate(c, req); err != nil {
|
if err := utilVal.ParseAndValidate(c, req); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := _i.service.Save(req.ToEntity())
|
result, err := _i.service.Save(*req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_i.Log.Error().Err(err).Msg("failed create about us content")
|
_i.Log.Error().Err(err).Msg("failed create about us content")
|
||||||
return err
|
return err
|
||||||
|
|
@ -98,13 +97,13 @@ func (_i *aboutUsContentController) Update(c *fiber.Ctx) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
req := new(request.AboutUsContentUpdateRequest)
|
req := new(map[string]interface{})
|
||||||
|
|
||||||
if err := utilVal.ParseAndValidate(c, req); err != nil {
|
if err := utilVal.ParseAndValidate(c, req); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = _i.service.Update(uint(id), req.ToEntity())
|
err = _i.service.Update(uint(id), *req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_i.Log.Error().Err(err).Msg("failed update about us content")
|
_i.Log.Error().Err(err).Msg("failed update about us content")
|
||||||
return err
|
return err
|
||||||
|
|
|
||||||
|
|
@ -34,9 +34,7 @@ func (r *aboutUsContentRepository) GetAll() ([]*entity.AboutUsContent, error) {
|
||||||
var results []*entity.AboutUsContent
|
var results []*entity.AboutUsContent
|
||||||
|
|
||||||
err := r.DB.DB.
|
err := r.DB.DB.
|
||||||
Preload("Images").
|
Where("is_active = ?", true).
|
||||||
Where("is_active IS NULL OR is_active = ?", true).
|
|
||||||
Order("id ASC").
|
|
||||||
Find(&results).Error
|
Find(&results).Error
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -71,24 +69,12 @@ func (r *aboutUsContentRepository) Create(data *entity.AboutUsContent) (*entity.
|
||||||
return data, nil
|
return data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update uses a column map so we never SET primary key / created_at to zero values (breaks FK children).
|
// UPDATE
|
||||||
func (r *aboutUsContentRepository) Update(id uint, data *entity.AboutUsContent) error {
|
func (r *aboutUsContentRepository) Update(id uint, data *entity.AboutUsContent) error {
|
||||||
updates := map[string]interface{}{
|
|
||||||
"primary_title": data.PrimaryTitle,
|
|
||||||
"secondary_title": data.SecondaryTitle,
|
|
||||||
"description": data.Description,
|
|
||||||
"primary_cta": data.PrimaryCta,
|
|
||||||
"secondary_cta_text": data.SecondaryCtaText,
|
|
||||||
"updated_at": data.UpdatedAt,
|
|
||||||
}
|
|
||||||
if data.IsActive != nil {
|
|
||||||
updates["is_active"] = data.IsActive
|
|
||||||
}
|
|
||||||
|
|
||||||
err := r.DB.DB.
|
err := r.DB.DB.
|
||||||
Model(&entity.AboutUsContent{}).
|
Model(&entity.AboutUsContent{}).
|
||||||
Where("id = ?", id).
|
Where("id = ?", id).
|
||||||
Updates(updates).Error
|
Updates(data).Error
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.Log.Error().Err(err).Msg("failed update about us content")
|
r.Log.Error().Err(err).Msg("failed update about us content")
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
package service
|
package service
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
|
|
||||||
"web-qudo-be/app/database/entity"
|
"web-qudo-be/app/database/entity"
|
||||||
|
|
@ -17,8 +15,8 @@ type aboutUsContentService struct {
|
||||||
type AboutUsContentService interface {
|
type AboutUsContentService interface {
|
||||||
All() ([]*entity.AboutUsContent, error)
|
All() ([]*entity.AboutUsContent, error)
|
||||||
Show(id uint) (*entity.AboutUsContent, error)
|
Show(id uint) (*entity.AboutUsContent, error)
|
||||||
Save(data *entity.AboutUsContent) (*entity.AboutUsContent, error)
|
Save(data map[string]interface{}) (*entity.AboutUsContent, error)
|
||||||
Update(id uint, data *entity.AboutUsContent) error
|
Update(id uint, data map[string]interface{}) error
|
||||||
Delete(id uint) error
|
Delete(id uint) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -55,8 +53,26 @@ func (s *aboutUsContentService) Show(id uint) (*entity.AboutUsContent, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// CREATE
|
// CREATE
|
||||||
func (s *aboutUsContentService) Save(data *entity.AboutUsContent) (*entity.AboutUsContent, error) {
|
func (s *aboutUsContentService) Save(data map[string]interface{}) (*entity.AboutUsContent, error) {
|
||||||
result, err := s.Repo.Create(data)
|
entityData := &entity.AboutUsContent{}
|
||||||
|
|
||||||
|
if v, ok := data["primary_title"].(string); ok {
|
||||||
|
entityData.PrimaryTitle = v
|
||||||
|
}
|
||||||
|
if v, ok := data["secondary_title"].(string); ok {
|
||||||
|
entityData.SecondaryTitle = v
|
||||||
|
}
|
||||||
|
if v, ok := data["description"].(string); ok {
|
||||||
|
entityData.Description = v
|
||||||
|
}
|
||||||
|
if v, ok := data["primary_cta"].(string); ok {
|
||||||
|
entityData.PrimaryCta = v
|
||||||
|
}
|
||||||
|
if v, ok := data["secondary_cta_text"].(string); ok {
|
||||||
|
entityData.SecondaryCtaText = v
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err := s.Repo.Create(entityData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.Log.Error().Err(err).Msg("failed create about us content")
|
s.Log.Error().Err(err).Msg("failed create about us content")
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -66,8 +82,26 @@ func (s *aboutUsContentService) Save(data *entity.AboutUsContent) (*entity.About
|
||||||
}
|
}
|
||||||
|
|
||||||
// UPDATE
|
// UPDATE
|
||||||
func (s *aboutUsContentService) Update(id uint, data *entity.AboutUsContent) error {
|
func (s *aboutUsContentService) Update(id uint, data map[string]interface{}) error {
|
||||||
err := s.Repo.Update(id, data)
|
entityData := &entity.AboutUsContent{}
|
||||||
|
|
||||||
|
if v, ok := data["primary_title"].(string); ok {
|
||||||
|
entityData.PrimaryTitle = v
|
||||||
|
}
|
||||||
|
if v, ok := data["secondary_title"].(string); ok {
|
||||||
|
entityData.SecondaryTitle = v
|
||||||
|
}
|
||||||
|
if v, ok := data["description"].(string); ok {
|
||||||
|
entityData.Description = v
|
||||||
|
}
|
||||||
|
if v, ok := data["primary_cta"].(string); ok {
|
||||||
|
entityData.PrimaryCta = v
|
||||||
|
}
|
||||||
|
if v, ok := data["secondary_cta_text"].(string); ok {
|
||||||
|
entityData.SecondaryCtaText = v
|
||||||
|
}
|
||||||
|
|
||||||
|
err := s.Repo.Update(id, entityData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.Log.Error().Err(err).Msg("failed update about us content")
|
s.Log.Error().Err(err).Msg("failed update about us content")
|
||||||
return err
|
return err
|
||||||
|
|
@ -85,7 +119,6 @@ func (s *aboutUsContentService) Delete(id uint) error {
|
||||||
|
|
||||||
isActive := false
|
isActive := false
|
||||||
result.IsActive = &isActive
|
result.IsActive = &isActive
|
||||||
result.UpdatedAt = time.Now()
|
|
||||||
|
|
||||||
return s.Repo.Update(id, result)
|
return s.Repo.Update(id, result)
|
||||||
}
|
}
|
||||||
|
|
@ -1,30 +0,0 @@
|
||||||
package cms_media
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/gofiber/fiber/v2"
|
|
||||||
"go.uber.org/fx"
|
|
||||||
|
|
||||||
"web-qudo-be/app/module/cms_media/controller"
|
|
||||||
"web-qudo-be/app/module/cms_media/service"
|
|
||||||
)
|
|
||||||
|
|
||||||
type CmsMediaRouter struct {
|
|
||||||
App *fiber.App
|
|
||||||
Ctrl *controller.CmsMediaController
|
|
||||||
}
|
|
||||||
|
|
||||||
var NewCmsMediaModule = fx.Options(
|
|
||||||
fx.Provide(service.NewCmsMediaService),
|
|
||||||
fx.Provide(controller.NewCmsMediaController),
|
|
||||||
fx.Provide(NewCmsMediaRouter),
|
|
||||||
)
|
|
||||||
|
|
||||||
func NewCmsMediaRouter(app *fiber.App, ctrl *controller.CmsMediaController) *CmsMediaRouter {
|
|
||||||
return &CmsMediaRouter{App: app, Ctrl: ctrl}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *CmsMediaRouter) RegisterCmsMediaRoutes() {
|
|
||||||
r.App.Route("/cms-media", func(router fiber.Router) {
|
|
||||||
router.Get("/viewer/*", r.Ctrl.Viewer)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
package controller
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/gofiber/fiber/v2"
|
|
||||||
"github.com/rs/zerolog"
|
|
||||||
|
|
||||||
"web-qudo-be/app/module/cms_media/service"
|
|
||||||
)
|
|
||||||
|
|
||||||
type CmsMediaController struct {
|
|
||||||
svc *service.CmsMediaService
|
|
||||||
Log zerolog.Logger
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewCmsMediaController(svc *service.CmsMediaService, log zerolog.Logger) *CmsMediaController {
|
|
||||||
return &CmsMediaController{svc: svc, Log: log}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Viewer streams CMS media from MinIO via API URL (for img/video src).
|
|
||||||
// @Router /cms-media/viewer/{path} [get]
|
|
||||||
func (ctrl *CmsMediaController) Viewer(c *fiber.Ctx) error {
|
|
||||||
return ctrl.svc.Viewer(c)
|
|
||||||
}
|
|
||||||
|
|
@ -1,75 +0,0 @@
|
||||||
package service
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"io"
|
|
||||||
"mime"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/gofiber/fiber/v2"
|
|
||||||
"github.com/minio/minio-go/v7"
|
|
||||||
"github.com/rs/zerolog"
|
|
||||||
|
|
||||||
minioStorage "web-qudo-be/config/config"
|
|
||||||
)
|
|
||||||
|
|
||||||
type CmsMediaService struct {
|
|
||||||
Minio *minioStorage.MinioStorage
|
|
||||||
Log zerolog.Logger
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewCmsMediaService(minio *minioStorage.MinioStorage, log zerolog.Logger) *CmsMediaService {
|
|
||||||
return &CmsMediaService{Minio: minio, Log: log}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Viewer streams a CMS object from MinIO (same idea as article-files viewer).
|
|
||||||
func (s *CmsMediaService) Viewer(c *fiber.Ctx) error {
|
|
||||||
objectKey := strings.TrimSpace(c.Params("*"))
|
|
||||||
objectKey = strings.TrimPrefix(objectKey, "/")
|
|
||||||
if objectKey == "" {
|
|
||||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
|
|
||||||
"success": false,
|
|
||||||
"messages": []string{"object key required"},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
if !strings.HasPrefix(objectKey, "cms/") || strings.Contains(objectKey, "..") {
|
|
||||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
|
|
||||||
"success": false,
|
|
||||||
"messages": []string{"invalid object key"},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx := context.Background()
|
|
||||||
bucket := s.Minio.Cfg.ObjectStorage.MinioStorage.BucketName
|
|
||||||
|
|
||||||
client, err := s.Minio.ConnectMinio()
|
|
||||||
if err != nil {
|
|
||||||
s.Log.Error().Err(err).Msg("cms media viewer: minio connect")
|
|
||||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
|
||||||
"success": false,
|
|
||||||
"messages": []string{"storage unavailable"},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
obj, err := client.GetObject(ctx, bucket, objectKey, minio.GetObjectOptions{})
|
|
||||||
if err != nil {
|
|
||||||
s.Log.Error().Err(err).Str("key", objectKey).Msg("cms media viewer: get object")
|
|
||||||
return c.Status(fiber.StatusNotFound).SendString("not found")
|
|
||||||
}
|
|
||||||
defer obj.Close()
|
|
||||||
|
|
||||||
ext := strings.ToLower(filepath.Ext(objectKey))
|
|
||||||
contentType := mime.TypeByExtension(ext)
|
|
||||||
if contentType == "" {
|
|
||||||
contentType = "application/octet-stream"
|
|
||||||
}
|
|
||||||
c.Set("Content-Type", contentType)
|
|
||||||
c.Set("Cache-Control", "public, max-age=86400")
|
|
||||||
|
|
||||||
if _, err := io.Copy(c.Response().BodyWriter(), obj); err != nil {
|
|
||||||
s.Log.Error().Err(err).Msg("cms media viewer: stream")
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
package controller
|
package controller
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
|
|
@ -84,21 +82,6 @@ func (_i *heroContentImagesController) Update(c *fiber.Ctx) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if strings.HasPrefix(c.Get("Content-Type"), "multipart/form-data") {
|
|
||||||
file, err := c.FormFile("file")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := _i.service.UpdateWithFile(id, file); err != nil {
|
|
||||||
_i.Log.Error().Err(err).Msg("failed update hero content image (upload)")
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return utilRes.Resp(c, utilRes.Response{
|
|
||||||
Success: true,
|
|
||||||
Messages: utilRes.Messages{"Hero content image updated"},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
req := new(request.HeroContentImageUpdateRequest)
|
req := new(request.HeroContentImageUpdateRequest)
|
||||||
if err := utilVal.ParseAndValidate(c, req); err != nil {
|
if err := utilVal.ParseAndValidate(c, req); err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
||||||
|
|
@ -1,40 +1,31 @@
|
||||||
package service
|
package service
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"mime/multipart"
|
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
|
|
||||||
"web-qudo-be/app/database/entity"
|
"web-qudo-be/app/database/entity"
|
||||||
"web-qudo-be/app/module/hero_content_images/repository"
|
"web-qudo-be/app/module/hero_content_images/repository"
|
||||||
minioStorage "web-qudo-be/config/config"
|
|
||||||
"web-qudo-be/utils/storage"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type heroContentImagesService struct {
|
type heroContentImagesService struct {
|
||||||
Repo repository.HeroContentImagesRepository
|
Repo repository.HeroContentImagesRepository
|
||||||
MinioStorage *minioStorage.MinioStorage
|
|
||||||
Log zerolog.Logger
|
Log zerolog.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
type HeroContentImagesService interface {
|
type HeroContentImagesService interface {
|
||||||
FindByHeroID(heroID uuid.UUID) (*entity.HeroContentImages, error)
|
FindByHeroID(heroID uuid.UUID) (*entity.HeroContentImages, error)
|
||||||
Save(data *entity.HeroContentImages) (*entity.HeroContentImages, error)
|
Save(data *entity.HeroContentImages) (*entity.HeroContentImages, error)
|
||||||
SaveWithFile(heroContentID uuid.UUID, file *multipart.FileHeader) (*entity.HeroContentImages, error)
|
|
||||||
Update(id uuid.UUID, data *entity.HeroContentImages) error
|
Update(id uuid.UUID, data *entity.HeroContentImages) error
|
||||||
UpdateWithFile(id uuid.UUID, file *multipart.FileHeader) error
|
|
||||||
Delete(id uuid.UUID) error
|
Delete(id uuid.UUID) error
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHeroContentImagesService(
|
func NewHeroContentImagesService(
|
||||||
repo repository.HeroContentImagesRepository,
|
repo repository.HeroContentImagesRepository,
|
||||||
minio *minioStorage.MinioStorage,
|
|
||||||
log zerolog.Logger,
|
log zerolog.Logger,
|
||||||
) HeroContentImagesService {
|
) HeroContentImagesService {
|
||||||
return &heroContentImagesService{
|
return &heroContentImagesService{
|
||||||
Repo: repo,
|
Repo: repo,
|
||||||
MinioStorage: minio,
|
|
||||||
Log: log,
|
Log: log,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -61,19 +52,6 @@ func (s *heroContentImagesService) Save(data *entity.HeroContentImages) (*entity
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *heroContentImagesService) SaveWithFile(heroContentID uuid.UUID, file *multipart.FileHeader) (*entity.HeroContentImages, error) {
|
|
||||||
key, url, err := storage.UploadCMSObject(s.MinioStorage, "hero", file, false)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
data := &entity.HeroContentImages{
|
|
||||||
HeroContentID: heroContentID,
|
|
||||||
ImagePath: key,
|
|
||||||
ImageURL: url,
|
|
||||||
}
|
|
||||||
return s.Save(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *heroContentImagesService) Update(id uuid.UUID, data *entity.HeroContentImages) error {
|
func (s *heroContentImagesService) Update(id uuid.UUID, data *entity.HeroContentImages) error {
|
||||||
err := s.Repo.Update(id, data)
|
err := s.Repo.Update(id, data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -84,17 +62,6 @@ func (s *heroContentImagesService) Update(id uuid.UUID, data *entity.HeroContent
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *heroContentImagesService) UpdateWithFile(id uuid.UUID, file *multipart.FileHeader) error {
|
|
||||||
key, url, err := storage.UploadCMSObject(s.MinioStorage, "hero", file, false)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return s.Repo.Update(id, &entity.HeroContentImages{
|
|
||||||
ImagePath: key,
|
|
||||||
ImageURL: url,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *heroContentImagesService) Delete(id uuid.UUID) error {
|
func (s *heroContentImagesService) Delete(id uuid.UUID) error {
|
||||||
err := s.Repo.Delete(id)
|
err := s.Repo.Delete(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,11 @@
|
||||||
package repository
|
package repository
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"web-qudo-be/app/database"
|
"web-qudo-be/app/database"
|
||||||
"web-qudo-be/app/database/entity"
|
"web-qudo-be/app/database/entity"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
"gorm.io/gorm"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type heroContentsRepository struct {
|
type heroContentsRepository struct {
|
||||||
|
|
@ -37,9 +35,6 @@ func (r *heroContentsRepository) Get() (*entity.HeroContents, error) {
|
||||||
First(&data).Error
|
First(&data).Error
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
r.Log.Error().Err(err).Msg("failed get hero content")
|
r.Log.Error().Err(err).Msg("failed get hero content")
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
package controller
|
package controller
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
|
|
@ -34,7 +32,7 @@ func NewOurProductContentImagesController(service service.OurProductContentImage
|
||||||
}
|
}
|
||||||
|
|
||||||
func (_i *ourProductContentImagesController) FindByOurProductContentID(c *fiber.Ctx) error {
|
func (_i *ourProductContentImagesController) FindByOurProductContentID(c *fiber.Ctx) error {
|
||||||
contentIDStr := c.Params("content_id")
|
contentIDStr := c.Params("our_product_content_id")
|
||||||
|
|
||||||
contentID, err := uuid.Parse(contentIDStr)
|
contentID, err := uuid.Parse(contentIDStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -55,28 +53,6 @@ func (_i *ourProductContentImagesController) FindByOurProductContentID(c *fiber.
|
||||||
}
|
}
|
||||||
|
|
||||||
func (_i *ourProductContentImagesController) Save(c *fiber.Ctx) error {
|
func (_i *ourProductContentImagesController) Save(c *fiber.Ctx) error {
|
||||||
if strings.HasPrefix(c.Get("Content-Type"), "multipart/form-data") {
|
|
||||||
cidStr := c.FormValue("our_product_content_id")
|
|
||||||
cid, err := uuid.Parse(cidStr)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
file, err := c.FormFile("file")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
result, err := _i.service.SaveWithFile(cid, file)
|
|
||||||
if err != nil {
|
|
||||||
_i.Log.Error().Err(err).Msg("failed create our product content image (upload)")
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return utilRes.Resp(c, utilRes.Response{
|
|
||||||
Success: true,
|
|
||||||
Messages: utilRes.Messages{"Our product content image created"},
|
|
||||||
Data: result,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
req := new(request.OurProductContentImageCreateRequest)
|
req := new(request.OurProductContentImageCreateRequest)
|
||||||
|
|
||||||
if err := utilVal.ParseAndValidate(c, req); err != nil {
|
if err := utilVal.ParseAndValidate(c, req); err != nil {
|
||||||
|
|
@ -106,21 +82,6 @@ func (_i *ourProductContentImagesController) Update(c *fiber.Ctx) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if strings.HasPrefix(c.Get("Content-Type"), "multipart/form-data") {
|
|
||||||
file, err := c.FormFile("file")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := _i.service.UpdateWithFile(id, file); err != nil {
|
|
||||||
_i.Log.Error().Err(err).Msg("failed update our product content image (upload)")
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return utilRes.Resp(c, utilRes.Response{
|
|
||||||
Success: true,
|
|
||||||
Messages: utilRes.Messages{"Our product content image updated"},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
req := new(request.OurProductContentImageUpdateRequest)
|
req := new(request.OurProductContentImageUpdateRequest)
|
||||||
if err := utilVal.ParseAndValidate(c, req); err != nil {
|
if err := utilVal.ParseAndValidate(c, req); err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
||||||
|
|
@ -1,40 +1,31 @@
|
||||||
package service
|
package service
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"mime/multipart"
|
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
|
|
||||||
"web-qudo-be/app/database/entity"
|
"web-qudo-be/app/database/entity"
|
||||||
"web-qudo-be/app/module/our_product_content_images/repository"
|
"web-qudo-be/app/module/our_product_content_images/repository"
|
||||||
minioStorage "web-qudo-be/config/config"
|
|
||||||
"web-qudo-be/utils/storage"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type ourProductContentImagesService struct {
|
type ourProductContentImagesService struct {
|
||||||
Repo repository.OurProductContentImagesRepository
|
Repo repository.OurProductContentImagesRepository
|
||||||
MinioStorage *minioStorage.MinioStorage
|
|
||||||
Log zerolog.Logger
|
Log zerolog.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
type OurProductContentImagesService interface {
|
type OurProductContentImagesService interface {
|
||||||
FindByContentID(contentID uuid.UUID) ([]entity.OurProductContentImage, error)
|
FindByContentID(contentID uuid.UUID) ([]entity.OurProductContentImage, error)
|
||||||
Save(data *entity.OurProductContentImage) (*entity.OurProductContentImage, error)
|
Save(data *entity.OurProductContentImage) (*entity.OurProductContentImage, error)
|
||||||
SaveWithFile(ourProductContentID uuid.UUID, file *multipart.FileHeader) (*entity.OurProductContentImage, error)
|
|
||||||
Update(id uuid.UUID, data *entity.OurProductContentImage) error
|
Update(id uuid.UUID, data *entity.OurProductContentImage) error
|
||||||
UpdateWithFile(id uuid.UUID, file *multipart.FileHeader) error
|
|
||||||
Delete(id uuid.UUID) error
|
Delete(id uuid.UUID) error
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewOurProductContentImagesService(
|
func NewOurProductContentImagesService(
|
||||||
repo repository.OurProductContentImagesRepository,
|
repo repository.OurProductContentImagesRepository,
|
||||||
minio *minioStorage.MinioStorage,
|
|
||||||
log zerolog.Logger,
|
log zerolog.Logger,
|
||||||
) OurProductContentImagesService {
|
) OurProductContentImagesService {
|
||||||
return &ourProductContentImagesService{
|
return &ourProductContentImagesService{
|
||||||
Repo: repo,
|
Repo: repo,
|
||||||
MinioStorage: minio,
|
|
||||||
Log: log,
|
Log: log,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -61,19 +52,6 @@ func (s *ourProductContentImagesService) Save(data *entity.OurProductContentImag
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ourProductContentImagesService) SaveWithFile(ourProductContentID uuid.UUID, file *multipart.FileHeader) (*entity.OurProductContentImage, error) {
|
|
||||||
key, url, err := storage.UploadCMSObject(s.MinioStorage, "our-products", file, false)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
data := &entity.OurProductContentImage{
|
|
||||||
OurProductContentID: ourProductContentID,
|
|
||||||
ImagePath: key,
|
|
||||||
ImageURL: url,
|
|
||||||
}
|
|
||||||
return s.Save(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ourProductContentImagesService) Update(id uuid.UUID, data *entity.OurProductContentImage) error {
|
func (s *ourProductContentImagesService) Update(id uuid.UUID, data *entity.OurProductContentImage) error {
|
||||||
err := s.Repo.Update(id, data)
|
err := s.Repo.Update(id, data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -84,17 +62,6 @@ func (s *ourProductContentImagesService) Update(id uuid.UUID, data *entity.OurPr
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ourProductContentImagesService) UpdateWithFile(id uuid.UUID, file *multipart.FileHeader) error {
|
|
||||||
key, url, err := storage.UploadCMSObject(s.MinioStorage, "our-products", file, false)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return s.Repo.Update(id, &entity.OurProductContentImage{
|
|
||||||
ImagePath: key,
|
|
||||||
ImageURL: url,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ourProductContentImagesService) Delete(id uuid.UUID) error {
|
func (s *ourProductContentImagesService) Delete(id uuid.UUID) error {
|
||||||
err := s.Repo.Delete(id)
|
err := s.Repo.Delete(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,11 @@
|
||||||
package repository
|
package repository
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"web-qudo-be/app/database"
|
"web-qudo-be/app/database"
|
||||||
"web-qudo-be/app/database/entity"
|
"web-qudo-be/app/database/entity"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
"gorm.io/gorm"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type ourProductContentRepository struct {
|
type ourProductContentRepository struct {
|
||||||
|
|
@ -17,7 +15,6 @@ type ourProductContentRepository struct {
|
||||||
|
|
||||||
type OurProductContentRepository interface {
|
type OurProductContentRepository interface {
|
||||||
Get() (*entity.OurProductContent, error)
|
Get() (*entity.OurProductContent, error)
|
||||||
GetAll() ([]entity.OurProductContent, error)
|
|
||||||
Create(data *entity.OurProductContent) (*entity.OurProductContent, error)
|
Create(data *entity.OurProductContent) (*entity.OurProductContent, error)
|
||||||
Update(id uuid.UUID, data *entity.OurProductContent) error
|
Update(id uuid.UUID, data *entity.OurProductContent) error
|
||||||
Delete(id uuid.UUID) error
|
Delete(id uuid.UUID) error
|
||||||
|
|
@ -38,9 +35,6 @@ func (r *ourProductContentRepository) Get() (*entity.OurProductContent, error) {
|
||||||
First(&data).Error
|
First(&data).Error
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
r.Log.Error().Err(err).Msg("failed get our product content")
|
r.Log.Error().Err(err).Msg("failed get our product content")
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -48,19 +42,6 @@ func (r *ourProductContentRepository) Get() (*entity.OurProductContent, error) {
|
||||||
return &data, nil
|
return &data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ourProductContentRepository) GetAll() ([]entity.OurProductContent, error) {
|
|
||||||
var rows []entity.OurProductContent
|
|
||||||
err := r.DB.DB.
|
|
||||||
Preload("Images").
|
|
||||||
Order("created_at ASC").
|
|
||||||
Find(&rows).Error
|
|
||||||
if err != nil {
|
|
||||||
r.Log.Error().Err(err).Msg("failed list our product contents")
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return rows, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *ourProductContentRepository) Create(data *entity.OurProductContent) (*entity.OurProductContent, error) {
|
func (r *ourProductContentRepository) Create(data *entity.OurProductContent) (*entity.OurProductContent, error) {
|
||||||
data.ID = uuid.New()
|
data.ID = uuid.New()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ type ourProductContentService struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type OurProductContentService interface {
|
type OurProductContentService interface {
|
||||||
Show() ([]entity.OurProductContent, error)
|
Show() (*entity.OurProductContent, error)
|
||||||
Save(data *entity.OurProductContent) (*entity.OurProductContent, error)
|
Save(data *entity.OurProductContent) (*entity.OurProductContent, error)
|
||||||
Update(id uuid.UUID, data *entity.OurProductContent) error
|
Update(id uuid.UUID, data *entity.OurProductContent) error
|
||||||
Delete(id uuid.UUID) error
|
Delete(id uuid.UUID) error
|
||||||
|
|
@ -34,13 +34,14 @@ func NewOurProductContentService(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ourProductContentService) Show() ([]entity.OurProductContent, error) {
|
func (s *ourProductContentService) Show() (*entity.OurProductContent, error) {
|
||||||
rows, err := s.Repo.GetAll()
|
data, err := s.Repo.Get()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.Log.Error().Err(err).Msg("failed list our product contents")
|
s.Log.Error().Err(err).Msg("failed get our product content")
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return rows, nil
|
|
||||||
|
return data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ourProductContentService) Save(data *entity.OurProductContent) (*entity.OurProductContent, error) {
|
func (s *ourProductContentService) Save(data *entity.OurProductContent) (*entity.OurProductContent, error) {
|
||||||
|
|
@ -66,5 +67,13 @@ func (s *ourProductContentService) Update(id uuid.UUID, data *entity.OurProductC
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ourProductContentService) Delete(id uuid.UUID) error {
|
func (s *ourProductContentService) Delete(id uuid.UUID) error {
|
||||||
return s.Repo.Delete(id)
|
result, err := s.Repo.Get()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
isActive := false
|
||||||
|
result.IsActive = &isActive
|
||||||
|
|
||||||
|
return s.Repo.Update(id, result)
|
||||||
}
|
}
|
||||||
|
|
@ -2,7 +2,6 @@ package controller
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
|
|
@ -57,29 +56,6 @@ func (_i *ourServiceContentImagesController) FindByOurServiceContentID(c *fiber.
|
||||||
}
|
}
|
||||||
|
|
||||||
func (_i *ourServiceContentImagesController) Save(c *fiber.Ctx) error {
|
func (_i *ourServiceContentImagesController) Save(c *fiber.Ctx) error {
|
||||||
if strings.HasPrefix(c.Get("Content-Type"), "multipart/form-data") {
|
|
||||||
cidStr := c.FormValue("our_service_content_id")
|
|
||||||
cidInt, err := strconv.Atoi(cidStr)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
cid := uint(cidInt)
|
|
||||||
file, err := c.FormFile("file")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
result, err := _i.service.SaveWithFile(cid, file)
|
|
||||||
if err != nil {
|
|
||||||
_i.Log.Error().Err(err).Msg("failed create our service content image (upload)")
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return utilRes.Resp(c, utilRes.Response{
|
|
||||||
Success: true,
|
|
||||||
Messages: utilRes.Messages{"Our service content image created"},
|
|
||||||
Data: result,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
req := new(request.OurServiceContentImageCreateRequest)
|
req := new(request.OurServiceContentImageCreateRequest)
|
||||||
|
|
||||||
if err := utilVal.ParseAndValidate(c, req); err != nil {
|
if err := utilVal.ParseAndValidate(c, req); err != nil {
|
||||||
|
|
@ -111,21 +87,6 @@ func (_i *ourServiceContentImagesController) Update(c *fiber.Ctx) error {
|
||||||
|
|
||||||
id := uint(idInt)
|
id := uint(idInt)
|
||||||
|
|
||||||
if strings.HasPrefix(c.Get("Content-Type"), "multipart/form-data") {
|
|
||||||
file, err := c.FormFile("file")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := _i.service.UpdateWithFile(id, file); err != nil {
|
|
||||||
_i.Log.Error().Err(err).Msg("failed update our service content image (upload)")
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return utilRes.Resp(c, utilRes.Response{
|
|
||||||
Success: true,
|
|
||||||
Messages: utilRes.Messages{"Our service content image updated"},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
req := new(request.OurServiceContentImageUpdateRequest)
|
req := new(request.OurServiceContentImageUpdateRequest)
|
||||||
if err := utilVal.ParseAndValidate(c, req); err != nil {
|
if err := utilVal.ParseAndValidate(c, req); err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
||||||
|
|
@ -1,39 +1,30 @@
|
||||||
package service
|
package service
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"mime/multipart"
|
|
||||||
|
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
|
|
||||||
"web-qudo-be/app/database/entity"
|
"web-qudo-be/app/database/entity"
|
||||||
"web-qudo-be/app/module/our_service_content_images/repository"
|
"web-qudo-be/app/module/our_service_content_images/repository"
|
||||||
minioStorage "web-qudo-be/config/config"
|
|
||||||
"web-qudo-be/utils/storage"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type ourServiceContentImagesService struct {
|
type ourServiceContentImagesService struct {
|
||||||
Repo repository.OurServiceContentImagesRepository
|
Repo repository.OurServiceContentImagesRepository
|
||||||
MinioStorage *minioStorage.MinioStorage
|
|
||||||
Log zerolog.Logger
|
Log zerolog.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
type OurServiceContentImagesService interface {
|
type OurServiceContentImagesService interface {
|
||||||
FindByContentID(contentID uint) ([]entity.OurServiceContentImage, error)
|
FindByContentID(contentID uint) ([]entity.OurServiceContentImage, error)
|
||||||
Save(data *entity.OurServiceContentImage) (*entity.OurServiceContentImage, error)
|
Save(data *entity.OurServiceContentImage) (*entity.OurServiceContentImage, error)
|
||||||
SaveWithFile(ourServiceContentID uint, file *multipart.FileHeader) (*entity.OurServiceContentImage, error)
|
|
||||||
Update(id uint, data *entity.OurServiceContentImage) error
|
Update(id uint, data *entity.OurServiceContentImage) error
|
||||||
UpdateWithFile(id uint, file *multipart.FileHeader) error
|
|
||||||
Delete(id uint) error
|
Delete(id uint) error
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewOurServiceContentImagesService(
|
func NewOurServiceContentImagesService(
|
||||||
repo repository.OurServiceContentImagesRepository,
|
repo repository.OurServiceContentImagesRepository,
|
||||||
minio *minioStorage.MinioStorage,
|
|
||||||
log zerolog.Logger,
|
log zerolog.Logger,
|
||||||
) OurServiceContentImagesService {
|
) OurServiceContentImagesService {
|
||||||
return &ourServiceContentImagesService{
|
return &ourServiceContentImagesService{
|
||||||
Repo: repo,
|
Repo: repo,
|
||||||
MinioStorage: minio,
|
|
||||||
Log: log,
|
Log: log,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -58,19 +49,6 @@ func (s *ourServiceContentImagesService) Save(data *entity.OurServiceContentImag
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ourServiceContentImagesService) SaveWithFile(ourServiceContentID uint, file *multipart.FileHeader) (*entity.OurServiceContentImage, error) {
|
|
||||||
key, url, err := storage.UploadCMSObject(s.MinioStorage, "our-services", file, false)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
data := &entity.OurServiceContentImage{
|
|
||||||
OurServiceContentID: ourServiceContentID,
|
|
||||||
ImagePath: key,
|
|
||||||
ImageURL: url,
|
|
||||||
}
|
|
||||||
return s.Save(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ourServiceContentImagesService) Update(id uint, data *entity.OurServiceContentImage) error {
|
func (s *ourServiceContentImagesService) Update(id uint, data *entity.OurServiceContentImage) error {
|
||||||
err := s.Repo.Update(id, data)
|
err := s.Repo.Update(id, data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -81,17 +59,6 @@ func (s *ourServiceContentImagesService) Update(id uint, data *entity.OurService
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ourServiceContentImagesService) UpdateWithFile(id uint, file *multipart.FileHeader) error {
|
|
||||||
key, url, err := storage.UploadCMSObject(s.MinioStorage, "our-services", file, false)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return s.Repo.Update(id, &entity.OurServiceContentImage{
|
|
||||||
ImagePath: key,
|
|
||||||
ImageURL: url,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ourServiceContentImagesService) Delete(id uint) error {
|
func (s *ourServiceContentImagesService) Delete(id uint) error {
|
||||||
err := s.Repo.Delete(id)
|
err := s.Repo.Delete(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,10 @@
|
||||||
package repository
|
package repository
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"web-qudo-be/app/database"
|
"web-qudo-be/app/database"
|
||||||
"web-qudo-be/app/database/entity"
|
"web-qudo-be/app/database/entity"
|
||||||
|
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
"gorm.io/gorm"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type ourServiceContentRepository struct {
|
type ourServiceContentRepository struct {
|
||||||
|
|
@ -16,7 +14,6 @@ type ourServiceContentRepository struct {
|
||||||
|
|
||||||
type OurServiceContentRepository interface {
|
type OurServiceContentRepository interface {
|
||||||
Get() (*entity.OurServiceContent, error)
|
Get() (*entity.OurServiceContent, error)
|
||||||
GetAll() ([]entity.OurServiceContent, error)
|
|
||||||
Create(data *entity.OurServiceContent) (*entity.OurServiceContent, error)
|
Create(data *entity.OurServiceContent) (*entity.OurServiceContent, error)
|
||||||
Update(id uint, data *entity.OurServiceContent) error
|
Update(id uint, data *entity.OurServiceContent) error
|
||||||
Delete(id uint) error
|
Delete(id uint) error
|
||||||
|
|
@ -37,9 +34,6 @@ func (r *ourServiceContentRepository) Get() (*entity.OurServiceContent, error) {
|
||||||
First(&data).Error
|
First(&data).Error
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
r.Log.Error().Err(err).Msg("failed get our service content")
|
r.Log.Error().Err(err).Msg("failed get our service content")
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -47,19 +41,6 @@ func (r *ourServiceContentRepository) Get() (*entity.OurServiceContent, error) {
|
||||||
return &data, nil
|
return &data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ourServiceContentRepository) GetAll() ([]entity.OurServiceContent, error) {
|
|
||||||
var rows []entity.OurServiceContent
|
|
||||||
err := r.DB.DB.
|
|
||||||
Preload("Images").
|
|
||||||
Order("created_at ASC").
|
|
||||||
Find(&rows).Error
|
|
||||||
if err != nil {
|
|
||||||
r.Log.Error().Err(err).Msg("failed list our service contents")
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return rows, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *ourServiceContentRepository) Create(data *entity.OurServiceContent) (*entity.OurServiceContent, error) {
|
func (r *ourServiceContentRepository) Create(data *entity.OurServiceContent) (*entity.OurServiceContent, error) {
|
||||||
err := r.DB.DB.Create(data).Error
|
err := r.DB.DB.Create(data).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ type ourServiceContentService struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type OurServiceContentService interface {
|
type OurServiceContentService interface {
|
||||||
Show() ([]entity.OurServiceContent, error)
|
Show() (*entity.OurServiceContent, error)
|
||||||
Save(data *entity.OurServiceContent) (*entity.OurServiceContent, error)
|
Save(data *entity.OurServiceContent) (*entity.OurServiceContent, error)
|
||||||
Update(id uint, data *entity.OurServiceContent) error
|
Update(id uint, data *entity.OurServiceContent) error
|
||||||
Delete(id uint) error
|
Delete(id uint) error
|
||||||
|
|
@ -33,13 +33,14 @@ func NewOurServiceContentService(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ourServiceContentService) Show() ([]entity.OurServiceContent, error) {
|
func (s *ourServiceContentService) Show() (*entity.OurServiceContent, error) {
|
||||||
rows, err := s.Repo.GetAll()
|
data, err := s.Repo.Get()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.Log.Error().Err(err).Msg("failed list our service contents")
|
s.Log.Error().Err(err).Msg("failed get our service content")
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return rows, nil
|
|
||||||
|
return data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ourServiceContentService) Save(data *entity.OurServiceContent) (*entity.OurServiceContent, error) {
|
func (s *ourServiceContentService) Save(data *entity.OurServiceContent) (*entity.OurServiceContent, error) {
|
||||||
|
|
@ -74,5 +75,13 @@ func (s *ourServiceContentService) Update(id uint, data *entity.OurServiceConten
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ourServiceContentService) Delete(id uint) error {
|
func (s *ourServiceContentService) Delete(id uint) error {
|
||||||
return s.Repo.Delete(id)
|
result, err := s.Repo.Get()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
isActive := false
|
||||||
|
result.IsActive = &isActive
|
||||||
|
|
||||||
|
return s.Repo.Update(id, result)
|
||||||
}
|
}
|
||||||
|
|
@ -21,7 +21,6 @@ type PartnerContentController interface {
|
||||||
Show(c *fiber.Ctx) error
|
Show(c *fiber.Ctx) error
|
||||||
Save(c *fiber.Ctx) error
|
Save(c *fiber.Ctx) error
|
||||||
Update(c *fiber.Ctx) error
|
Update(c *fiber.Ctx) error
|
||||||
UploadLogo(c *fiber.Ctx) error
|
|
||||||
Delete(c *fiber.Ctx) error
|
Delete(c *fiber.Ctx) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -95,26 +94,6 @@ func (_i *partnerContentController) Update(c *fiber.Ctx) error {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (_i *partnerContentController) UploadLogo(c *fiber.Ctx) error {
|
|
||||||
idStr := c.Params("id")
|
|
||||||
id, err := uuid.Parse(idStr)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
file, err := c.FormFile("file")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := _i.service.UploadLogo(id, file); err != nil {
|
|
||||||
_i.Log.Error().Err(err).Msg("failed upload partner logo")
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return utilRes.Resp(c, utilRes.Response{
|
|
||||||
Success: true,
|
|
||||||
Messages: utilRes.Messages{"Partner logo uploaded"},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (_i *partnerContentController) Delete(c *fiber.Ctx) error {
|
func (_i *partnerContentController) Delete(c *fiber.Ctx) error {
|
||||||
idStr := c.Params("id")
|
idStr := c.Params("id")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,6 @@ func (_i *PartnerContentsRouter) RegisterPartnerContentsRoutes() {
|
||||||
_i.App.Route("/partner-contents", func(router fiber.Router) {
|
_i.App.Route("/partner-contents", func(router fiber.Router) {
|
||||||
router.Get("/", partnerController.Show)
|
router.Get("/", partnerController.Show)
|
||||||
router.Post("/", partnerController.Save)
|
router.Post("/", partnerController.Save)
|
||||||
router.Post("/:id/logo", partnerController.UploadLogo)
|
|
||||||
router.Put("/:id", partnerController.Update)
|
router.Put("/:id", partnerController.Update)
|
||||||
router.Delete("/:id", partnerController.Delete)
|
router.Delete("/:id", partnerController.Delete)
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,6 @@ type PartnerContentRepository interface {
|
||||||
Get() ([]entity.PartnerContent, error)
|
Get() ([]entity.PartnerContent, error)
|
||||||
Create(data *entity.PartnerContent) (*entity.PartnerContent, error)
|
Create(data *entity.PartnerContent) (*entity.PartnerContent, error)
|
||||||
Update(id uuid.UUID, data *entity.PartnerContent) error
|
Update(id uuid.UUID, data *entity.PartnerContent) error
|
||||||
UpdateImageFields(id uuid.UUID, imagePath, imageURL string) error
|
|
||||||
Delete(id uuid.UUID) error
|
Delete(id uuid.UUID) error
|
||||||
FindByID(id uuid.UUID) (*entity.PartnerContent, error) // opsional (buat soft delete)
|
FindByID(id uuid.UUID) (*entity.PartnerContent, error) // opsional (buat soft delete)
|
||||||
}
|
}
|
||||||
|
|
@ -69,21 +68,6 @@ func (r *partnerContentRepository) Update(id uuid.UUID, data *entity.PartnerCont
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *partnerContentRepository) UpdateImageFields(id uuid.UUID, imagePath, imageURL string) error {
|
|
||||||
err := r.DB.DB.
|
|
||||||
Model(&entity.PartnerContent{}).
|
|
||||||
Where("id = ?", id).
|
|
||||||
Updates(map[string]interface{}{
|
|
||||||
"image_path": imagePath,
|
|
||||||
"image_url": imageURL,
|
|
||||||
}).Error
|
|
||||||
if err != nil {
|
|
||||||
r.Log.Error().Err(err).Msg("failed update partner logo")
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *partnerContentRepository) Delete(id uuid.UUID) error {
|
func (r *partnerContentRepository) Delete(id uuid.UUID) error {
|
||||||
err := r.DB.DB.Delete(&entity.PartnerContent{}, id).Error
|
err := r.DB.DB.Delete(&entity.PartnerContent{}, id).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,15 @@
|
||||||
package service
|
package service
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"mime/multipart"
|
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
|
|
||||||
"web-qudo-be/app/database/entity"
|
"web-qudo-be/app/database/entity"
|
||||||
"web-qudo-be/app/module/partner_contents/repository"
|
"web-qudo-be/app/module/partner_contents/repository"
|
||||||
minioStorage "web-qudo-be/config/config"
|
|
||||||
"web-qudo-be/utils/storage"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type partnerContentService struct {
|
type partnerContentService struct {
|
||||||
Repo repository.PartnerContentRepository
|
Repo repository.PartnerContentRepository
|
||||||
MinioStorage *minioStorage.MinioStorage
|
|
||||||
Log zerolog.Logger
|
Log zerolog.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -22,18 +17,15 @@ type PartnerContentService interface {
|
||||||
Show() ([]entity.PartnerContent, error)
|
Show() ([]entity.PartnerContent, error)
|
||||||
Save(data *entity.PartnerContent) (*entity.PartnerContent, error)
|
Save(data *entity.PartnerContent) (*entity.PartnerContent, error)
|
||||||
Update(id uuid.UUID, data *entity.PartnerContent) error
|
Update(id uuid.UUID, data *entity.PartnerContent) error
|
||||||
UploadLogo(id uuid.UUID, file *multipart.FileHeader) error
|
|
||||||
Delete(id uuid.UUID) error
|
Delete(id uuid.UUID) error
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewPartnerContentService(
|
func NewPartnerContentService(
|
||||||
repo repository.PartnerContentRepository,
|
repo repository.PartnerContentRepository,
|
||||||
minio *minioStorage.MinioStorage,
|
|
||||||
log zerolog.Logger,
|
log zerolog.Logger,
|
||||||
) PartnerContentService {
|
) PartnerContentService {
|
||||||
return &partnerContentService{
|
return &partnerContentService{
|
||||||
Repo: repo,
|
Repo: repo,
|
||||||
MinioStorage: minio,
|
|
||||||
Log: log,
|
Log: log,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -70,14 +62,6 @@ func (s *partnerContentService) Update(id uuid.UUID, data *entity.PartnerContent
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *partnerContentService) UploadLogo(id uuid.UUID, file *multipart.FileHeader) error {
|
|
||||||
key, url, err := storage.UploadCMSObject(s.MinioStorage, "partners", file, false)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return s.Repo.UpdateImageFields(id, key, url)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *partnerContentService) Delete(id uuid.UUID) error {
|
func (s *partnerContentService) Delete(id uuid.UUID) error {
|
||||||
err := s.Repo.Delete(id)
|
err := s.Repo.Delete(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ package controller
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
|
|
||||||
|
|
@ -40,32 +39,6 @@ func NewPopupNewsContentImagesController(s service.PopupNewsContentImagesService
|
||||||
// @Failure 500 {object} response.Response
|
// @Failure 500 {object} response.Response
|
||||||
// @Router /popup-news-content-images [post]
|
// @Router /popup-news-content-images [post]
|
||||||
func (_i *popupNewsContentImagesController) Save(c *fiber.Ctx) error {
|
func (_i *popupNewsContentImagesController) Save(c *fiber.Ctx) error {
|
||||||
if strings.HasPrefix(c.Get("Content-Type"), "multipart/form-data") {
|
|
||||||
cidStr := c.FormValue("popup_news_content_id")
|
|
||||||
cid64, err := strconv.ParseUint(cidStr, 10, 32)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
file, err := c.FormFile("file")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
var isThumb *bool
|
|
||||||
if v := strings.TrimSpace(c.FormValue("is_thumbnail")); v != "" {
|
|
||||||
b := v == "true" || v == "1" || v == "on"
|
|
||||||
isThumb = &b
|
|
||||||
}
|
|
||||||
result, err := _i.service.SaveWithFile(uint(cid64), file, isThumb)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return utilRes.Resp(c, utilRes.Response{
|
|
||||||
Success: true,
|
|
||||||
Messages: utilRes.Messages{"Popup news content image successfully uploaded"},
|
|
||||||
Data: result,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
req := new(request.PopupNewsContentImagesCreateRequest)
|
req := new(request.PopupNewsContentImagesCreateRequest)
|
||||||
if err := utilVal.ParseAndValidate(c, req); err != nil {
|
if err := utilVal.ParseAndValidate(c, req); err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
@ -77,7 +50,6 @@ func (_i *popupNewsContentImagesController) Save(c *fiber.Ctx) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
return utilRes.Resp(c, utilRes.Response{
|
return utilRes.Resp(c, utilRes.Response{
|
||||||
Success: true,
|
|
||||||
Messages: utilRes.Messages{"Popup news content image successfully uploaded"},
|
Messages: utilRes.Messages{"Popup news content image successfully uploaded"},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,76 +1,40 @@
|
||||||
package service
|
package service
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"mime/multipart"
|
|
||||||
|
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
|
|
||||||
"web-qudo-be/app/database/entity"
|
|
||||||
"web-qudo-be/app/module/popup_news_content_images/repository"
|
"web-qudo-be/app/module/popup_news_content_images/repository"
|
||||||
"web-qudo-be/app/module/popup_news_content_images/request"
|
"web-qudo-be/app/module/popup_news_content_images/request"
|
||||||
minioStorage "web-qudo-be/config/config"
|
|
||||||
"web-qudo-be/utils/storage"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// service struct
|
||||||
type popupNewsContentImagesService struct {
|
type popupNewsContentImagesService struct {
|
||||||
Repo repository.PopupNewsContentImagesRepository
|
Repo repository.PopupNewsContentImagesRepository
|
||||||
MinioStorage *minioStorage.MinioStorage
|
|
||||||
Log zerolog.Logger
|
Log zerolog.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// interface
|
||||||
type PopupNewsContentImagesService interface {
|
type PopupNewsContentImagesService interface {
|
||||||
Save(req request.PopupNewsContentImagesCreateRequest) error
|
Save(req request.PopupNewsContentImagesCreateRequest) error
|
||||||
SaveWithFile(popupNewsContentID uint, file *multipart.FileHeader, isThumbnail *bool) (*entity.PopupNewsContentImages, error)
|
|
||||||
Delete(id uint) error
|
Delete(id uint) error
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewPopupNewsContentImagesService(
|
// constructor
|
||||||
repo repository.PopupNewsContentImagesRepository,
|
func NewPopupNewsContentImagesService(repo repository.PopupNewsContentImagesRepository, log zerolog.Logger) PopupNewsContentImagesService {
|
||||||
minio *minioStorage.MinioStorage,
|
|
||||||
log zerolog.Logger,
|
|
||||||
) PopupNewsContentImagesService {
|
|
||||||
return &popupNewsContentImagesService{
|
return &popupNewsContentImagesService{
|
||||||
Repo: repo,
|
Repo: repo,
|
||||||
MinioStorage: minio,
|
|
||||||
Log: log,
|
Log: log,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Save
|
||||||
func (_i *popupNewsContentImagesService) Save(req request.PopupNewsContentImagesCreateRequest) error {
|
func (_i *popupNewsContentImagesService) Save(req request.PopupNewsContentImagesCreateRequest) error {
|
||||||
_i.Log.Info().Interface("data", req).Msg("create popup news content image (json)")
|
_i.Log.Info().Interface("data", req).Msg("upload popup news content image")
|
||||||
|
|
||||||
return _i.Repo.Create(req.ToEntity())
|
return _i.Repo.Create(req.ToEntity())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (_i *popupNewsContentImagesService) SaveWithFile(popupNewsContentID uint, file *multipart.FileHeader, isThumbnail *bool) (*entity.PopupNewsContentImages, error) {
|
// Delete
|
||||||
_i.Log.Info().
|
|
||||||
Uint("popup_news_content_id", popupNewsContentID).
|
|
||||||
Str("filename", file.Filename).
|
|
||||||
Msg("upload popup news content image")
|
|
||||||
|
|
||||||
key, url, err := storage.UploadCMSObject(_i.MinioStorage, "popup-news", file, false)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if isThumbnail != nil && *isThumbnail {
|
|
||||||
if err := _i.Repo.ResetThumbnail(popupNewsContentID); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
row := &entity.PopupNewsContentImages{
|
|
||||||
PopupNewsContentID: popupNewsContentID,
|
|
||||||
MediaPath: key,
|
|
||||||
MediaURL: url,
|
|
||||||
IsThumbnail: isThumbnail,
|
|
||||||
}
|
|
||||||
if err := _i.Repo.Create(row); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return row, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (_i *popupNewsContentImagesService) Delete(id uint) error {
|
func (_i *popupNewsContentImagesService) Delete(id uint) error {
|
||||||
return _i.Repo.Delete(id)
|
return _i.Repo.Delete(id)
|
||||||
}
|
}
|
||||||
|
|
@ -110,14 +110,13 @@ func (_i *popupNewsContentsController) Save(c *fiber.Ctx) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
data, err := _i.service.Save(*req)
|
err := _i.service.Save(*req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return utilRes.Resp(c, utilRes.Response{
|
return utilRes.Resp(c, utilRes.Response{
|
||||||
Messages: utilRes.Messages{"Popup news content successfully created"},
|
Messages: utilRes.Messages{"Popup news content successfully created"},
|
||||||
Data: data,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ type popupNewsContentsService struct {
|
||||||
type PopupNewsContentsService interface {
|
type PopupNewsContentsService interface {
|
||||||
All(req request.PopupNewsContentsQueryRequest) (data []*response.PopupNewsContentsResponse, paging paginator.Pagination, err error)
|
All(req request.PopupNewsContentsQueryRequest) (data []*response.PopupNewsContentsResponse, paging paginator.Pagination, err error)
|
||||||
Show(id uint) (*response.PopupNewsContentsResponse, error)
|
Show(id uint) (*response.PopupNewsContentsResponse, error)
|
||||||
Save(req request.PopupNewsContentsCreateRequest) (*response.PopupNewsContentsResponse, error)
|
Save(req request.PopupNewsContentsCreateRequest) error
|
||||||
Update(id uint, req request.PopupNewsContentsUpdateRequest) error
|
Update(id uint, req request.PopupNewsContentsUpdateRequest) error
|
||||||
Delete(id uint) error
|
Delete(id uint) error
|
||||||
}
|
}
|
||||||
|
|
@ -58,14 +58,10 @@ func (_i *popupNewsContentsService) Show(id uint) (*response.PopupNewsContentsRe
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save
|
// Save
|
||||||
func (_i *popupNewsContentsService) Save(req request.PopupNewsContentsCreateRequest) (*response.PopupNewsContentsResponse, error) {
|
func (_i *popupNewsContentsService) Save(req request.PopupNewsContentsCreateRequest) error {
|
||||||
_i.Log.Info().Interface("data", req).Msg("create popup news content")
|
_i.Log.Info().Interface("data", req).Msg("create popup news content")
|
||||||
|
|
||||||
ent := req.ToEntity()
|
return _i.Repo.Create(req.ToEntity())
|
||||||
if err := _i.Repo.Create(ent); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return mapper.PopupNewsContentsResponseMapper(ent), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update
|
// Update
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,6 @@ import (
|
||||||
"web-qudo-be/app/module/cities"
|
"web-qudo-be/app/module/cities"
|
||||||
"web-qudo-be/app/module/client_approval_settings"
|
"web-qudo-be/app/module/client_approval_settings"
|
||||||
"web-qudo-be/app/module/clients"
|
"web-qudo-be/app/module/clients"
|
||||||
"web-qudo-be/app/module/cms_media"
|
|
||||||
"web-qudo-be/app/module/custom_static_pages"
|
"web-qudo-be/app/module/custom_static_pages"
|
||||||
"web-qudo-be/app/module/districts"
|
"web-qudo-be/app/module/districts"
|
||||||
"web-qudo-be/app/module/feedbacks"
|
"web-qudo-be/app/module/feedbacks"
|
||||||
|
|
@ -73,7 +72,6 @@ type Router struct {
|
||||||
CitiesRouter *cities.CitiesRouter
|
CitiesRouter *cities.CitiesRouter
|
||||||
ClientApprovalSettingsRouter *client_approval_settings.ClientApprovalSettingsRouter
|
ClientApprovalSettingsRouter *client_approval_settings.ClientApprovalSettingsRouter
|
||||||
ClientsRouter *clients.ClientsRouter
|
ClientsRouter *clients.ClientsRouter
|
||||||
CmsMediaRouter *cms_media.CmsMediaRouter
|
|
||||||
HeroContentsRouter *hero_content.HeroContentsRouter
|
HeroContentsRouter *hero_content.HeroContentsRouter
|
||||||
HeroContentImagesRouter *hero_content_image.HeroContentImagesRouter
|
HeroContentImagesRouter *hero_content_image.HeroContentImagesRouter
|
||||||
CustomStaticPagesRouter *custom_static_pages.CustomStaticPagesRouter
|
CustomStaticPagesRouter *custom_static_pages.CustomStaticPagesRouter
|
||||||
|
|
@ -121,7 +119,6 @@ func NewRouter(
|
||||||
citiesRouter *cities.CitiesRouter,
|
citiesRouter *cities.CitiesRouter,
|
||||||
clientApprovalSettingsRouter *client_approval_settings.ClientApprovalSettingsRouter,
|
clientApprovalSettingsRouter *client_approval_settings.ClientApprovalSettingsRouter,
|
||||||
clientsRouter *clients.ClientsRouter,
|
clientsRouter *clients.ClientsRouter,
|
||||||
cmsMediaRouter *cms_media.CmsMediaRouter,
|
|
||||||
heroContentsRouter *hero_content.HeroContentsRouter,
|
heroContentsRouter *hero_content.HeroContentsRouter,
|
||||||
heroContentImagesRouter *hero_content_image.HeroContentImagesRouter,
|
heroContentImagesRouter *hero_content_image.HeroContentImagesRouter,
|
||||||
customStaticPagesRouter *custom_static_pages.CustomStaticPagesRouter,
|
customStaticPagesRouter *custom_static_pages.CustomStaticPagesRouter,
|
||||||
|
|
@ -168,7 +165,6 @@ func NewRouter(
|
||||||
CitiesRouter: citiesRouter,
|
CitiesRouter: citiesRouter,
|
||||||
ClientApprovalSettingsRouter: clientApprovalSettingsRouter,
|
ClientApprovalSettingsRouter: clientApprovalSettingsRouter,
|
||||||
ClientsRouter: clientsRouter,
|
ClientsRouter: clientsRouter,
|
||||||
CmsMediaRouter: cmsMediaRouter,
|
|
||||||
HeroContentsRouter: heroContentsRouter,
|
HeroContentsRouter: heroContentsRouter,
|
||||||
HeroContentImagesRouter: heroContentImagesRouter,
|
HeroContentImagesRouter: heroContentImagesRouter,
|
||||||
CustomStaticPagesRouter: customStaticPagesRouter,
|
CustomStaticPagesRouter: customStaticPagesRouter,
|
||||||
|
|
@ -225,7 +221,6 @@ func (r *Router) Register() {
|
||||||
r.CitiesRouter.RegisterCitiesRoutes()
|
r.CitiesRouter.RegisterCitiesRoutes()
|
||||||
r.ClientApprovalSettingsRouter.RegisterClientApprovalSettingsRoutes()
|
r.ClientApprovalSettingsRouter.RegisterClientApprovalSettingsRoutes()
|
||||||
r.ClientsRouter.RegisterClientsRoutes()
|
r.ClientsRouter.RegisterClientsRoutes()
|
||||||
r.CmsMediaRouter.RegisterCmsMediaRoutes()
|
|
||||||
r.HeroContentsRouter.RegisterHeroContentsRoutes()
|
r.HeroContentsRouter.RegisterHeroContentsRoutes()
|
||||||
r.HeroContentImagesRouter.RegisterHeroContentImagesRoutes()
|
r.HeroContentImagesRouter.RegisterHeroContentImagesRoutes()
|
||||||
r.CustomStaticPagesRouter.RegisterCustomStaticPagesRoutes()
|
r.CustomStaticPagesRouter.RegisterCustomStaticPagesRoutes()
|
||||||
|
|
|
||||||
|
|
@ -128,23 +128,6 @@ type Config struct {
|
||||||
Smtp smtp
|
Smtp smtp
|
||||||
}
|
}
|
||||||
|
|
||||||
// APIPublicBaseURL is the base URL embedded in links returned to clients (e.g. CMS image preview).
|
|
||||||
// If app.production is true, it uses app.domain (trimmed). Otherwise it uses http://localhost plus app.port
|
|
||||||
// so local runs match opening the API in the browser without rewriting https://qudo.id/api.
|
|
||||||
func (c *Config) APIPublicBaseURL() string {
|
|
||||||
if c.App.Production {
|
|
||||||
return strings.TrimSuffix(c.App.Domain, "/")
|
|
||||||
}
|
|
||||||
port := strings.TrimSpace(c.App.Port)
|
|
||||||
if port == "" {
|
|
||||||
return "http://localhost"
|
|
||||||
}
|
|
||||||
if !strings.HasPrefix(port, ":") {
|
|
||||||
port = ":" + port
|
|
||||||
}
|
|
||||||
return "http://localhost" + port
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewConfig : initialize config
|
// NewConfig : initialize config
|
||||||
func NewConfig() *Config {
|
func NewConfig() *Config {
|
||||||
config, err := ParseConfig("config")
|
config, err := ParseConfig("config")
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
"github.com/minio/minio-go/v7"
|
"github.com/minio/minio-go/v7"
|
||||||
|
|
@ -70,13 +69,3 @@ func (_minio *MinioStorage) ConnectMinio() (*minio.Client, error) {
|
||||||
log.Printf("[MinIO] Successfully connected to MinIO and bucket '%s' is ready", bucketName)
|
log.Printf("[MinIO] Successfully connected to MinIO and bucket '%s' is ready", bucketName)
|
||||||
return minioClient, nil
|
return minioClient, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// PublicObjectURL builds a path-style URL for public reads (bucket policy must allow GET).
|
|
||||||
func (m *MinioStorage) PublicObjectURL(objectKey string) string {
|
|
||||||
o := m.Cfg.ObjectStorage.MinioStorage
|
|
||||||
scheme := "http"
|
|
||||||
if o.UseSSL {
|
|
||||||
scheme = "https"
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("%s://%s/%s/%s", scheme, o.Endpoint, o.BucketName, objectKey)
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -8,12 +8,11 @@ external-port = ":8812"
|
||||||
idle-timeout = 5 # As seconds
|
idle-timeout = 5 # As seconds
|
||||||
print-routes = false
|
print-routes = false
|
||||||
prefork = false
|
prefork = false
|
||||||
# false: CMS preview URLs use http://localhost + port above. true: use domain (e.g. https://qudo.id/api).
|
|
||||||
production = false
|
production = false
|
||||||
body-limit = 1048576000 # "100 * 1024 * 1024"
|
body-limit = 1048576000 # "100 * 1024 * 1024"
|
||||||
|
|
||||||
[db.postgres]
|
[db.postgres]
|
||||||
dsn = "postgresql://qudo_user:QudoDB@2026@38.47.185.79:5432/qudo_db" # <driver>://<username>:<password>@<host>:<port>/<database>
|
dsn = "postgresql://medols_user:MedolsDB@2025@38.47.185.79:5432/medols_db" # <driver>://<username>:<password>@<host>:<port>/<database>
|
||||||
log-mode = "ERROR"
|
log-mode = "ERROR"
|
||||||
migrate = true
|
migrate = true
|
||||||
seed = false
|
seed = false
|
||||||
|
|
@ -29,7 +28,7 @@ endpoint = "is3.cloudhost.id"
|
||||||
access-key-id = "YRP1RM617986USRU6NN8"
|
access-key-id = "YRP1RM617986USRU6NN8"
|
||||||
secret-access-key = "vfbwQDYb1m7nfzo4LVEz90BIyOWfBMZ6bfGQbqDO"
|
secret-access-key = "vfbwQDYb1m7nfzo4LVEz90BIyOWfBMZ6bfGQbqDO"
|
||||||
use-ssl = true
|
use-ssl = true
|
||||||
bucket-name = "qudo"
|
bucket-name = "mikulnews"
|
||||||
location = "us-east-1"
|
location = "us-east-1"
|
||||||
|
|
||||||
[middleware.compress]
|
[middleware.compress]
|
||||||
|
|
|
||||||
2
main.go
2
main.go
|
|
@ -23,7 +23,6 @@ import (
|
||||||
"web-qudo-be/app/module/cities"
|
"web-qudo-be/app/module/cities"
|
||||||
"web-qudo-be/app/module/client_approval_settings"
|
"web-qudo-be/app/module/client_approval_settings"
|
||||||
"web-qudo-be/app/module/clients"
|
"web-qudo-be/app/module/clients"
|
||||||
"web-qudo-be/app/module/cms_media"
|
|
||||||
"web-qudo-be/app/module/custom_static_pages"
|
"web-qudo-be/app/module/custom_static_pages"
|
||||||
"web-qudo-be/app/module/districts"
|
"web-qudo-be/app/module/districts"
|
||||||
"web-qudo-be/app/module/feedbacks"
|
"web-qudo-be/app/module/feedbacks"
|
||||||
|
|
@ -105,7 +104,6 @@ func main() {
|
||||||
cities.NewCitiesModule,
|
cities.NewCitiesModule,
|
||||||
client_approval_settings.NewClientApprovalSettingsModule,
|
client_approval_settings.NewClientApprovalSettingsModule,
|
||||||
clients.NewClientsModule,
|
clients.NewClientsModule,
|
||||||
cms_media.NewCmsMediaModule,
|
|
||||||
custom_static_pages.NewCustomStaticPagesModule,
|
custom_static_pages.NewCustomStaticPagesModule,
|
||||||
districts.NewDistrictsModule,
|
districts.NewDistrictsModule,
|
||||||
feedbacks.NewFeedbacksModule,
|
feedbacks.NewFeedbacksModule,
|
||||||
|
|
|
||||||
|
|
@ -1,76 +0,0 @@
|
||||||
package storage
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"mime"
|
|
||||||
"mime/multipart"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/google/uuid"
|
|
||||||
"github.com/minio/minio-go/v7"
|
|
||||||
|
|
||||||
appcfg "web-qudo-be/config/config"
|
|
||||||
)
|
|
||||||
|
|
||||||
// CMSPreviewURL is the absolute URL served by this API (GET /cms-media/viewer/...) for DB image_url / media_url fields.
|
|
||||||
func CMSPreviewURL(cfg *appcfg.Config, objectKey string) string {
|
|
||||||
base := cfg.APIPublicBaseURL()
|
|
||||||
key := strings.TrimPrefix(strings.TrimSpace(objectKey), "/")
|
|
||||||
return base + "/cms-media/viewer/" + key
|
|
||||||
}
|
|
||||||
|
|
||||||
var imageExts = map[string]bool{
|
|
||||||
".jpg": true, ".jpeg": true, ".png": true, ".gif": true, ".webp": true,
|
|
||||||
}
|
|
||||||
|
|
||||||
var mediaExts = map[string]bool{
|
|
||||||
".jpg": true, ".jpeg": true, ".png": true, ".gif": true, ".webp": true,
|
|
||||||
".mp4": true, ".webm": true,
|
|
||||||
}
|
|
||||||
|
|
||||||
// UploadCMSObject stores a file in MinIO under cms/{folder}/YYYY/MM/{uuid}{ext} and returns object key + preview URL (API viewer, not direct MinIO).
|
|
||||||
func UploadCMSObject(ms *appcfg.MinioStorage, folder string, file *multipart.FileHeader, allowVideo bool) (objectKey string, previewURL string, err error) {
|
|
||||||
if file == nil {
|
|
||||||
return "", "", fmt.Errorf("file is required")
|
|
||||||
}
|
|
||||||
ext := strings.ToLower(filepath.Ext(file.Filename))
|
|
||||||
if allowVideo {
|
|
||||||
if !mediaExts[ext] {
|
|
||||||
return "", "", fmt.Errorf("unsupported file type (allowed: images, mp4, webm)")
|
|
||||||
}
|
|
||||||
} else if !imageExts[ext] {
|
|
||||||
return "", "", fmt.Errorf("unsupported image type")
|
|
||||||
}
|
|
||||||
|
|
||||||
client, err := ms.ConnectMinio()
|
|
||||||
if err != nil {
|
|
||||||
return "", "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
src, err := file.Open()
|
|
||||||
if err != nil {
|
|
||||||
return "", "", err
|
|
||||||
}
|
|
||||||
defer src.Close()
|
|
||||||
|
|
||||||
bucket := ms.Cfg.ObjectStorage.MinioStorage.BucketName
|
|
||||||
now := time.Now()
|
|
||||||
objectKey = fmt.Sprintf("cms/%s/%d/%02d/%s%s", folder, now.Year(), int(now.Month()), uuid.New().String(), ext)
|
|
||||||
|
|
||||||
contentType := mime.TypeByExtension(ext)
|
|
||||||
if contentType == "" {
|
|
||||||
contentType = "application/octet-stream"
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = client.PutObject(context.Background(), bucket, objectKey, src, file.Size, minio.PutObjectOptions{
|
|
||||||
ContentType: contentType,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return "", "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return objectKey, CMSPreviewURL(ms.Cfg, objectKey), nil
|
|
||||||
}
|
|
||||||
BIN
web-qudo-be.exe
BIN
web-qudo-be.exe
Binary file not shown.
Loading…
Reference in New Issue