add images

This commit is contained in:
nochill 2023-09-19 21:49:48 +07:00
parent a866730e37
commit d05a9671ee
12 changed files with 219 additions and 9 deletions

44
api/image.go Normal file
View File

@ -0,0 +1,44 @@
package api
import (
"net/http"
db "git.nochill.in/nochill/hiling_go/db/sqlc"
"github.com/gin-gonic/gin"
)
type getAllImagesReq struct {
Page int32 `form:"page" binding:"required,min=1"`
PageSize int32 `form:"page_size" binding:"required,min=5"`
LocationId int32 `form:"location_id" binding:"required,numeric"`
}
func (server *Server) getAllImagesByLocation(ctx *gin.Context) {
var req getAllImagesReq
if err := ctx.BindQuery(&req); err != nil {
ctx.JSON(http.StatusBadRequest, ValidationErrorResponse(err))
return
}
arg := db.GetImagesByLocationParams{
Limit: req.PageSize,
Offset: (req.Page - 1) * req.PageSize,
LocationId: req.LocationId,
}
count, err := server.Store.GetCountImageByLocation(ctx, arg.LocationId)
if err != nil {
ctx.JSON(http.StatusInternalServerError, ErrorResponse(err, "Something went wrong"))
return
}
images, err := server.Store.GetImagesByLocation(ctx, arg)
if err != nil {
ctx.JSON(http.StatusInternalServerError, ErrorResponse(err, "Something went wrong"))
return
}
ctx.JSON(http.StatusOK, gin.H{
"total_image": count,
"images": images,
})
}

View File

@ -46,6 +46,9 @@ func (server *Server) getRoutes() {
router.GET("/locations", server.getListLocations) router.GET("/locations", server.getListLocations)
router.GET("/location/:location_id", server.getLocation) router.GET("/location/:location_id", server.getLocation)
//IMAGES
router.GET("/images/location", server.getAllImagesByLocation)
server.Router = router server.Router = router
} }

8
db/csv_seeder/images.csv Normal file
View File

@ -0,0 +1,8 @@
id,image_url,uploaded_by,image_type,image_of
1#https://dynamic-media-cdn.tripadvisor.com/media/photo-o/1b/ee/b0/7b/murni-s-warung-shop-ubud.jpg?w=1200&h=-1&s=1#1#ocations#1
2#https://dynamic-media-cdn.tripadvisor.com/media/photo-o/1b/4f/fc/65/getlstd-property-photo.jpg?w=1100&h=-1&s=1#1#locations#1
3#https://dynamic-media-cdn.tripadvisor.com/media/photo-o/1b/ee/b0/43/murni-s-warung-shop-ubud.jpg?w=1200&h=-1&s=1#1#locations#1
4#https://dynamic-media-cdn.tripadvisor.com/media/photo-o/1b/ee/af/d0/murni-s-warung-shop-ubud.jpg?w=1200&h=-1&s=1#1#locations#1
5#https://dynamic-media-cdn.tripadvisor.com/media/photo-o/04/0f/7e/53/istiqlal-mosque-mesjid.jpg?w=1200&h=-1&s=1#1#locations#2
6#https://dynamic-media-cdn.tripadvisor.com/media/photo-o/28/27/1a/5a/istiqlal-mosque.jpg?w=1200&h=-1&s=1#1#locations#2
7#https://dynamic-media-cdn.tripadvisor.com/media/photo-o/28/27/1a/5a/istiqlal-mosque.jpg?w=1200&h=-1&s=1#1#locations#2
1 id,image_url,uploaded_by,image_type,image_of
2 1#https://dynamic-media-cdn.tripadvisor.com/media/photo-o/1b/ee/b0/7b/murni-s-warung-shop-ubud.jpg?w=1200&h=-1&s=1#1#ocations#1
3 2#https://dynamic-media-cdn.tripadvisor.com/media/photo-o/1b/4f/fc/65/getlstd-property-photo.jpg?w=1100&h=-1&s=1#1#locations#1
4 3#https://dynamic-media-cdn.tripadvisor.com/media/photo-o/1b/ee/b0/43/murni-s-warung-shop-ubud.jpg?w=1200&h=-1&s=1#1#locations#1
5 4#https://dynamic-media-cdn.tripadvisor.com/media/photo-o/1b/ee/af/d0/murni-s-warung-shop-ubud.jpg?w=1200&h=-1&s=1#1#locations#1
6 5#https://dynamic-media-cdn.tripadvisor.com/media/photo-o/04/0f/7e/53/istiqlal-mosque-mesjid.jpg?w=1200&h=-1&s=1#1#locations#2
7 6#https://dynamic-media-cdn.tripadvisor.com/media/photo-o/28/27/1a/5a/istiqlal-mosque.jpg?w=1200&h=-1&s=1#1#locations#2
8 7#https://dynamic-media-cdn.tripadvisor.com/media/photo-o/28/27/1a/5a/istiqlal-mosque.jpg?w=1200&h=-1&s=1#1#locations#2

View File

@ -0,0 +1 @@
DROP TABLE IF EXISTS images;

View File

@ -0,0 +1,9 @@
CREATE TABLE images(
id serial primary key not null,
image_url varchar not null,
uploaded_by integer references "users"("id") not null,
image_type varchar not null, -- Locations, Stories
image_of integer not null, -- Location_id, stories_id
created_at timestamp default (now()) not null,
updated_at timestamp default (now()) not null
);

View File

@ -64,6 +64,36 @@ func (mr *MockStoreMockRecorder) CreateUser(arg0, arg1 interface{}) *gomock.Call
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateUser", reflect.TypeOf((*MockStore)(nil).CreateUser), arg0, arg1) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateUser", reflect.TypeOf((*MockStore)(nil).CreateUser), arg0, arg1)
} }
// GetCountImageByLocation mocks base method.
func (m *MockStore) GetCountImageByLocation(arg0 context.Context, arg1 int32) (int64, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetCountImageByLocation", arg0, arg1)
ret0, _ := ret[0].(int64)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetCountImageByLocation indicates an expected call of GetCountImageByLocation.
func (mr *MockStoreMockRecorder) GetCountImageByLocation(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCountImageByLocation", reflect.TypeOf((*MockStore)(nil).GetCountImageByLocation), arg0, arg1)
}
// GetImagesByLocation mocks base method.
func (m *MockStore) GetImagesByLocation(arg0 context.Context, arg1 db.GetImagesByLocationParams) ([]db.GetImagesByLocationRow, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetImagesByLocation", arg0, arg1)
ret0, _ := ret[0].([]db.GetImagesByLocationRow)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetImagesByLocation indicates an expected call of GetImagesByLocation.
func (mr *MockStoreMockRecorder) GetImagesByLocation(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetImagesByLocation", reflect.TypeOf((*MockStore)(nil).GetImagesByLocation), arg0, arg1)
}
// GetListLocations mocks base method. // GetListLocations mocks base method.
func (m *MockStore) GetListLocations(arg0 context.Context) ([]db.Location, error) { func (m *MockStore) GetListLocations(arg0 context.Context) ([]db.Location, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
@ -95,10 +125,10 @@ func (mr *MockStoreMockRecorder) GetListRecentLocationsWithRatings(arg0, arg1 in
} }
// GetLocation mocks base method. // GetLocation mocks base method.
func (m *MockStore) GetLocation(arg0 context.Context, arg1 int32) (db.Location, error) { func (m *MockStore) GetLocation(arg0 context.Context, arg1 int32) (db.GetLocationRow, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetLocation", arg0, arg1) ret := m.ctrl.Call(m, "GetLocation", arg0, arg1)
ret0, _ := ret[0].(db.Location) ret0, _ := ret[0].(db.GetLocationRow)
ret1, _ := ret[1].(error) ret1, _ := ret[1].(error)
return ret0, ret1 return ret0, ret1
} }

6
db/queries/images.sql Normal file
View File

@ -0,0 +1,6 @@
-- name: GetCountImageByLocation :one
SELECT
COUNT(id)
FROM images
WHERE image_type = 'locations'
AND image_of = $1;

61
db/sqlc/images.go Normal file
View File

@ -0,0 +1,61 @@
package db
import (
"context"
"time"
)
type GetImagesByLocationParams struct {
Limit int32
Offset int32
LocationId int32
}
type GetImagesByLocationRow struct {
ID int32 `json:"id"`
Src string `json:"src"`
CreatedAt time.Time `json:"created_at"`
UploadedBy string `json:"uploaded_by"`
}
const getImagesByLocationQ = `
SELECT
i.id,
i.image_url as src,
i.created_at,
u.username as uploaded_by
FROM images i
JOIN users u on i.uploaded_by = u.id
WHERE i.image_type = 'locations' AND image_of = $1
LIMIT $2
OFFSET $3
`
func (q *Queries) GetImagesByLocation(ctx context.Context, arg GetImagesByLocationParams) ([]GetImagesByLocationRow, error) {
rows, err := q.db.QueryContext(ctx, getImagesByLocationQ, arg.LocationId, arg.Limit, arg.Offset)
if err != nil {
return nil, err
}
defer rows.Close()
items := []GetImagesByLocationRow{}
for rows.Next() {
var i GetImagesByLocationRow
if err := rows.Scan(
&i.ID,
&i.Src,
&i.CreatedAt,
&i.UploadedBy,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Close(); err != nil {
return nil, err
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}

25
db/sqlc/images.sql.go Normal file
View File

@ -0,0 +1,25 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.20.0
// source: images.sql
package db
import (
"context"
)
const getCountImageByLocation = `-- name: GetCountImageByLocation :one
SELECT
COUNT(id)
FROM images
WHERE image_type = 'locations'
AND image_of = $1
`
func (q *Queries) GetCountImageByLocation(ctx context.Context, imageOf int32) (int64, error) {
row := q.db.QueryRowContext(ctx, getCountImageByLocation, imageOf)
var count int64
err := row.Scan(&count)
return count, err
}

View File

@ -124,6 +124,16 @@ type Comment struct {
UpdatedAt sql.NullTime `json:"updated_at"` UpdatedAt sql.NullTime `json:"updated_at"`
} }
type Image struct {
ID int32 `json:"id"`
ImageUrl string `json:"image_url"`
UploadedBy int32 `json:"uploaded_by"`
ImageType string `json:"image_type"`
ImageOf int32 `json:"image_of"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
type Location struct { type Location struct {
ID int32 `json:"id"` ID int32 `json:"id"`
Address string `json:"address"` Address string `json:"address"`
@ -187,10 +197,10 @@ type Review struct {
type Tag struct { type Tag struct {
ID int32 `json:"id"` ID int32 `json:"id"`
Name string `json:"name"` Name string `json:"name"`
SubmittedBy int32 `json:"submitted_by"`
TargetID sql.NullInt32 `json:"target_id"` TargetID sql.NullInt32 `json:"target_id"`
TagsType sql.NullString `json:"tags_type"` TagsType sql.NullString `json:"tags_type"`
CreatedAt sql.NullTime `json:"created_at"` ApprovedBy int32 `json:"approved_by"`
UpdatedAt sql.NullTime `json:"updated_at"`
} }
type User struct { type User struct {
@ -213,6 +223,17 @@ type User struct {
UpdatedAt sql.NullTime `json:"updated_at"` UpdatedAt sql.NullTime `json:"updated_at"`
} }
type UserActivity struct {
ID int32 `json:"id"`
TargetID int32 `json:"target_id"`
Target string `json:"target"`
Action string `json:"action"`
Link sql.NullString `json:"link"`
Comment sql.NullString `json:"comment"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
type UserReport struct { type UserReport struct {
ID int32 `json:"id"` ID int32 `json:"id"`
Message string `json:"message"` Message string `json:"message"`

View File

@ -11,9 +11,10 @@ import (
type Querier interface { type Querier interface {
CreateLocation(ctx context.Context, arg CreateLocationParams) error CreateLocation(ctx context.Context, arg CreateLocationParams) 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)
GetListLocations(ctx context.Context) ([]Location, error) GetListLocations(ctx context.Context) ([]Location, error)
GetListRecentLocationsWithRatings(ctx context.Context, limit int32) ([]GetListRecentLocationsWithRatingsRow, error) GetListRecentLocationsWithRatings(ctx context.Context, limit int32) ([]GetListRecentLocationsWithRatingsRow, error)
GetLocation(ctx context.Context, id int32) (Location, error) GetLocation(ctx context.Context, id int32) (GetLocationRow, error)
UpdatePassword(ctx context.Context, arg UpdatePasswordParams) error UpdatePassword(ctx context.Context, arg UpdatePasswordParams) error
UpdateUser(ctx context.Context, arg UpdateUserParams) (User, error) UpdateUser(ctx context.Context, arg UpdateUserParams) (User, error)
} }

View File

@ -10,6 +10,7 @@ import (
type Store interface { type Store interface {
Querier Querier
GetTopListLocations(ctx context.Context, arg GetTopListLocationsParams) ([]GetTopListLocationsRow, error) GetTopListLocations(ctx context.Context, arg GetTopListLocationsParams) ([]GetTopListLocationsRow, error)
GetImagesByLocation(ctx context.Context, arg GetImagesByLocationParams) ([]GetImagesByLocationRow, error)
} }
type SQLStore struct { type SQLStore struct {