aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBobby <[email protected]>2025-07-17 15:56:55 +0530
committerBobby <[email protected]>2025-07-17 15:56:55 +0530
commit3c39a30a53656fa1c51afb30bb8c07f862bd39e2 (patch)
tree4f4ea2f07d2c333e25337b48aa8c6c74ba9d8369
parentf826397be8178dc3be812ac95c5d9219a7924c32 (diff)
downloadimageboard-3c39a30a53656fa1c51afb30bb8c07f862bd39e2.tar.xz
imageboard-3c39a30a53656fa1c51afb30bb8c07f862bd39e2.zip
posts list page and collage look
-rw-r--r--controllers/posts.go6
-rw-r--r--database/posts.go2
-rw-r--r--imageboard/main.go4
-rw-r--r--models/image.go11
-rw-r--r--static/css/main.css87
-rw-r--r--templates/posts/list.django20
6 files changed, 126 insertions, 4 deletions
diff --git a/controllers/posts.go b/controllers/posts.go
index f77c24c..7e4eae3 100644
--- a/controllers/posts.go
+++ b/controllers/posts.go
@@ -51,11 +51,17 @@ func PostsPageController(ctx *fiber.Ctx) error {
posts, err := database.GetPosts(preferences.PostsPerPage)
+ cdnURL := strings.TrimRight(config.S3.PublicURL, "/") + "/" + config.S3.BucketName
+ if config.S3.FolderPath != "" {
+ cdnURL += "/" + config.S3.FolderPath
+ }
+
return shortcuts.Render(ctx, config.TEMPLATE_POST_LIST, fiber.Map{
"Posts": posts,
"Error": err,
"QueryTags": queryTags,
"QueryRatings": queryRatings,
+ "CDNURL": cdnURL,
})
}
diff --git a/database/posts.go b/database/posts.go
index 3e949c2..dd2a74e 100644
--- a/database/posts.go
+++ b/database/posts.go
@@ -4,7 +4,7 @@ import "imageboard/models"
func GetPosts(limit int) ([]models.Image, error) {
var posts []models.Image
- if err := DB.Limit(limit).Find(&posts).Error; err != nil {
+ if err := DB.Preload("Sizes").Preload("Uploader").Preload("Tags").Limit(limit).Find(&posts).Error; err != nil {
return nil, err
}
return posts, nil
diff --git a/imageboard/main.go b/imageboard/main.go
index 57c5eea..207b1aa 100644
--- a/imageboard/main.go
+++ b/imageboard/main.go
@@ -33,7 +33,9 @@ func main() {
app.Use(recover.New())
app.Use(logger.New())
- app.Use(helmet.New())
+ app.Use(helmet.New(helmet.Config{
+ CrossOriginEmbedderPolicy: "unsafe-none",
+ }))
app.Use(cors.New())
processors.Initialize(app)
diff --git a/models/image.go b/models/image.go
index 3eeadb1..03f6d0f 100644
--- a/models/image.go
+++ b/models/image.go
@@ -13,7 +13,7 @@ import (
type ImageSize struct {
gorm.Model
ImageID uint `gorm:"not null;index" json:"-"`
- Image Image `gorm:"foreignKey:ImageID" json:"image"`
+ Image Image `gorm:"foreignKey:ImageID" json:"-"`
SizeType config.ImageSizeType `gorm:"not null;size:50" json:"size_type"`
Width int `gorm:"not null" json:"width"`
Height int `gorm:"not null" json:"height"`
@@ -121,6 +121,15 @@ func (i *Image) GetSize(sizeType config.ImageSizeType) *ImageSize {
return nil
}
+func (i *Image) GetSizeByString(sizeType string) *ImageSize {
+ for _, size := range i.Sizes {
+ if string(size.SizeType) == sizeType {
+ return &size
+ }
+ }
+ return nil
+}
+
func (i *Image) GetOriginalDimensions() string {
if fullSize := i.GetSize(config.ImageSizeTypeOriginal); fullSize != nil {
return fullSize.GetDimensions()
diff --git a/static/css/main.css b/static/css/main.css
index 969b156..685a24e 100644
--- a/static/css/main.css
+++ b/static/css/main.css
@@ -692,4 +692,91 @@ footer::before {
background-color: #440000;
border-color: #ff0000;
color: #ffcccc;
+}
+
+.post-list {
+ margin: 16px auto;
+ columns: 4;
+ column-gap: 4px;
+}
+
+.post-item {
+ break-inside: avoid;
+ margin-bottom: 4px;
+ cursor: pointer;
+ position: relative;
+ display: inline-block;
+ width: 100%;
+ overflow: hidden;
+ border: 2px solid transparent;
+ transition: border-color 0.3s ease;
+}
+
+.post-item:hover {
+ border-color: #4a9eff;
+ box-shadow: 0 0 10px rgba(74, 158, 255, 0.3);
+}
+
+.post-item img {
+ width: 100%;
+ height: auto;
+ display: block;
+}
+
+.post-overlay {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ background: linear-gradient(to top, rgba(10, 14, 26, 0.95) 0%, rgba(10, 14, 26, 0.7) 60%, transparent 100%);
+ color: #4a9eff;
+ padding: 8px 6px 6px 6px;
+ transform: translateY(100%);
+ transition: transform 0.3s ease;
+}
+
+.post-item:hover .post-overlay {
+ transform: translateY(0);
+}
+
+.post-overlay-top {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 4px;
+}
+
+.post-id {
+ color: #ffffff;
+ font-weight: bold;
+}
+
+.post-score {
+ color: #ffa500;
+}
+
+.post-rating {
+ color: #ff6b6b;
+}
+
+.post-tags {
+ word-wrap: break-word;
+ max-height: 40px;
+ overflow: hidden;
+}
+
+.post-tags .tag {
+ text-decoration: none;
+ margin-right: 3px;
+ cursor: pointer;
+ padding: 1px 2px;
+ border-radius: 2px;
+ display: inline-block;
+ margin-bottom: 1px;
+ transition: all 0.2s ease;
+}
+
+.post-tags .post-tag:hover {
+ background-color: rgba(255, 255, 255, 0.2);
+ transform: scale(1.1);
} \ No newline at end of file
diff --git a/templates/posts/list.django b/templates/posts/list.django
index 2dc5d03..c476cfa 100644
--- a/templates/posts/list.django
+++ b/templates/posts/list.django
@@ -7,7 +7,25 @@
{% endif %}
{% include 'partials/search.django' %}
{% if Posts %}
- Will Show posts here
+ <div class="post-list">
+ {% for image in Posts %}
+ <a href="/posts/{{ image.ID }}" class="post-item">
+ <img src="{{ CDNURL }}/thumbnail/{{ image.FileName }}" alt="{{ image.Title }}" width="{{ image.Sizes.1.Width }}" height="{{ image.Sizes.1.Height }}" />
+ <div class="post-overlay">
+ <div class="post-overlay-top">
+ <div class="post-id">ID: {{ image.ID }}</div>
+ <div class="post-score">★{{ image.FavouriteCount }}</div>
+ </div>
+ <div class="post-rating">{{ image.Rating }}</div>
+ <div class="post-tags">
+ {% for tag in image.Tags %}
+ <span class="post-tag" style="color: {{ tag.Type.Color }};">{{ tag.Name }}</span>
+ {% endfor %}
+ </div>
+ </div>
+ </a>
+ {% endfor %}
+ </div>
{% else %}
<div class="centered-main">
<h1>No Posts Available</h1>