Fix archiving and unarchiving functionality.
This commit is contained in:
@@ -21,6 +21,6 @@ type MessageService interface {
|
|||||||
Archive(userID, id int64) error
|
Archive(userID, id int64) error
|
||||||
//Restore()
|
//Restore()
|
||||||
//ToDo: implement
|
//ToDo: implement
|
||||||
//Unarchive(userID, id int64) error
|
Unarchive(userID, id int64) error
|
||||||
//MarkRead(userID, id int64) error
|
//MarkRead(userID, id int64) error
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,12 +6,14 @@ package accountMessageHandler
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"database/sql"
|
||||||
|
"errors"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
templateHandlers "synlotto-website/internal/handlers/template"
|
templateHandlers "synlotto-website/internal/handlers/template"
|
||||||
templateHelpers "synlotto-website/internal/helpers/template"
|
templateHelpers "synlotto-website/internal/helpers/template"
|
||||||
errors "synlotto-website/internal/http/error"
|
httpErrors "synlotto-website/internal/http/error"
|
||||||
|
|
||||||
"synlotto-website/internal/logging"
|
"synlotto-website/internal/logging"
|
||||||
"synlotto-website/internal/platform/bootstrap"
|
"synlotto-website/internal/platform/bootstrap"
|
||||||
@@ -104,7 +106,7 @@ func (h *AccountMessageHandlers) ArchivePost(c *gin.Context) {
|
|||||||
idStr := c.PostForm("id")
|
idStr := c.PostForm("id")
|
||||||
id, err := strconv.ParseInt(idStr, 10, 64)
|
id, err := strconv.ParseInt(idStr, 10, 64)
|
||||||
if err != nil || id <= 0 {
|
if err != nil || id <= 0 {
|
||||||
errors.RenderStatus(c, sm, http.StatusBadRequest)
|
httpErrors.RenderStatus(c, sm, http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,24 +121,32 @@ func (h *AccountMessageHandlers) ArchivePost(c *gin.Context) {
|
|||||||
c.Redirect(http.StatusSeeOther, "/account/messages")
|
c.Redirect(http.StatusSeeOther, "/account/messages")
|
||||||
}
|
}
|
||||||
|
|
||||||
// POST /account/messages/restore
|
// POST /account/messages/archived
|
||||||
func (h *AccountMessageHandlers) RestorePost(c *gin.Context) {
|
func (h *AccountMessageHandlers) RestoreArchived(c *gin.Context) {
|
||||||
app := c.MustGet("app").(*bootstrap.App)
|
app := c.MustGet("app").(*bootstrap.App)
|
||||||
sm := app.SessionManager
|
sm := app.SessionManager
|
||||||
//userID := mustUserID(c)
|
userID := mustUserID(c)
|
||||||
|
|
||||||
idStr := c.PostForm("id")
|
idStr := c.PostForm("id")
|
||||||
id, err := strconv.ParseInt(idStr, 10, 64)
|
id, err := strconv.ParseInt(idStr, 10, 64)
|
||||||
if err != nil || id <= 0 {
|
if err != nil || id <= 0 {
|
||||||
errors.RenderStatus(c, sm, http.StatusBadRequest)
|
sm.Put(c.Request.Context(), "flash", "Invalid message id.")
|
||||||
|
c.Redirect(http.StatusSeeOther, "/account/messages/archive")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
//
|
|
||||||
// if err := h.Svc.Unarchive(userID, id); err != nil {
|
if err := h.Svc.Unarchive(userID, id); err != nil {
|
||||||
// logging.Info("❌ Restore error: %v", err)
|
logging.Info("❌ restore/unarchive error: %v", err)
|
||||||
// sm.Put(c.Request.Context(), "flash", "Could not restore message.")
|
// If no rows affected, show friendly flash; otherwise generic message.
|
||||||
// } else {
|
if errors.Is(err, sql.ErrNoRows) {
|
||||||
// sm.Put(c.Request.Context(), "flash", "Message restored.")
|
sm.Put(c.Request.Context(), "flash", "Message not found or not permitted.")
|
||||||
// }
|
} else {
|
||||||
c.Redirect(http.StatusSeeOther, "/account/messages/archived")
|
sm.Put(c.Request.Context(), "flash", "Could not restore message.")
|
||||||
|
}
|
||||||
|
c.Redirect(http.StatusSeeOther, "/account/messages/archive")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
sm.Put(c.Request.Context(), "flash", "Message restored.")
|
||||||
|
c.Redirect(http.StatusSeeOther, "/account/messages/archive")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -177,6 +177,6 @@ func RestoreMessageHandler(app *bootstrap.App) http.HandlerFunc {
|
|||||||
templateHelpers.SetFlash(r, "Message restored.")
|
templateHelpers.SetFlash(r, "Message restored.")
|
||||||
}
|
}
|
||||||
|
|
||||||
http.Redirect(w, r, "/account/messages/archived", http.StatusSeeOther)
|
http.Redirect(w, r, "/account/messages/archive", http.StatusSeeOther)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ func RegisterAccountRoutes(app *bootstrap.App) {
|
|||||||
messages.POST("/send", msgH.SendPost)
|
messages.POST("/send", msgH.SendPost)
|
||||||
messages.GET("/archive", msgH.ArchivedList) // view archived messages
|
messages.GET("/archive", msgH.ArchivedList) // view archived messages
|
||||||
messages.POST("/archive", msgH.ArchivePost) // archive a message
|
messages.POST("/archive", msgH.ArchivePost) // archive a message
|
||||||
messages.POST("/restore", msgH.RestorePost)
|
messages.POST("/restore", msgH.RestoreArchived)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notifications (auth-required)
|
// Notifications (auth-required)
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
import "time"
|
import (
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
type Message struct {
|
type Message struct {
|
||||||
ID int
|
ID int
|
||||||
|
|||||||
@@ -76,7 +76,8 @@ func (s *Service) ListArchived(userID int64) ([]domain.Message, error) {
|
|||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
q := `
|
q := `
|
||||||
SELECT id, senderId, recipientId, subject, body, is_read, is_archived, created_at
|
SELECT id, senderId, recipientId, subject, body,
|
||||||
|
is_read, is_archived, created_at, archived_at
|
||||||
FROM user_messages
|
FROM user_messages
|
||||||
WHERE recipientId = ? AND is_archived = TRUE
|
WHERE recipientId = ? AND is_archived = TRUE
|
||||||
ORDER BY created_at DESC`
|
ORDER BY created_at DESC`
|
||||||
@@ -91,11 +92,32 @@ func (s *Service) ListArchived(userID int64) ([]domain.Message, error) {
|
|||||||
var out []domain.Message
|
var out []domain.Message
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var m domain.Message
|
var m domain.Message
|
||||||
if err := rows.Scan(&m.ID, &m.SenderId, &m.RecipientId, &m.Subject, &m.Body, &m.IsRead, &m.IsArchived, &m.CreatedAt); err != nil {
|
var archived sql.NullTime
|
||||||
|
|
||||||
|
if err := rows.Scan(
|
||||||
|
&m.ID,
|
||||||
|
&m.SenderId,
|
||||||
|
&m.RecipientId,
|
||||||
|
&m.Subject,
|
||||||
|
&m.Body,
|
||||||
|
&m.IsRead,
|
||||||
|
&m.IsArchived,
|
||||||
|
&m.CreatedAt,
|
||||||
|
&archived,
|
||||||
|
); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if archived.Valid {
|
||||||
|
t := archived.Time
|
||||||
|
m.ArchivedAt = &t
|
||||||
|
} else {
|
||||||
|
m.ArchivedAt = nil
|
||||||
|
}
|
||||||
|
|
||||||
out = append(out, m)
|
out = append(out, m)
|
||||||
}
|
}
|
||||||
|
|
||||||
return out, rows.Err()
|
return out, rows.Err()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -233,3 +255,25 @@ func intToStr(n int) string {
|
|||||||
}
|
}
|
||||||
return string(b[i:])
|
return string(b[i:])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Service) Unarchive(userID, id int64) error {
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), s.Timeout)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
q := `
|
||||||
|
UPDATE user_messages
|
||||||
|
SET is_archived = 0, archived_at = NULL
|
||||||
|
WHERE id = ? AND recipientId = ?
|
||||||
|
`
|
||||||
|
q = s.bind(q)
|
||||||
|
|
||||||
|
res, err := s.DB.ExecContext(ctx, q, id, userID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
n, _ := res.RowsAffected()
|
||||||
|
if n == 0 {
|
||||||
|
return sql.ErrNoRows
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
<p class="card-text">
|
<p class="card-text">
|
||||||
<small class="text-muted">
|
<small class="text-muted">
|
||||||
Archived:
|
Archived:
|
||||||
{{ if .ArchivedAt.Valid }}
|
{{ with .ArchivedAt }}
|
||||||
{{ .Format "02 Jan 2006 15:04" }}
|
{{ .Format "02 Jan 2006 15:04" }}
|
||||||
{{ else }}
|
{{ else }}
|
||||||
—
|
—
|
||||||
@@ -30,14 +30,14 @@
|
|||||||
<!-- Pagination Controls (keep if your funcs exist) -->
|
<!-- Pagination Controls (keep if your funcs exist) -->
|
||||||
<nav>
|
<nav>
|
||||||
<ul class="pagination">
|
<ul class="pagination">
|
||||||
{{ if gt .Page 1 }}
|
{{ if gt .CurrentPage 1 }}
|
||||||
<li class="page-item">
|
<li class="page-item">
|
||||||
<a class="page-link" href="?page={{ minus1 .Page }}">Previous</a>
|
<a class="page-link" href="?page={{ sub .CurrentPage 1 }}">Previous</a>
|
||||||
</li>
|
</li>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
{{ if .HasMore }}
|
{{ if lt .CurrentPage .TotalPages }}
|
||||||
<li class="page-item">
|
<li class="page-item">
|
||||||
<a class="page-link" href="?page={{ plus1 .Page }}">Next</a>
|
<a class="page-link" href="?page={{ add .CurrentPage 1 }}">Next</a>
|
||||||
</li>
|
</li>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
{{ range .Messages }}
|
{{ range .Messages }}
|
||||||
<li class="list-group-item d-flex justify-content-between align-items-center">
|
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||||
<div>
|
<div>
|
||||||
<a href="/account/messages/read?={{ .ID }}" class="fw-bold text-dark">{{ .Subject }}</a><br>
|
<a href="/account/messages/read?id={{ .ID }}" class="fw-bold text-dark">{{ .Subject }}</a><br>
|
||||||
<small class="text-muted">{{ .CreatedAt.Format "02 Jan 2006 15:04" }}</small>
|
<small class="text-muted">{{ .CreatedAt.Format "02 Jan 2006 15:04" }}</small>
|
||||||
</div>
|
</div>
|
||||||
<form method="POST" action="/account/messages/archive" class="m-0">
|
<form method="POST" action="/account/messages/archive" class="m-0">
|
||||||
|
|||||||
Reference in New Issue
Block a user