adjust with multiple image locations

This commit is contained in:
nochill 2023-10-03 14:56:57 +07:00
parent 110cbfeec0
commit 5a5d157882
10 changed files with 166 additions and 69 deletions

View File

@ -20,6 +20,7 @@ type createLocationReq struct {
Name string `form:"name" binding:"required"` Name string `form:"name" binding:"required"`
SubmittedBy int32 `form:"submitted_by" binding:"required,number"` SubmittedBy int32 `form:"submitted_by" binding:"required,number"`
RegencyID int16 `form:"regency_id" binding:"required,number"` RegencyID int16 `form:"regency_id" binding:"required,number"`
LocationType string `form:"location_type" binding:"required"`
GoogleMapsLink string `form:"google_maps_link"` GoogleMapsLink string `form:"google_maps_link"`
} }
@ -27,40 +28,23 @@ func (server *Server) createLocation(ctx *gin.Context) {
var req createLocationReq var req createLocationReq
var imgPath string var imgPath string
var thumbnail, _ = ctx.FormFile("thumbnail")
if err := ctx.Bind(&req); err != nil { if err := ctx.Bind(&req); err != nil {
ctx.JSON(http.StatusBadRequest, ValidationErrorResponse(err)) ctx.JSON(http.StatusBadRequest, ValidationErrorResponse(err))
return return
} }
if thumbnail != nil {
img := thumbnail
fileExt := filepath.Ext(img.Filename)
now := time.Now()
dir := fmt.Sprintf("public/upload/images/locations/%s/thumbnail", req.Name)
osFilename := fmt.Sprintf("%s%s%s", util.RandomString(5), fmt.Sprintf("%v", now.Unix()), fileExt)
imgPath = fmt.Sprintf("%s%s", dir, osFilename)
if _, err := os.Stat(dir); os.IsNotExist(err) {
os.Mkdir(dir, 0775)
}
if err := ctx.SaveUploadedFile(img, imgPath); err != nil {
ctx.JSON(http.StatusInternalServerError, ErrorResponse(err, "Error while try to save thumbnail image"))
return
}
}
arg := db.CreateLocationParams{ arg := db.CreateLocationParams{
Address: req.Address, Address: req.Address,
Name: req.Name, Name: req.Name,
LocationType: db.LocationType(req.LocationType),
SubmittedBy: req.SubmittedBy, SubmittedBy: req.SubmittedBy,
RegencyID: req.RegencyID, RegencyID: req.RegencyID,
IsDeleted: false,
ApprovedBy: sql.NullInt32{Int32: 0, Valid: false},
GoogleMapsLink: sql.NullString{Valid: len(req.GoogleMapsLink) > 0, String: req.GoogleMapsLink}, GoogleMapsLink: sql.NullString{Valid: len(req.GoogleMapsLink) > 0, String: req.GoogleMapsLink},
} }
err := server.Store.CreateLocation(ctx, arg) id, err := server.Store.CreateLocation(ctx, arg)
if err != nil { if err != nil {
if pqErr, ok := err.(*pq.Error); ok { if pqErr, ok := err.(*pq.Error); ok {
@ -76,10 +60,47 @@ func (server *Server) createLocation(ctx *gin.Context) {
} }
} }
} }
ctx.JSON(http.StatusInternalServerError, ErrorResponse(err, "Something went wrong")) ctx.JSON(http.StatusInternalServerError, ErrorResponse(err, "Something went wrong while try to create location"))
return return
} }
form, _ := ctx.MultipartForm()
thumbnails := form.File["thumbnail"]
if len(thumbnails) > 0 {
var tempImg []db.CreateImageParams
for _, img := range thumbnails {
fileExt := filepath.Ext(img.Filename)
now := time.Now()
dir := fmt.Sprintf("public/upload/images/locations/%s/thumbnail", req.Name)
osFilename := fmt.Sprintf("%s%s%s", util.RandomString(5), fmt.Sprintf("%v", now.Unix()), fileExt)
imgPath = fmt.Sprintf("%s/%s", dir, osFilename)
if _, err := os.Stat(dir); os.IsNotExist(err) {
os.Mkdir(dir, 0775)
}
if err := ctx.SaveUploadedFile(img, imgPath); err != nil {
ctx.JSON(http.StatusInternalServerError, ErrorResponse(err, "Error while try to save thumbnail image"))
return
}
tempImg = append(tempImg, db.CreateImageParams{
ImageUrl: imgPath,
UploadedBy: req.SubmittedBy,
ImageType: "locations",
ImageOf: id,
})
}
err := server.Store.CreateImage(ctx, tempImg)
if err != nil {
ctx.JSON(http.StatusInternalServerError, ErrorResponse(err, "Something went wrong while try to save image"))
return
}
}
ctx.Writer.WriteHeader(http.StatusOK) ctx.Writer.WriteHeader(http.StatusOK)
} }

View File

@ -50,14 +50,29 @@ func (mr *MockStoreMockRecorder) CheckIfReviewExists(arg0, arg1 interface{}) *go
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CheckIfReviewExists", reflect.TypeOf((*MockStore)(nil).CheckIfReviewExists), arg0, arg1) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CheckIfReviewExists", reflect.TypeOf((*MockStore)(nil).CheckIfReviewExists), arg0, arg1)
} }
// CreateLocation mocks base method. // CreateImage mocks base method.
func (m *MockStore) CreateLocation(arg0 context.Context, arg1 db.CreateLocationParams) error { func (m *MockStore) CreateImage(arg0 context.Context, arg1 []db.CreateImageParams) error {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "CreateLocation", arg0, arg1) ret := m.ctrl.Call(m, "CreateImage", arg0, arg1)
ret0, _ := ret[0].(error) ret0, _ := ret[0].(error)
return ret0 return ret0
} }
// CreateImage indicates an expected call of CreateImage.
func (mr *MockStoreMockRecorder) CreateImage(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateImage", reflect.TypeOf((*MockStore)(nil).CreateImage), arg0, arg1)
}
// CreateLocation mocks base method.
func (m *MockStore) CreateLocation(arg0 context.Context, arg1 db.CreateLocationParams) (int32, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "CreateLocation", arg0, arg1)
ret0, _ := ret[0].(int32)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// CreateLocation indicates an expected call of CreateLocation. // CreateLocation indicates an expected call of CreateLocation.
func (mr *MockStoreMockRecorder) CreateLocation(arg0, arg1 interface{}) *gomock.Call { func (mr *MockStoreMockRecorder) CreateLocation(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper() mr.mock.ctrl.T.Helper()

View File

@ -19,17 +19,6 @@ WHERE approved_by IS NOT NULL
ORDER BY l.created_at ASC ORDER BY l.created_at ASC
LIMIT $1; LIMIT $1;
-- name: CreateLocation :exec
INSERT INTO locations(
address,
name,
submitted_by,
regency_id,
google_maps_link
) values (
$1, $2, $3, $4, $5
);
-- name: GetLocationTag :many -- name: GetLocationTag :many
SELECT SELECT
name name

View File

@ -2,7 +2,10 @@ package db
import ( import (
"context" "context"
"strings"
"time" "time"
"git.nochill.in/nochill/hiling_go/util"
) )
type GetImagesByLocationParams struct { type GetImagesByLocationParams struct {
@ -59,3 +62,38 @@ func (q *Queries) GetImagesByLocation(ctx context.Context, arg GetImagesByLocati
} }
return items, nil return items, nil
} }
type CreateImageParams struct {
ImageUrl string `json:"url"`
UploadedBy int32 `json:"uploaded_by"`
ImageType string `json:"image_type"`
ImageOf int32 `json:"image_of"`
}
func (q *Queries) CreateImage(ctx context.Context, arg []CreateImageParams) error {
values := []interface{}{}
queryStr := ` INSERT INTO
images(image_url, uploaded_by, image_type, image_of)
VALUES
`
for _, row := range arg {
queryStr += "(?, ?, ?, ?),"
values = append(values, row.ImageUrl, row.UploadedBy, row.ImageType, row.ImageOf)
}
queryStr = strings.TrimSuffix(queryStr, ",")
// Replacing ? with $n for postgres
queryStr = util.ReplaceSQL(queryStr, "?")
// prepare the statement
stmt, _ := q.db.PrepareContext(ctx, queryStr)
// format all vals at once
_, err := stmt.ExecContext(ctx, values...)
return err
}

View File

@ -171,3 +171,53 @@ func (q *Queries) GetLocation(ctx context.Context, location_id int32) (GetLocati
return i, err return i, err
} }
const createLocation = `-- name: CreateLocation :exec
INSERT INTO locations(
address,
name,
submitted_by,
location_type,
regency_id,
google_maps_link,
approved_by,
is_deleted
) values (
$1, $2, $3, $4, $5, $6, $7, $8
)
RETURNING id
`
type CreateLocationParams struct {
Address string `json:"address"`
Name string `json:"name"`
SubmittedBy int32 `json:"submitted_by"`
LocationType LocationType `json:"location_type"`
RegencyID int16 `json:"regency_id"`
GoogleMapsLink sql.NullString `json:"google_maps_link"`
IsDeleted bool `json:"is_deleted"`
ApprovedBy sql.NullInt32 `json:"approved_by"`
}
func (q *Queries) CreateLocation(ctx context.Context, arg CreateLocationParams) (int32, error) {
row := q.db.QueryRowContext(ctx, createLocation,
arg.Address,
arg.Name,
arg.SubmittedBy,
arg.LocationType,
arg.RegencyID,
arg.GoogleMapsLink,
arg.ApprovedBy,
arg.IsDeleted,
)
var i int32
err := row.Scan(
&i,
)
fmt.Println(i)
return i, err
}

View File

@ -10,37 +10,6 @@ import (
"database/sql" "database/sql"
) )
const createLocation = `-- name: CreateLocation :exec
INSERT INTO locations(
address,
name,
submitted_by,
regency_id,
google_maps_link
) values (
$1, $2, $3, $4, $5
)
`
type CreateLocationParams struct {
Address string `json:"address"`
Name string `json:"name"`
SubmittedBy int32 `json:"submitted_by"`
RegencyID int16 `json:"regency_id"`
GoogleMapsLink sql.NullString `json:"google_maps_link"`
}
func (q *Queries) CreateLocation(ctx context.Context, arg CreateLocationParams) error {
_, err := q.db.ExecContext(ctx, createLocation,
arg.Address,
arg.Name,
arg.SubmittedBy,
arg.RegencyID,
arg.GoogleMapsLink,
)
return err
}
const getListLocations = `-- name: GetListLocations :many const getListLocations = `-- name: GetListLocations :many
SELECT id, address, name, google_maps_link, location_type, submitted_by, total_visited, thumbnail, regency_id, is_deleted, created_at, updated_at, approved_by, approved_at FROM locations SELECT id, address, name, google_maps_link, location_type, submitted_by, total_visited, thumbnail, regency_id, is_deleted, created_at, updated_at, approved_by, approved_at FROM locations
` `

View File

@ -10,7 +10,6 @@ import (
type Querier interface { type Querier interface {
CheckIfReviewExists(ctx context.Context, arg CheckIfReviewExistsParams) (int64, error) CheckIfReviewExists(ctx context.Context, arg CheckIfReviewExistsParams) (int64, error)
CreateLocation(ctx context.Context, arg CreateLocationParams) error
CreateSession(ctx context.Context, arg CreateSessionParams) (UserSession, error) CreateSession(ctx context.Context, arg CreateSessionParams) (UserSession, error)
CreateUser(ctx context.Context, arg CreateUserParams) (User, error) CreateUser(ctx context.Context, arg CreateUserParams) (User, error)
GetCountImageByLocation(ctx context.Context, imageOf int32) (int64, error) GetCountImageByLocation(ctx context.Context, imageOf int32) (int64, error)

View File

@ -15,6 +15,8 @@ type Store interface {
GetUser(ctx context.Context, username string) (GetUserRow, error) GetUser(ctx context.Context, username string) (GetUserRow, error)
CreateReview(ctx context.Context, arg CreateReviewParams) (Review, error) CreateReview(ctx context.Context, arg CreateReviewParams) (Review, error)
GetListLocationReviews(ctx context.Context, arg GetListLocationReviewsParams) ([]GetListLocationReviewsRow, error) GetListLocationReviews(ctx context.Context, arg GetListLocationReviewsParams) ([]GetListLocationReviewsRow, error)
CreateLocation(ctx context.Context, arg CreateLocationParams) (int32, error)
CreateImage(ctx context.Context, arg []CreateImageParams) error
} }
type SQLStore struct { type SQLStore struct {

View File

@ -31,6 +31,6 @@ func TestCreateLocation(t *testing.T) {
GoogleMapsLink: sql.NullString{Valid: true, String: util.RandomString(10)}, GoogleMapsLink: sql.NullString{Valid: true, String: util.RandomString(10)},
} }
err := testQueries.CreateLocation(context.Background(), arg) _, err := testQueries.CreateLocation(context.Background(), arg)
require.NoError(t, err) require.NoError(t, err)
} }

14
util/common.go Normal file
View File

@ -0,0 +1,14 @@
package util
import (
"strconv"
"strings"
)
func ReplaceSQL(old, searchPattern string) string {
tmpCount := strings.Count(old, searchPattern)
for m := 1; m <= tmpCount; m++ {
old = strings.Replace(old, searchPattern, "$"+strconv.Itoa(m), 1)
}
return old
}