adjust with multiple image locations
This commit is contained in:
parent
110cbfeec0
commit
5a5d157882
@ -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)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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()
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
|
@ -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
|
||||||
`
|
`
|
||||||
|
@ -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)
|
||||||
|
@ -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 {
|
||||||
|
@ -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
14
util/common.go
Normal 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
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user