Merge pull request #1698 from NyaaPantsu/fix
Redesign of notification page, lots of fixes & lots of improvements
Cette révision appartient à :
révision
6f47f1b77d
|
@ -59,15 +59,15 @@ func addAnnouncement(c *gin.Context) {
|
||||||
c.AbortWithStatus(http.StatusNotFound)
|
c.AbortWithStatus(http.StatusNotFound)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
delay := int(math.Ceil(math.Max(1, float64(announcement.Expire.Sub(time.Now())/(24*time.Hour)))))
|
duration := int(math.Ceil(math.Max(1, float64(announcement.Expire.Sub(time.Now())/(24*time.Hour)))))
|
||||||
form := &announcementValidator.CreateForm{
|
form := &announcementValidator.CreateForm{
|
||||||
ID: announcement.ID,
|
ID: announcement.ID,
|
||||||
Message: announcement.Content,
|
Message: announcement.Content,
|
||||||
Delay: delay,
|
Duration: duration,
|
||||||
}
|
}
|
||||||
c.Bind(form)
|
c.Bind(form)
|
||||||
if form.Delay == 0 {
|
if form.Duration == 0 {
|
||||||
form.Delay = delay
|
form.Duration = duration
|
||||||
}
|
}
|
||||||
templates.Form(c, "admin/announcement_form.jet.html", form)
|
templates.Form(c, "admin/announcement_form.jet.html", form)
|
||||||
}
|
}
|
||||||
|
@ -102,7 +102,8 @@ func postAnnouncement(c *gin.Context) {
|
||||||
}
|
}
|
||||||
} else { // announcement doesn't exist, we create it
|
} else { // announcement doesn't exist, we create it
|
||||||
var err error
|
var err error
|
||||||
announcement, err := notifications.NotifyAll(form.Message, time.Now().AddDate(0, 0, form.Delay))
|
currentTime := time.Now()
|
||||||
|
announcement, err := notifications.NotifyAll(form.Message, currentTime.Add(time.Hour * time.Duration(form.Duration)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Error, we add it as a message
|
// Error, we add it as a message
|
||||||
messages.AddErrorT("errors", "create_failed")
|
messages.AddErrorT("errors", "create_failed")
|
||||||
|
@ -120,7 +121,7 @@ func postAnnouncement(c *gin.Context) {
|
||||||
|
|
||||||
// deleteAnnouncement : Controller for deleting an announcement
|
// deleteAnnouncement : Controller for deleting an announcement
|
||||||
func deleteAnnouncement(c *gin.Context) {
|
func deleteAnnouncement(c *gin.Context) {
|
||||||
id, _ := strconv.ParseInt(c.Query("id"), 10, 32)
|
id, _ := strconv.ParseInt(c.PostForm("id"), 10, 32)
|
||||||
announcement, err := notifications.FindByID(uint(id))
|
announcement, err := notifications.FindByID(uint(id))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithStatus(http.StatusNotFound)
|
c.AbortWithStatus(http.StatusNotFound)
|
||||||
|
|
|
@ -146,7 +146,7 @@ func torrentManyAction(c *gin.Context) {
|
||||||
query.Append("torrent_id", torrentID)
|
query.Append("torrent_id", torrentID)
|
||||||
reports, _, _ := reports.FindOrderBy(query, "", 0, 0)
|
reports, _, _ := reports.FindOrderBy(query, "", 0, 0)
|
||||||
for _, report := range reports {
|
for _, report := range reports {
|
||||||
report.Delete(false)
|
report.Delete()
|
||||||
}
|
}
|
||||||
messages.AddInfoTf("infos", "torrent_reports_deleted", torrent.Name)
|
messages.AddInfoTf("infos", "torrent_reports_deleted", torrent.Name)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package moderatorController
|
package moderatorController
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"html"
|
"html"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
@ -39,13 +38,16 @@ func TorrentReportListPanel(c *gin.Context) {
|
||||||
func TorrentReportDeleteModPanel(c *gin.Context) {
|
func TorrentReportDeleteModPanel(c *gin.Context) {
|
||||||
id := c.PostForm("id")
|
id := c.PostForm("id")
|
||||||
|
|
||||||
fmt.Println(id)
|
if c.Request.URL.Query()["all"] != nil {
|
||||||
idNum, _ := strconv.ParseUint(id, 10, 64)
|
reports.DeleteAll()
|
||||||
_, _, _ = reports.Delete(uint(idNum))
|
} else {
|
||||||
/* If we need to log report delete activity
|
idNum, _ := strconv.ParseUint(id, 10, 64)
|
||||||
if err == nil {
|
_, _, _ = reports.Delete(uint(idNum))
|
||||||
activity.Log(&models.User{}, torrent.Identifier(), "delete", "torrent_report_deleted_by", strconv.Itoa(int(report.ID)), router.GetUser(c).Username)
|
/* If we need to log report delete activity
|
||||||
|
if err == nil {
|
||||||
|
activity.Log(&models.User{}, torrent.Identifier(), "delete", "torrent_report_deleted_by", strconv.Itoa(int(report.ID)), router.GetUser(c).Username)
|
||||||
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
c.Redirect(http.StatusSeeOther, "/mod/reports?deleted")
|
c.Redirect(http.StatusSeeOther, "/mod/reports?deleted")
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,26 +129,19 @@ func TorrentDeleteModPanel(c *gin.Context) {
|
||||||
var err error
|
var err error
|
||||||
if definitely != nil {
|
if definitely != nil {
|
||||||
_, _, err = torrent.DefinitelyDelete()
|
_, _, err = torrent.DefinitelyDelete()
|
||||||
|
|
||||||
//delete reports of torrent
|
|
||||||
query := &search.Query{}
|
|
||||||
query.Append("torrent_id", id)
|
|
||||||
reports, _, _ := reports.FindOrderBy(query, "", 0, 0)
|
|
||||||
for _, report := range reports {
|
|
||||||
report.Delete(true)
|
|
||||||
}
|
|
||||||
returnRoute = "/mod/torrents/deleted"
|
returnRoute = "/mod/torrents/deleted"
|
||||||
} else {
|
} else {
|
||||||
_, _, err = torrent.Delete(false)
|
_, _, err = torrent.Delete(false)
|
||||||
|
|
||||||
//delete reports of torrent
|
|
||||||
query := &search.Query{}
|
|
||||||
query.Append("torrent_id", id)
|
|
||||||
reports, _, _ := reports.FindOrderBy(query, "", 0, 0)
|
|
||||||
for _, report := range reports {
|
|
||||||
report.Delete(false)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//delete reports of torrent
|
||||||
|
query := &search.Query{}
|
||||||
|
query.Append("torrent_id", id)
|
||||||
|
reports, _, _ := reports.FindOrderBy(query, "", 0, 0)
|
||||||
|
for _, report := range reports {
|
||||||
|
report.Delete()
|
||||||
|
}
|
||||||
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if torrent.Uploader == nil {
|
if torrent.Uploader == nil {
|
||||||
torrent.Uploader = &models.User{}
|
torrent.Uploader = &models.User{}
|
||||||
|
@ -176,7 +169,7 @@ func DeleteTagsModPanel(c *gin.Context) {
|
||||||
|
|
||||||
// TorrentBlockModPanel : Controller to lock torrents, redirecting to previous page
|
// TorrentBlockModPanel : Controller to lock torrents, redirecting to previous page
|
||||||
func TorrentBlockModPanel(c *gin.Context) {
|
func TorrentBlockModPanel(c *gin.Context) {
|
||||||
id, _ := strconv.ParseInt(c.Query("id"), 10, 32)
|
id, _ := strconv.ParseInt(c.PostForm("id"), 10, 32)
|
||||||
torrent, _, err := torrents.ToggleBlock(uint(id))
|
torrent, _, err := torrents.ToggleBlock(uint(id))
|
||||||
var returnRoute, action string
|
var returnRoute, action string
|
||||||
if torrent.IsDeleted() {
|
if torrent.IsDeleted() {
|
||||||
|
|
|
@ -21,7 +21,7 @@ func ReportTorrentHandler(c *gin.Context) {
|
||||||
messages := msg.GetMessages(c)
|
messages := msg.GetMessages(c)
|
||||||
captchaError := "?reported"
|
captchaError := "?reported"
|
||||||
currentUser := router.GetUser(c)
|
currentUser := router.GetUser(c)
|
||||||
if currentUser.NeedsCaptcha() {
|
if currentUser.ID == 0 {
|
||||||
userCaptcha := captcha.Extract(c)
|
userCaptcha := captcha.Extract(c)
|
||||||
if !captcha.Authenticate(userCaptcha) {
|
if !captcha.Authenticate(userCaptcha) {
|
||||||
captchaError = "?badcaptcha"
|
captchaError = "?badcaptcha"
|
||||||
|
@ -33,7 +33,11 @@ func ReportTorrentHandler(c *gin.Context) {
|
||||||
messages.Error(err)
|
messages.Error(err)
|
||||||
}
|
}
|
||||||
if !messages.HasErrors() {
|
if !messages.HasErrors() {
|
||||||
_, err := reports.Create(c.PostForm("report_type"), torrent, currentUser)
|
reportMessage := c.PostForm("report_message")
|
||||||
|
if len(reportMessage) > 60 {
|
||||||
|
reportMessage = reportMessage[0:60]
|
||||||
|
}
|
||||||
|
_, err := reports.Create(c.PostForm("report_type"), reportMessage, torrent, currentUser)
|
||||||
messages.AddInfoTf("infos", "report_msg", id)
|
messages.AddInfoTf("infos", "report_msg", id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
messages.ImportFromError("errors", err)
|
messages.ImportFromError("errors", err)
|
||||||
|
|
|
@ -42,7 +42,9 @@ func toggleThemeHandler(c *gin.Context) {
|
||||||
http.SetCookie(c.Writer, &http.Cookie{Name: "theme2", Value: theme, Domain: getDomainName(), Path: "/", Expires: timeHelper.FewDaysLater(365)})
|
http.SetCookie(c.Writer, &http.Cookie{Name: "theme2", Value: theme, Domain: getDomainName(), Path: "/", Expires: timeHelper.FewDaysLater(365)})
|
||||||
|
|
||||||
//Redirect user to page he was in beforehand
|
//Redirect user to page he was in beforehand
|
||||||
c.Redirect(http.StatusSeeOther, c.Param("redirect") + "#footer")
|
if c.Request.URL.Query()["no_redirect"] == nil {
|
||||||
|
c.Redirect(http.StatusSeeOther, c.Param("redirect") + "#footer")
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ func TorrentDeleteUserPanel(c *gin.Context) {
|
||||||
query.Append("torrent_id", id)
|
query.Append("torrent_id", id)
|
||||||
torrentReports, _, _ := reports.FindOrderBy(query, "", 0, 0)
|
torrentReports, _, _ := reports.FindOrderBy(query, "", 0, 0)
|
||||||
for _, report := range torrentReports {
|
for _, report := range torrentReports {
|
||||||
report.Delete(false)
|
report.Delete()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
c.Redirect(http.StatusSeeOther, "/?deleted")
|
c.Redirect(http.StatusSeeOther, "/?deleted")
|
||||||
|
|
|
@ -40,9 +40,9 @@ func ViewHandler(c *gin.Context) {
|
||||||
// Retrieve the torrent
|
// Retrieve the torrent
|
||||||
torrent, err := torrents.FindByID(uint(id))
|
torrent, err := torrents.FindByID(uint(id))
|
||||||
|
|
||||||
// If come from notification, toggle the notification as read
|
// Toggle the notifications related to this torrent as read
|
||||||
if c.Request.URL.Query()["notif"] != nil && user.ID > 0 {
|
if user.ID > 0 {
|
||||||
notifications.ToggleReadNotification(torrent.Identifier(), user.ID)
|
notifications.ToggleReadNotification(torrent.Identifier(), user)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If torrent not found, display 404
|
// If torrent not found, display 404
|
||||||
|
|
|
@ -15,7 +15,7 @@ func UserFollowHandler(c *gin.Context) {
|
||||||
id, _ := strconv.ParseUint(c.Param("id"), 10, 32)
|
id, _ := strconv.ParseUint(c.Param("id"), 10, 32)
|
||||||
currentUser := router.GetUser(c)
|
currentUser := router.GetUser(c)
|
||||||
user, _, errorUser := users.FindForAdmin(uint(id))
|
user, _, errorUser := users.FindForAdmin(uint(id))
|
||||||
if errorUser == nil && user.ID > 0 {
|
if errorUser == nil && user.ID > 0 && currentUser.ID > 0 && user.ID != currentUser.ID {
|
||||||
if !currentUser.IsFollower(uint(id)) {
|
if !currentUser.IsFollower(uint(id)) {
|
||||||
followAction = "followed"
|
followAction = "followed"
|
||||||
currentUser.SetFollow(user)
|
currentUser.SetFollow(user)
|
||||||
|
@ -28,5 +28,8 @@ func UserFollowHandler(c *gin.Context) {
|
||||||
if c.Query("id") != "" {
|
if c.Query("id") != "" {
|
||||||
url = "/view/" + c.Query("id") + "?" + followAction
|
url = "/view/" + c.Query("id") + "?" + followAction
|
||||||
}
|
}
|
||||||
|
if currentUser.ID == 0 {
|
||||||
|
url = "/login"
|
||||||
|
}
|
||||||
c.Redirect(http.StatusSeeOther, url)
|
c.Redirect(http.StatusSeeOther, url)
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,6 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/NyaaPantsu/nyaa/controllers/router"
|
"github.com/NyaaPantsu/nyaa/controllers/router"
|
||||||
"github.com/NyaaPantsu/nyaa/models"
|
|
||||||
"github.com/NyaaPantsu/nyaa/models/notifications"
|
"github.com/NyaaPantsu/nyaa/models/notifications"
|
||||||
"github.com/NyaaPantsu/nyaa/models/users"
|
"github.com/NyaaPantsu/nyaa/models/users"
|
||||||
"github.com/NyaaPantsu/nyaa/templates"
|
"github.com/NyaaPantsu/nyaa/templates"
|
||||||
|
@ -190,9 +189,13 @@ func UserProfileFormHandler(c *gin.Context) {
|
||||||
validator.ValidateForm(&userForm, messages)
|
validator.ValidateForm(&userForm, messages)
|
||||||
if !messages.HasErrors() {
|
if !messages.HasErrors() {
|
||||||
if userForm.Email != userProfile.Email {
|
if userForm.Email != userProfile.Email {
|
||||||
email.SendVerificationToUser(currentUser, userForm.Email)
|
if currentUser.HasAdmin() {
|
||||||
messages.AddInfoTf("infos", "email_changed", userForm.Email)
|
userProfile.Email = userForm.Email
|
||||||
userForm.Email = userProfile.Email // reset, it will be set when user clicks verification
|
} else {
|
||||||
|
email.SendVerificationToUser(currentUser, userForm.Email)
|
||||||
|
messages.AddInfoTf("infos", "email_changed", userForm.Email)
|
||||||
|
userForm.Email = userProfile.Email // reset, it will be set when user clicks verification
|
||||||
|
}
|
||||||
}
|
}
|
||||||
user, _, err := users.UpdateFromRequest(c, &userForm, &userSettingsForm, currentUser, uint(id))
|
user, _, err := users.UpdateFromRequest(c, &userForm, &userSettingsForm, currentUser, uint(id))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -204,6 +207,7 @@ func UserProfileFormHandler(c *gin.Context) {
|
||||||
}
|
}
|
||||||
if !messages.HasErrors() {
|
if !messages.HasErrors() {
|
||||||
messages.AddInfoT("infos", "profile_updated")
|
messages.AddInfoT("infos", "profile_updated")
|
||||||
|
userProfile = user
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -215,11 +219,13 @@ func UserProfileFormHandler(c *gin.Context) {
|
||||||
func UserNotificationsHandler(c *gin.Context) {
|
func UserNotificationsHandler(c *gin.Context) {
|
||||||
currentUser := router.GetUser(c)
|
currentUser := router.GetUser(c)
|
||||||
if currentUser.ID > 0 {
|
if currentUser.ID > 0 {
|
||||||
messages := msg.GetMessages(c)
|
|
||||||
if c.Request.URL.Query()["clear"] != nil {
|
if c.Request.URL.Query()["clear"] != nil {
|
||||||
notifications.DeleteAllNotifications(currentUser.ID)
|
notifications.DeleteNotifications(currentUser, false)
|
||||||
messages.AddInfoT("infos", "notifications_cleared")
|
|
||||||
currentUser.Notifications = []models.Notification{}
|
} else if c.Request.URL.Query()["clear_all"] != nil {
|
||||||
|
notifications.DeleteNotifications(currentUser, true)
|
||||||
|
} else if c.Request.URL.Query()["read_all"] != nil {
|
||||||
|
notifications.MarkAllNotificationsAsRead(currentUser)
|
||||||
}
|
}
|
||||||
templates.UserProfileNotifications(c, currentUser)
|
templates.UserProfileNotifications(c, currentUser)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -12,6 +12,9 @@ import (
|
||||||
// When a new comment is added this is called
|
// When a new comment is added this is called
|
||||||
func NewCommentEvent(comment *models.Comment, torrent *models.Torrent) {
|
func NewCommentEvent(comment *models.Comment, torrent *models.Torrent) {
|
||||||
comment.Torrent = torrent
|
comment.Torrent = torrent
|
||||||
|
if comment.UserID == torrent.UploaderID {
|
||||||
|
return
|
||||||
|
}
|
||||||
url := "/view/" + strconv.FormatUint(uint64(torrent.ID), 10)
|
url := "/view/" + strconv.FormatUint(uint64(torrent.ID), 10)
|
||||||
if torrent.UploaderID > 0 {
|
if torrent.UploaderID > 0 {
|
||||||
torrent.Uploader.ParseSettings()
|
torrent.Uploader.ParseSettings()
|
||||||
|
|
|
@ -15,13 +15,14 @@ type Notification struct {
|
||||||
Identifier string
|
Identifier string
|
||||||
URL string
|
URL string
|
||||||
Expire time.Time
|
Expire time.Time
|
||||||
|
Date time.Time
|
||||||
UserID uint
|
UserID uint
|
||||||
// User *User `gorm:"AssociationForeignKey:UserID;ForeignKey:user_id"` // Don't think that we need it here
|
// User *User `gorm:"AssociationForeignKey:UserID;ForeignKey:user_id"` // Don't think that we need it here
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewNotification : Create a new notification
|
// NewNotification : Create a new notification
|
||||||
func NewNotification(identifier string, c string, url string) Notification {
|
func NewNotification(identifier string, c string, url string) Notification {
|
||||||
return Notification{Identifier: identifier, Content: c, URL: url}
|
return Notification{Identifier: identifier, Content: c, URL: url, Date: time.Now()}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TableName : Return the name of notification table
|
// TableName : Return the name of notification table
|
||||||
|
|
|
@ -18,11 +18,38 @@ func NotifyUser(user *models.User, name string, msg string, url string, email bo
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToggleReadNotification : Make a notification as read according to its identifier
|
// ToggleReadNotification : Make a notification as read according to its identifier
|
||||||
func ToggleReadNotification(identifier string, id uint) { //
|
func ToggleReadNotification(identifier string, user *models.User) { //
|
||||||
models.ORM.Model(&models.Notification{}).Where("identifier = ? AND user_id = ?", identifier, id).Updates(models.Notification{Read: true})
|
models.ORM.Model(&models.Notification{}).Where("identifier = ? AND user_id = ?", identifier, user.ID).Updates(models.Notification{Read: true})
|
||||||
|
for i, notif := range user.Notifications {
|
||||||
|
if notif.Identifier == identifier {
|
||||||
|
user.Notifications[i].Read = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Need to update both DB and variable, otherwise when the function is called the user still needs to do an additional refresh to see the notification gone/read
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteAllNotifications : Erase notifications from a user
|
// MarkAllNotificationsAsRead : Force every notification as read
|
||||||
func DeleteAllNotifications(id uint) { //
|
func MarkAllNotificationsAsRead(user *models.User) { //
|
||||||
models.ORM.Where("user_id = ?", id).Delete(&models.Notification{})
|
models.ORM.Model(&models.Notification{}).Where("user_id = ?", user.ID).Updates(models.Notification{Read: true})
|
||||||
|
for i := range user.Notifications {
|
||||||
|
user.Notifications[i].Read = true
|
||||||
|
}
|
||||||
|
//Need to update both DB and variable, otherwise when the function is called the user still needs to do an additional refresh to see the notification gone/read
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteNotifications : Erase notifications from a user
|
||||||
|
func DeleteNotifications(user *models.User, all bool) { //
|
||||||
|
if all {
|
||||||
|
models.ORM.Where("user_id = ?", user.ID).Delete(&models.Notification{})
|
||||||
|
user.Notifications = []models.Notification{}
|
||||||
|
} else {
|
||||||
|
models.ORM.Where("user_id = ? AND read = ?", user.ID, true).Delete(&models.Notification{})
|
||||||
|
NewNotifications := []models.Notification{}
|
||||||
|
for _, notif := range user.Notifications {
|
||||||
|
if !notif.Read {
|
||||||
|
NewNotifications = append(NewNotifications, notif)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
user.Notifications = NewNotifications
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,8 +27,8 @@ func NotifyAll(msg string, expire time.Time) (*models.Notification, error) {
|
||||||
// UpdateAnnouncement updates an announcement
|
// UpdateAnnouncement updates an announcement
|
||||||
func UpdateAnnouncement(announcement *models.Notification, form *announcementValidator.CreateForm) error {
|
func UpdateAnnouncement(announcement *models.Notification, form *announcementValidator.CreateForm) error {
|
||||||
announcement.Content = form.Message
|
announcement.Content = form.Message
|
||||||
if form.Delay > 0 {
|
if form.Duration > 0 {
|
||||||
announcement.Expire = time.Now().AddDate(0, 0, form.Delay)
|
announcement.Expire = time.Now().Add(time.Hour * time.Duration(form.Duration))
|
||||||
}
|
}
|
||||||
if models.ORM.Model(announcement).UpdateColumn(announcement).Error != nil {
|
if models.ORM.Model(announcement).UpdateColumn(announcement).Error != nil {
|
||||||
return errors.New("Announcement was not updated")
|
return errors.New("Announcement was not updated")
|
||||||
|
|
|
@ -11,8 +11,9 @@ import (
|
||||||
// User can be null (anonymous reports)
|
// User can be null (anonymous reports)
|
||||||
// FIXME can't preload field Torrents for models.TorrentReport
|
// FIXME can't preload field Torrents for models.TorrentReport
|
||||||
type TorrentReport struct {
|
type TorrentReport struct {
|
||||||
ID uint `gorm:"column:torrent_report_id;primary_key"`
|
ID uint `gorm:"column:torrent_report_id;primary_key"`
|
||||||
Description string `gorm:"column:type"`
|
Description string `gorm:"column:type"`
|
||||||
|
Message string `gorm:"column:message"`
|
||||||
TorrentID uint `gorm:"column:torrent_id"`
|
TorrentID uint `gorm:"column:torrent_id"`
|
||||||
UserID uint `gorm:"column:user_id"`
|
UserID uint `gorm:"column:user_id"`
|
||||||
|
|
||||||
|
@ -31,6 +32,7 @@ func (report TorrentReport) TableName() string {
|
||||||
type TorrentReportJSON struct {
|
type TorrentReportJSON struct {
|
||||||
ID uint `json:"id"`
|
ID uint `json:"id"`
|
||||||
Description string `json:"description"`
|
Description string `json:"description"`
|
||||||
|
Message string `json:"message"`
|
||||||
Torrent TorrentJSON `json:"torrent"`
|
Torrent TorrentJSON `json:"torrent"`
|
||||||
User UserJSON `json:"user"`
|
User UserJSON `json:"user"`
|
||||||
}
|
}
|
||||||
|
@ -45,7 +47,7 @@ func (report *TorrentReport) ToJSON() TorrentReportJSON {
|
||||||
if report.User != nil {
|
if report.User != nil {
|
||||||
u = report.User.ToJSON()
|
u = report.User.ToJSON()
|
||||||
}
|
}
|
||||||
json := TorrentReportJSON{report.ID, report.Description, t, u}
|
json := TorrentReportJSON{report.ID, report.Description, report.Message, t, u}
|
||||||
return json
|
return json
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,9 +61,6 @@ func TorrentReportsToJSON(reports []TorrentReport) []TorrentReportJSON {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete : Delete torrent report
|
// Delete : Delete torrent report
|
||||||
func (report *TorrentReport) Delete(definitely bool) (int, error) {
|
func (report *TorrentReport) Delete() (int, error) {
|
||||||
if definitely {
|
return http.StatusOK, ORM.Unscoped().Delete(report).Error
|
||||||
return 0, ORM.Unscoped().Delete(report).Error
|
|
||||||
}
|
|
||||||
return http.StatusOK, nil
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,9 +7,10 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Create(desc string, torrent *models.Torrent, user *models.User) (*models.TorrentReport, error) {
|
func Create(desc string, message string, torrent *models.Torrent, user *models.User) (*models.TorrentReport, error) {
|
||||||
report := &models.TorrentReport{
|
report := &models.TorrentReport{
|
||||||
Description: desc,
|
Description: desc,
|
||||||
|
Message: message,
|
||||||
TorrentID: torrent.ID,
|
TorrentID: torrent.ID,
|
||||||
UserID: user.ID,
|
UserID: user.ID,
|
||||||
CreatedAt: time.Now(),
|
CreatedAt: time.Now(),
|
||||||
|
|
|
@ -20,31 +20,22 @@ type Query interface {
|
||||||
Prepend(string, ...interface{})
|
Prepend(string, ...interface{})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete : Delete a torrent report by id
|
|
||||||
func Delete(id uint) (*models.TorrentReport, int, error) {
|
func Delete(id uint) (*models.TorrentReport, int, error) {
|
||||||
return delete(id, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteDefinitely : Delete definitely a torrent report by id
|
|
||||||
func DeleteDefinitely(id uint) (*models.TorrentReport, int, error) {
|
|
||||||
return delete(id, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
func delete(id uint, definitely bool) (*models.TorrentReport, int, error) {
|
|
||||||
var torrentReport models.TorrentReport
|
var torrentReport models.TorrentReport
|
||||||
db := models.ORM
|
db := models.ORM.Unscoped()
|
||||||
if definitely {
|
|
||||||
db = models.ORM.Unscoped()
|
|
||||||
}
|
|
||||||
if db.First(&torrentReport, id).RecordNotFound() {
|
if db.First(&torrentReport, id).RecordNotFound() {
|
||||||
return &torrentReport, http.StatusNotFound, errors.New("try_to_delete_report_inexistant")
|
return &torrentReport, http.StatusNotFound, errors.New("try_to_delete_report_inexistant")
|
||||||
}
|
}
|
||||||
if _, err := torrentReport.Delete(false); err != nil {
|
if _, err := torrentReport.Delete(); err != nil {
|
||||||
return &torrentReport, http.StatusInternalServerError, err
|
return &torrentReport, http.StatusInternalServerError, err
|
||||||
}
|
}
|
||||||
return &torrentReport, http.StatusOK, nil
|
return &torrentReport, http.StatusOK, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func DeleteAll() {
|
||||||
|
models.ORM.Delete(&models.TorrentReport{})
|
||||||
|
}
|
||||||
|
|
||||||
func findOrderBy(parameters Query, orderBy string, limit int, offset int, countAll bool) (
|
func findOrderBy(parameters Query, orderBy string, limit int, offset int, countAll bool) (
|
||||||
torrentReports []models.TorrentReport, count int, err error,
|
torrentReports []models.TorrentReport, count int, err error,
|
||||||
) {
|
) {
|
||||||
|
|
|
@ -216,6 +216,14 @@ func (t *Torrent) ParseTrackers(trackers []string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
tempTrackers := []string{}
|
||||||
|
for _, line := range trackers {
|
||||||
|
if !contains(tempTrackers, line) {
|
||||||
|
tempTrackers = append(tempTrackers, line)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
trackers = tempTrackers
|
||||||
|
|
||||||
v["tr"] = trackers
|
v["tr"] = trackers
|
||||||
t.Trackers = v.Encode()
|
t.Trackers = v.Encode()
|
||||||
}
|
}
|
||||||
|
@ -517,3 +525,12 @@ func (t *Torrent) DeleteTags() {
|
||||||
log.CheckErrorWithMessage(err, "LOAD_TAGS_ERROR: Couldn't delete tags!")
|
log.CheckErrorWithMessage(err, "LOAD_TAGS_ERROR: Couldn't delete tags!")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func contains(s []string, e string) bool {
|
||||||
|
for _, a := range s {
|
||||||
|
if a == e {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
|
@ -252,7 +252,7 @@ select.form-input {
|
||||||
|
|
||||||
.not-important {
|
.not-important {
|
||||||
font-size: 9pt;
|
font-size: 9pt;
|
||||||
margin: 2px 3px;
|
margin: 0 3px 2px 3px;
|
||||||
color: #8a8a8a;
|
color: #8a8a8a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -346,10 +346,11 @@ select.form-input {
|
||||||
color: #292929;
|
color: #292929;
|
||||||
background: #fd6b6b;
|
background: #fd6b6b;
|
||||||
padding: 1px 4px;
|
padding: 1px 4px;
|
||||||
border-radius: 7px;
|
font-size: 8px;
|
||||||
font-size: 10px;
|
|
||||||
top: 37px;
|
top: 37px;
|
||||||
right: 19px;
|
right: 22px;
|
||||||
|
max-height: 17px;
|
||||||
|
line-height: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#content {
|
#content {
|
||||||
|
@ -662,6 +663,9 @@ th {
|
||||||
.website-nav table {
|
.website-nav table {
|
||||||
width: auto;
|
width: auto;
|
||||||
}
|
}
|
||||||
|
.website-nav table tr {
|
||||||
|
background: none!important;
|
||||||
|
}
|
||||||
.website-nav #nav-category-list {
|
.website-nav #nav-category-list {
|
||||||
width: 70%;
|
width: 70%;
|
||||||
margin-bottom: 7px;
|
margin-bottom: 7px;
|
||||||
|
@ -758,6 +762,9 @@ html, body {
|
||||||
.header .h-user>a.nav-btn {
|
.header .h-user>a.nav-btn {
|
||||||
padding: 0!important;
|
padding: 0!important;
|
||||||
}
|
}
|
||||||
|
.user-avatar span {
|
||||||
|
right: 25px;
|
||||||
|
}
|
||||||
.nav-btn.log-in span {
|
.nav-btn.log-in span {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
@ -901,6 +908,9 @@ html, body {
|
||||||
.header .h-user .user-avatar {
|
.header .h-user .user-avatar {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
.user-avatar span {
|
||||||
|
right: 20px;
|
||||||
|
}
|
||||||
.header .h-user {
|
.header .h-user {
|
||||||
max-width: 46px;
|
max-width: 46px;
|
||||||
width: auto;
|
width: auto;
|
||||||
|
@ -944,7 +954,9 @@ html, body {
|
||||||
.header .h-user .nav-btn {
|
.header .h-user .nav-btn {
|
||||||
height: 57px;
|
height: 57px;
|
||||||
}
|
}
|
||||||
|
.user-avatar span {
|
||||||
|
right: 14px;
|
||||||
|
}
|
||||||
h3 {
|
h3 {
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
}
|
}
|
||||||
|
@ -1062,8 +1074,7 @@ html, body {
|
||||||
margin-bottom: 2px;
|
margin-bottom: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.profile-usertitle-uploadcount span {
|
.profile-usertitle-uploadcount b {
|
||||||
font-weight: bold;
|
|
||||||
margin-left: 2px;
|
margin-left: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1182,7 +1193,7 @@ html, body {
|
||||||
.comment-box {
|
.comment-box {
|
||||||
padding: 0 7px;
|
padding: 0 7px;
|
||||||
margin: 10px 30px 0 30px;
|
margin: 10px 30px 0 30px;
|
||||||
min-height: 70px;
|
min-height: 67px;
|
||||||
word-break: break-word;
|
word-break: break-word;
|
||||||
text-align: justify;
|
text-align: justify;
|
||||||
}
|
}
|
||||||
|
@ -1191,11 +1202,16 @@ html, body {
|
||||||
margin-top: 9px;
|
margin-top: 9px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.comment-box .comment-user {
|
.comment-box .comment-userinfo {
|
||||||
font-size: 12px;
|
display: block;
|
||||||
|
margin-top: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.comment-box span+p img {
|
.comment-box .comment-user {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.comment-userinfo img {
|
||||||
width: 50px;
|
width: 50px;
|
||||||
height: 50px;
|
height: 50px;
|
||||||
float: left;
|
float: left;
|
||||||
|
@ -1215,6 +1231,11 @@ html, body {
|
||||||
margin-left: 4px;
|
margin-left: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.comment-content {
|
||||||
|
max-width: 100%;
|
||||||
|
max-height: 500px;
|
||||||
|
}
|
||||||
|
|
||||||
.comment-content :last-child {
|
.comment-content :last-child {
|
||||||
margin-bottom: 2px;
|
margin-bottom: 2px;
|
||||||
}
|
}
|
||||||
|
@ -1226,8 +1247,12 @@ html, body {
|
||||||
padding-bottom: 5px;
|
padding-bottom: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.comment-form textarea {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.comment-form h3 {
|
.comment-form h3 {
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.comment-index {
|
.comment-index {
|
||||||
|
@ -1276,7 +1301,7 @@ div.profile-content.box>nav>ul>a>li {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.profile-content.box>nav>ul>a>li, nav.adminNav>ul>li {
|
div.profile-content.box>nav>ul>a>li {
|
||||||
border-right-width: 1px;
|
border-right-width: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1538,7 +1563,9 @@ input.filelist-checkbox:checked+table.table-filelist {
|
||||||
.modal-body :first-child {
|
.modal-body :first-child {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
.modal-body h4 {
|
||||||
|
margin-bottom: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
/* Modal Footer */
|
/* Modal Footer */
|
||||||
|
|
||||||
|
@ -1560,7 +1587,7 @@ input.filelist-checkbox:checked+table.table-filelist {
|
||||||
margin-top: 7px;
|
margin-top: 7px;
|
||||||
padding: 0.7em 1.5em;
|
padding: 0.7em 1.5em;
|
||||||
background: none;
|
background: none;
|
||||||
border: 1px solid white;
|
border: 1px solid black;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
color: white;
|
color: white;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
@ -1757,11 +1784,11 @@ input.filelist-checkbox:checked+table.table-filelist {
|
||||||
padding: 0 10px 10px;
|
padding: 0 10px 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-blue:hover, .btn-red:hover, .btn-green:hover, .btn-orange:hover {
|
[class^="btn-"]:hover {
|
||||||
opacity: 0.7;
|
opacity: 0.7;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-blue, .btn-red, .btn-green, .btn-orange {
|
[class^="btn-"] {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
@ -2196,6 +2223,9 @@ iframe {
|
||||||
height: 36px;
|
height: 36px;
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
.adminNav {
|
||||||
|
margin: 12px 0 5px 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
table.multiple-upload {
|
table.multiple-upload {
|
||||||
|
@ -2299,6 +2329,11 @@ table.multiple-upload {
|
||||||
right: 16px;
|
right: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.user-search-notice {
|
||||||
|
margin: 10px 0 0 1px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
.torrent-info-row .tr-se span, .torrent-info-row .tr-le span, .torrent-info-row .tr-dl span {
|
.torrent-info-row .tr-se span, .torrent-info-row .tr-le span, .torrent-info-row .tr-dl span {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
background-color: #ffe0bf;
|
background-color: #ffe0bf;
|
||||||
|
@ -2348,6 +2383,61 @@ form.delete-form button.form-input.btn-red {
|
||||||
bottom: 9px;
|
bottom: 9px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#clear-notification {
|
||||||
|
bottom: 8px;
|
||||||
|
right: 8px;
|
||||||
|
position: absolute;
|
||||||
|
width: calc(100% - 16px);
|
||||||
|
}
|
||||||
|
#clear-notification a {
|
||||||
|
float: right;
|
||||||
|
margin-left: 3px;
|
||||||
|
}
|
||||||
|
.notification-table {
|
||||||
|
margin-bottom: 44px;
|
||||||
|
}
|
||||||
|
.notification-table td {
|
||||||
|
text-align: center;
|
||||||
|
padding: 6px 0;
|
||||||
|
border-bottom: 1px solid;
|
||||||
|
}
|
||||||
|
.notification-table tr:hover td {
|
||||||
|
filter: brightness(1.2);
|
||||||
|
}
|
||||||
|
.notification-status {
|
||||||
|
width: 140px;
|
||||||
|
}
|
||||||
|
.notification-event {
|
||||||
|
text-align: left!important;
|
||||||
|
padding: 6px 10px!important;
|
||||||
|
}
|
||||||
|
.notification-date {
|
||||||
|
width: 195px;
|
||||||
|
}
|
||||||
|
td.notification-status {
|
||||||
|
border: 1px solid black;
|
||||||
|
}
|
||||||
|
td.notification-status {
|
||||||
|
background-color: #e4e4e4;
|
||||||
|
}
|
||||||
|
td.notification-status.notification-unread {
|
||||||
|
background-color: rgb(161, 211, 253);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.torrent-report-table td, .torrent-report-table th {
|
||||||
|
width: 165px;
|
||||||
|
}
|
||||||
|
.td-report-message {
|
||||||
|
width: auto!important;
|
||||||
|
white-space: normal;
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
.locked {
|
||||||
|
background: hsla(216, 10%, 73%, 0.2) !important;
|
||||||
|
}
|
||||||
|
|
||||||
/* Language specific CSS */
|
/* Language specific CSS */
|
||||||
|
|
||||||
html[lang="ja-jp"] .form-refine span.spacing {
|
html[lang="ja-jp"] .form-refine span.spacing {
|
||||||
|
|
|
@ -26,7 +26,7 @@ body, .header {
|
||||||
font-family: Arial, sans-serif!important;
|
font-family: Arial, sans-serif!important;
|
||||||
}
|
}
|
||||||
.torrent-info-data {
|
.torrent-info-data {
|
||||||
width: 59%;
|
width: 52%;
|
||||||
}
|
}
|
||||||
#torrent-view-data {
|
#torrent-view-data {
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
|
@ -37,8 +37,8 @@ body, .header {
|
||||||
width: 87%;
|
width: 87%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.comment-box p:nth-child(2) {
|
.comment-userinfo {
|
||||||
margin-top: auto;
|
margin-top: 0!important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-refine span.spacing {
|
.form-refine span.spacing {
|
||||||
|
@ -54,7 +54,7 @@ body, .header {
|
||||||
|
|
||||||
#sort-list-order {
|
#sort-list-order {
|
||||||
width: auto;
|
width: auto;
|
||||||
margin-left: 4px;
|
margin-left: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
|
@ -63,12 +63,12 @@ a {
|
||||||
.sukebei a {
|
.sukebei a {
|
||||||
color: #660000;
|
color: #660000;
|
||||||
}
|
}
|
||||||
a:hover {
|
a:hover, .h-nav a:hover, .h-nav:active a:hover {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
.upload-form-table .checkbox-container+input {
|
.upload-form-table .checkbox-container+input {
|
||||||
width: 385px;
|
width: 385px;1
|
||||||
}
|
}
|
||||||
.upload-form-table .table-checkboxes {
|
.upload-form-table .table-checkboxes {
|
||||||
padding: 3px 0!important;
|
padding: 3px 0!important;
|
||||||
|
@ -95,7 +95,7 @@ th.tr-name a {
|
||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
}
|
}
|
||||||
.tr-links {
|
.tr-links {
|
||||||
width: 29px;
|
width: 22px;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
.tr-links .icon-magnet::before {
|
.tr-links .icon-magnet::before {
|
||||||
|
@ -158,7 +158,7 @@ th.tr-name a {
|
||||||
}
|
}
|
||||||
.header .container>div {
|
.header .container>div {
|
||||||
line-height: 40px;
|
line-height: 40px;
|
||||||
padding: 0 0.2rem;
|
padding: 0 0.4rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header .nav-btn {
|
.header .nav-btn {
|
||||||
|
@ -245,6 +245,8 @@ select.form-input {
|
||||||
}
|
}
|
||||||
.sukebei .pagination span:hover {
|
.sukebei .pagination span:hover {
|
||||||
background-color: #993333;
|
background-color: #993333;
|
||||||
|
color: white;
|
||||||
|
font-weight: normal;
|
||||||
}
|
}
|
||||||
.website-nav .pagination p {
|
.website-nav .pagination p {
|
||||||
display: none;
|
display: none;
|
||||||
|
@ -254,7 +256,7 @@ select.form-input {
|
||||||
padding-top: 4px!important;
|
padding-top: 4px!important;
|
||||||
}
|
}
|
||||||
.website-nav .pagination {
|
.website-nav .pagination {
|
||||||
padding: .5rem;
|
padding: .5rem 0 0rem 0;
|
||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
}
|
}
|
||||||
.website-nav .pagination a {
|
.website-nav .pagination a {
|
||||||
|
@ -327,7 +329,7 @@ span.comment-index+p {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
span.comment-index+p a {
|
.comment-user {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
padding-top: 2px;
|
padding-top: 2px;
|
||||||
font-size: .9em;
|
font-size: .9em;
|
||||||
|
@ -335,12 +337,11 @@ span.comment-index+p a {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
line-height: 22px;
|
line-height: 22px;
|
||||||
}
|
}
|
||||||
span.comment-index+p a:hover {
|
.comment-user:hover {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
.comment-index {
|
.comment-index {
|
||||||
margin: 3px 0 0 0;
|
margin: 1px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#solution {
|
#solution {
|
||||||
|
@ -382,6 +383,7 @@ span.comment-index+p a:hover {
|
||||||
|
|
||||||
#description-box {
|
#description-box {
|
||||||
font-size: 0.8em;
|
font-size: 0.8em;
|
||||||
|
border-radius: 5px;
|
||||||
}
|
}
|
||||||
.form-input {
|
.form-input {
|
||||||
border-color: #c4c4c4 !important;
|
border-color: #c4c4c4 !important;
|
||||||
|
@ -395,6 +397,11 @@ span.comment-index+p a:hover {
|
||||||
width: 24px;
|
width: 24px;
|
||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
}
|
}
|
||||||
|
.user-avatar span {
|
||||||
|
font-size: 8px;
|
||||||
|
top: 20px;
|
||||||
|
right: 9px;
|
||||||
|
}
|
||||||
|
|
||||||
.torrent-info-data.uploader-link {
|
.torrent-info-data.uploader-link {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
@ -402,13 +409,16 @@ span.comment-index+p a:hover {
|
||||||
.torrent-info-data.uploader-anon {
|
.torrent-info-data.uploader-anon {
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
}
|
}
|
||||||
.torrent-info-data.uploader-link a, .torrent-info-data.uploader-anon a{
|
.torrent-info-data.uploader-link a, .torrent-info-data.uploader-anon a, .user-search-notice a{
|
||||||
color: green;
|
color: green;
|
||||||
}
|
}
|
||||||
|
|
||||||
#torrent-description-hr {
|
#torrent-description-hr {
|
||||||
margin-top: 40px;
|
margin-top: 40px;
|
||||||
}
|
}
|
||||||
|
.torrent-hr {
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
.comment-submit h3 {
|
.comment-submit h3 {
|
||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
|
@ -451,7 +461,7 @@ span.comment-index+p a:hover {
|
||||||
float: left;
|
float: left;
|
||||||
}
|
}
|
||||||
.sukebei .torrent-buttons a, .sukebei .torrent-buttons button {
|
.sukebei .torrent-buttons a, .sukebei .torrent-buttons button {
|
||||||
background: linear-gradient(to bottom, #CA3346 5%, #482120 80%);
|
background: linear-gradient(to bottom, #CA3346 5%, #482120 80%);
|
||||||
}
|
}
|
||||||
.torrent-buttons a.hidden {
|
.torrent-buttons a.hidden {
|
||||||
opacity: 0.6!important;
|
opacity: 0.6!important;
|
||||||
|
@ -489,12 +499,17 @@ th {
|
||||||
td {
|
td {
|
||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
padding: 2px 0!important;
|
padding: 2px 0!important;
|
||||||
|
|
||||||
}
|
}
|
||||||
.results td {
|
.results td, .profile-content td {
|
||||||
border-bottom: 1px solid #666666!important;
|
border-bottom: 1px solid #666666!important;
|
||||||
border-top: 1px solid #666666!important;
|
border-top: 1px solid #666666!important;
|
||||||
}
|
}
|
||||||
|
.torrent-view-data {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
.torrent-view-data td {
|
||||||
|
padding: 1px 0!important;
|
||||||
|
}
|
||||||
td a {
|
td a {
|
||||||
color: #106655;
|
color: #106655;
|
||||||
}
|
}
|
||||||
|
@ -558,35 +573,39 @@ td.tr-size {
|
||||||
.container.bottom {
|
.container.bottom {
|
||||||
padding: 5px 10px;
|
padding: 5px 10px;
|
||||||
padding-top: 0;
|
padding-top: 0;
|
||||||
margin-top: -8px;
|
margin-top: -11px;
|
||||||
}
|
}
|
||||||
.container.bottom .pagination {
|
.container.bottom .pagination {
|
||||||
border-top: none;
|
border-top: none;
|
||||||
padding: 0;
|
padding: 0 14px;
|
||||||
}
|
}
|
||||||
.container.bottom .pagination p {
|
.container.bottom .pagination p {
|
||||||
margin: 4px 0 6px 0px;
|
margin: 2px 0 4px 0px
|
||||||
}
|
}
|
||||||
.bottom.center {
|
.bottom.center {
|
||||||
width: 87%;
|
width: 87%;
|
||||||
max-width: 1328px;
|
max-width: 1328px;
|
||||||
padding: 0 8px;
|
padding: 0 8px;
|
||||||
}
|
}
|
||||||
.content > .centered {
|
.content > .centered {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
#content > .centered {
|
#content > .centered {
|
||||||
width: 87%;
|
width: 87%;
|
||||||
max-width: 1328px;
|
max-width: 1328px;
|
||||||
padding: 0 8px;
|
padding: 0 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pagination .active, .pagination .active:hover {
|
.pagination .active, .pagination .active:hover {
|
||||||
background: #fbfbfb;
|
background: none!important;
|
||||||
font-weight: bold;
|
font-weight: bold!important;
|
||||||
border: none;
|
border: none;
|
||||||
color: #106655;
|
color: #106655;
|
||||||
|
cursor: text;
|
||||||
|
}
|
||||||
|
.sukebei .pagination .active, .pagination .active:hover {
|
||||||
|
color: #111111!important;
|
||||||
}
|
}
|
||||||
|
|
||||||
a.nav-btn.log-in {
|
a.nav-btn.log-in {
|
||||||
|
@ -713,3 +732,49 @@ span.tag {
|
||||||
.torrent-info-data #subscribe-link::before, .torrent-info-data #subscribe-link:: after {
|
.torrent-info-data #subscribe-link::before, .torrent-info-data #subscribe-link:: after {
|
||||||
color: #111111;
|
color: #111111;
|
||||||
}
|
}
|
||||||
|
.content > p:first-child+div.centered+div.refine+div #reportPopup {
|
||||||
|
top: 145px;
|
||||||
|
}
|
||||||
|
.content > p:first-child+div#announce+div.refine+div #reportPopup {
|
||||||
|
top: 110px;
|
||||||
|
}
|
||||||
|
.content > div#announce:first-child+div.refine+div #reportPopup {
|
||||||
|
top: 65px;
|
||||||
|
}
|
||||||
|
#reportPopup {
|
||||||
|
text-decoration: underline dotted;
|
||||||
|
height: 16px!important;
|
||||||
|
font-size: 13px!important;
|
||||||
|
background: none;
|
||||||
|
color: #106655!important;
|
||||||
|
position: absolute;
|
||||||
|
top: 103px;
|
||||||
|
right: 11px;
|
||||||
|
}
|
||||||
|
.comment-content :first-child {
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
.sukebei #reportPopup {
|
||||||
|
color: #660000!important;
|
||||||
|
}
|
||||||
|
#reportPopup:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
.modal-header {
|
||||||
|
background: linear-gradient(to bottom, #33ca98 0%, #337372 72%);
|
||||||
|
}
|
||||||
|
.sukebei .modal-header {
|
||||||
|
background: linear-gradient(to bottom, #c54f6a 5%, #482120 80%);
|
||||||
|
}
|
||||||
|
.modal-footer{
|
||||||
|
background: #26332e;
|
||||||
|
}
|
||||||
|
.sukebei .modal-footer {
|
||||||
|
background: #332626;
|
||||||
|
}
|
||||||
|
.user-search-notice {
|
||||||
|
margin: 9px 0 0 3px;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: bold;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -62,6 +62,7 @@ a:hover {
|
||||||
}
|
}
|
||||||
.user-avatar span {
|
.user-avatar span {
|
||||||
background-color: #d02727;
|
background-color: #d02727;
|
||||||
|
color: #272727;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header .h-user .user-menu {
|
.header .h-user .user-menu {
|
||||||
|
@ -102,6 +103,9 @@ td.tr-le, .error-text {
|
||||||
.sukebei .btn-red {
|
.sukebei .btn-red {
|
||||||
color: #c5c8c6;
|
color: #c5c8c6;
|
||||||
}
|
}
|
||||||
|
.btn-grey {
|
||||||
|
background-color: #777777;
|
||||||
|
}
|
||||||
|
|
||||||
.alt-colors tr:nth-child(even) {
|
.alt-colors tr:nth-child(even) {
|
||||||
background: hsla(244, 11%, 21%, 0.2);
|
background: hsla(244, 11%, 21%, 0.2);
|
||||||
|
@ -348,5 +352,13 @@ span.tag {
|
||||||
}
|
}
|
||||||
|
|
||||||
#subscribe-link::before, #subscribe-link::after {
|
#subscribe-link::before, #subscribe-link::after {
|
||||||
color: #c5c8c6;
|
color: #c5c8c6!important;
|
||||||
|
}
|
||||||
|
|
||||||
|
td.notification-status {
|
||||||
|
background-color: #505255;
|
||||||
|
}
|
||||||
|
td.notification-status.notification-unread {
|
||||||
|
background-color: rgba(144, 103, 24, 0.4);
|
||||||
|
color: #c5c8c6;
|
||||||
}
|
}
|
||||||
|
|
Fichier binaire non affiché.
Après Largeur: | Hauteur: | Taille: 14 KiB |
Fichier binaire non affiché.
Après Largeur: | Hauteur: | Taille: 4.5 KiB |
Fichier binaire non affiché.
Après Largeur: | Hauteur: | Taille: 18 KiB |
Fichier binaire non affiché.
Après Largeur: | Hauteur: | Taille: 4.7 KiB |
|
@ -219,7 +219,7 @@ function toggleTheme(e) {
|
||||||
document.getElementById("theme").href = "/css/themes/" + CurrentTheme + ".css";
|
document.getElementById("theme").href = "/css/themes/" + CurrentTheme + ".css";
|
||||||
|
|
||||||
if(UserID > 0 ){
|
if(UserID > 0 ){
|
||||||
Query.Get("/dark", function(data) {})
|
Query.Get("/dark?no_redirect", function(data) {})
|
||||||
//If user logged in, we're forced to go through this page in order to save the new user theme
|
//If user logged in, we're forced to go through this page in order to save the new user theme
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -11,11 +11,11 @@
|
||||||
{{ yield errors(name="Message")}}
|
{{ yield errors(name="Message")}}
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="delay">{{ T("delay")}} ({{ Form.Delay }} {{ T("days") }})</label>
|
<label for="duration">{{ T("duration")}})</label>
|
||||||
<input type="text" name="delay" id="delay" class="form-input up-input" placeholder="{{ T("delay")}}">
|
<input type="text" name="duration" id="duration" class="form-input up-input" value="1">
|
||||||
{{ yield errors(name="Delay")}}
|
{{ yield errors(name="Duration")}}
|
||||||
</div>
|
</div>
|
||||||
<button type="submit" class="form-input up-input btn-green">{{ T("save_changes")}}</button>
|
<button type="submit" class="form-input up-input btn-green">{{ T("save_changes")}}</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
<td class="tr-size home-td">
|
<td class="tr-size home-td">
|
||||||
<form method="POST" action="/mod/torrent/delete">
|
<form method="POST" action="/mod/torrent/delete">
|
||||||
<input type="hidden" name="id" value="{{ .ID }}">
|
<input type="hidden" name="id" value="{{ .ID }}">
|
||||||
<button type="submit" class="form-input btn-red" onclick="if (!confirm('{{ T(" are_you_sure ") }}')) return false;"><i class="icon-trash"></i> {{ T("delete") }}</button>
|
<button type="submit" class="form-input btn-red" onclick="if (!confirm('{{ T("are_you_sure") }}')) return false;"><i class="icon-trash"></i> {{ T("delete") }}</button>
|
||||||
</form>
|
</form>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -33,19 +33,19 @@
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<nav class="adminNav" aria-label="Page navigation">
|
<nav class="adminNav" aria-label="Page navigation">
|
||||||
<ul class="pagination">
|
<a href="/mod/torrents">{{T("more")}}</a></li>
|
||||||
<li><a href="/mod/torrents">{{T("more")}}</a></li>
|
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
<hr />
|
<hr />
|
||||||
|
|
||||||
<h3 id="torrents">{{ T("last_reports") }}</h3>
|
<h3 id="torrents">{{ T("last_reports") }}</h3>
|
||||||
<table class="table">
|
<table class="torrent-report-table">
|
||||||
<thead class="torrent-info">
|
<thead class="torrent-info">
|
||||||
<tr>
|
<tr>
|
||||||
<th class="tr-name">{{ T("name") }}</th>
|
<th class="tr-name">{{ T("name") }}</th>
|
||||||
<th class="tr-actions">{{ T("username") }}</th>
|
<th class="tr-actions">{{ T("username") }}</th>
|
||||||
<th class="tr-actions">{{ T("reason") }}</th>
|
<th class="tr-actions">{{ T("reason") }}</th>
|
||||||
|
<th class="td-report-message">{{ T("message") }}</th>
|
||||||
<th class="tr-actions">{{ T("actions") }}</th>
|
<th class="tr-actions">{{ T("actions") }}</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
@ -58,6 +58,7 @@
|
||||||
</td>
|
</td>
|
||||||
<td class="tr-size home-td">{{.User.Username}}</td>
|
<td class="tr-size home-td">{{.User.Username}}</td>
|
||||||
<td class="tr-actions home-td">{{ getReportDescription(.Description,T) }}</td>
|
<td class="tr-actions home-td">{{ getReportDescription(.Description,T) }}</td>
|
||||||
|
<td class="td-report-message home-td">{{.Message}}</td>
|
||||||
<td class="tr-actions home-td">
|
<td class="tr-actions home-td">
|
||||||
<form method="POST" action="/mod/report/delete" >
|
<form method="POST" action="/mod/report/delete" >
|
||||||
<input type="hidden" name="id" value="{{ .ID }}">
|
<input type="hidden" name="id" value="{{ .ID }}">
|
||||||
|
@ -69,9 +70,7 @@
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<nav class="adminNav" aria-label="Page navigation">
|
<nav class="adminNav" aria-label="Page navigation">
|
||||||
<ul class="pagination">
|
<a href="/mod/reports">{{ T("more") }}</a>
|
||||||
<li><a href="/mod/reports">{{ T("more") }}</a></li>
|
|
||||||
</ul>
|
|
||||||
</nav>
|
</nav>
|
||||||
<hr />
|
<hr />
|
||||||
<h3 id="users">{{ T("last_users") }}</h3>
|
<h3 id="users">{{ T("last_users") }}</h3>
|
||||||
|
@ -91,7 +90,7 @@
|
||||||
<td class="tr-size home-td">{{if .ID > 0}}
|
<td class="tr-size home-td">{{if .ID > 0}}
|
||||||
<form method="POST" action="/user/{{.ID}}/{{.Username }}/delete" >
|
<form method="POST" action="/user/{{.ID}}/{{.Username }}/delete" >
|
||||||
{{ yield csrf_field()}}
|
{{ yield csrf_field()}}
|
||||||
<button type="submit" class="form-input btn-red" onclick="if (!confirm('{{ T(" are_you_sure ") }}')) return false;"><i class="icon-trash"></i> {{ T("delete") }}</button>
|
<button type="submit" class="form-input btn-red" onclick="if (!confirm('{{ T("are_you_sure") }}')) return false;"><i class="icon-trash"></i> {{ T("delete") }}</button>
|
||||||
</form>
|
</form>
|
||||||
{{end}}
|
{{end}}
|
||||||
</td>
|
</td>
|
||||||
|
@ -100,8 +99,7 @@
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<nav class="adminNav" aria-label="Page navigation">
|
<nav class="adminNav" aria-label="Page navigation">
|
||||||
<ul class="pagination">
|
<a href="/mod/users">{{ T("more") }} </a></li>
|
||||||
<li><a href="/mod/users">{{ T("more") }} </a></li>
|
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
<hr />
|
<hr />
|
||||||
|
@ -136,8 +134,7 @@
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<nav class="adminNav" aria-label="Page navigation">
|
<nav class="adminNav" aria-label="Page navigation">
|
||||||
<ul class="pagination">
|
<a href="/mod/comments">{{ T("more") }}</a></li>
|
||||||
<li><a href="/mod/comments">{{ T("more") }}</a></li>
|
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -3,12 +3,13 @@
|
||||||
{{ block content_body()}}
|
{{ block content_body()}}
|
||||||
<div class="results box">
|
<div class="results box">
|
||||||
<h1>{{ T("reports_list") }}</h1>
|
<h1>{{ T("reports_list") }}</h1>
|
||||||
<table class="table">
|
<table class="torrent-report-table">
|
||||||
<thead class="torrent-info">
|
<thead class="torrent-info">
|
||||||
<tr>
|
<tr>
|
||||||
<th class="tr-name">{{ T("name") }}</th>
|
<th class="tr-name">{{ T("name") }}</th>
|
||||||
<th class="tr-actions">{{ T("username") }}</th>
|
<th class="tr-actions">{{ T("username") }}</th>
|
||||||
<th class="tr-actions">{{ T("reason") }}</th>
|
<th class="tr-actions">{{ T("reason") }}</th>
|
||||||
|
<th class="td-report-message">{{ T("message") }}</th>
|
||||||
<th class="tr-actions">{{ T("actions") }}</th>
|
<th class="tr-actions">{{ T("actions") }}</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
@ -21,10 +22,11 @@
|
||||||
</td>
|
</td>
|
||||||
<td class="tr-size home-td">{{.User.Username}}</td>
|
<td class="tr-size home-td">{{.User.Username}}</td>
|
||||||
<td class="tr-actions home-td">{{ getReportDescription(.Description, T) }}</td>
|
<td class="tr-actions home-td">{{ getReportDescription(.Description, T) }}</td>
|
||||||
|
<td class="td-report-message home-td">{{.Message}}</td>
|
||||||
<td class="tr-actions home-td">
|
<td class="tr-actions home-td">
|
||||||
<form method="POST" action="/mod/torrent/delete">
|
<form method="POST" action="/mod/torrent/delete">
|
||||||
<input type="hidden" name="id" value="{{ .Torrent }}">
|
<input type="hidden" name="id" value="{{ .Torrent }}">
|
||||||
<button type="submit" class="form-input btn-red" onclick="if (!confirm('{{ T(" are_you_sure ") }}')) return false;"><i class="icon-trash"></i> {{ T("delete_torrent") }}</button>
|
<button type="submit" class="form-input btn-red" onclick="if (!confirm('{{ T("are_you_sure") }}')) return false;"><i class="icon-trash"></i> {{ T("delete_torrent") }}</button>
|
||||||
</form>
|
</form>
|
||||||
<form method="POST" action="/mod/report/delete">
|
<form method="POST" action="/mod/report/delete">
|
||||||
<input type="hidden" name="id" value="{{ .ID }}">
|
<input type="hidden" name="id" value="{{ .ID }}">
|
||||||
|
@ -35,5 +37,9 @@
|
||||||
{{end}}
|
{{end}}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
<hr/>
|
||||||
|
<form method="POST" action="/mod/report/delete?all">
|
||||||
|
<button type="submit" class="form-input btn-red" style="margin-bottom: 5px;"><i class="icon-attention"></i> {{ T("delete_all_reports") }}</button>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
|
@ -54,18 +54,15 @@
|
||||||
{{ .Uploader.Username }}
|
{{ .Uploader.Username }}
|
||||||
</a> {{ else }}れんちょん{{end}}
|
</a> {{ else }}れんちょん{{end}}
|
||||||
</td>
|
</td>
|
||||||
<td class="tr-actions home-td">
|
<td class="tr-actions home-td"> <form></form>
|
||||||
<a href="/torrent/block?id={{ .ID }}" class="form-input btn-orange" onclick="if (!confirm('{{ T(" are_you_sure ")}}')) return false;">
|
<form method="POST" action="/mod/torrent/block" class="delete-form">
|
||||||
{{ if .IsBlocked }}
|
<input type="hidden" name="id" value="{{ .ID }}">
|
||||||
{{ T("torrent_unblock") }}
|
<button type="submit" class="form-input btn-orange" onclick="if (!confirm('{{ T("are_you_sure") }}')) return false;"><i class="icon-trash"></i>{{ if .IsBlocked }}{{ T("torrent_unblock") }}{{else}}{{ T("torrent_block") }}{{end}}</button>
|
||||||
{{else}}
|
</form>
|
||||||
{{ T("torrent_block") }}
|
|
||||||
{{end}}
|
|
||||||
</a>
|
|
||||||
<form method="POST" action="/mod/torrent/delete" class="delete-form">
|
<form method="POST" action="/mod/torrent/delete" class="delete-form">
|
||||||
<input type="hidden" name="id" value="{{ .ID }}">
|
<input type="hidden" name="id" value="{{ .ID }}">
|
||||||
{{ if .IsDeleted }}<input type="hidden" name="definitely" value="true">{{ end }}
|
{{ if .IsDeleted }}<input type="hidden" name="definitely" value="true">{{ end }}
|
||||||
<button type="submit" class="form-input btn-red" onclick="if (!confirm('{{ T(" are_you_sure ") }} {{ if !.IsDeleted }}{{ T("delete") }}{{else}}{{ T("delete_definitely_torrent_warning ")}}{{end}}')) return false;"><i class="icon-trash"></i>{{ if .IsDeleted }}{{ T("delete_definitely") }}{{else}}{{ T("delete") }}{{end}}</button>
|
<button type="submit" class="form-input btn-red" onclick="if (!confirm('{{ T("are_you_sure") }} {{ if !.IsDeleted }}{{ T("delete") }}{{else}}{{ T("delete_definitely_torrent_warning ")}}{{end}}')) return false;"><i class="icon-trash"></i>{{ if .IsDeleted }}{{ T("delete_definitely") }}{{else}}{{ T("delete") }}{{end}}</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
{{if .ID > 0}}
|
{{if .ID > 0}}
|
||||||
<form method="POST" action="/user/{{.ID}}/{{.Username }}/delete">
|
<form method="POST" action="/user/{{.ID}}/{{.Username }}/delete">
|
||||||
{{ yield csrf_field()}}
|
{{ yield csrf_field()}}
|
||||||
<button type="submit" class="form-input btn-red" onclick="if (!confirm('{{ T(" are_you_sure ") }}')) return false;"><i class="icon-trash"></i> {{ T("delete") }}</button>
|
<button type="submit" class="form-input btn-red" onclick="if (!confirm('{{ T("are_you_sure") }}')) return false;"><i class="icon-trash"></i> {{ T("delete") }}</button>
|
||||||
</form>
|
</form>
|
||||||
{{end}}
|
{{end}}
|
||||||
</td>
|
</td>
|
||||||
|
|
|
@ -45,7 +45,7 @@
|
||||||
{{block menu()}}{{end}}
|
{{block menu()}}{{end}}
|
||||||
</nav>
|
</nav>
|
||||||
<div id="header-height-offset"></div>
|
<div id="header-height-offset"></div>
|
||||||
{{ AdType := kilo_rand(2) }}
|
{{ AdType := rand(2) }}
|
||||||
<div id="content" class="{{ block contclass()}}{{end}}">
|
<div id="content" class="{{ block contclass()}}{{end}}">
|
||||||
<div class="content container center">
|
<div class="content container center">
|
||||||
{{ yield infos()}}
|
{{ yield infos()}}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{{block ad_wide(Type=0)}}
|
{{block ad_wide(Type=0)}}
|
||||||
{{ if !kilo_strcmp(URL.String(), "/mod", 4, 1) }}
|
{{ if !strcmp(URL.String(), "/mod", 4, 1) }}
|
||||||
{{if Type == 0}}
|
{{if Type == 0}}
|
||||||
{{ aAdsId := Sukebei() ? 634159 : 634157 }}
|
{{ aAdsId := Sukebei() ? 634159 : 634157 }}
|
||||||
<iframe data-aa='{{aAdsId}}' src='//ad.a-ads.com/{{aAdsId}}?size=728x90' scrolling='no'></iframe>
|
<iframe data-aa='{{aAdsId}}' src='//ad.a-ads.com/{{aAdsId}}?size=728x90' scrolling='no'></iframe>
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
<button href="#" class="nav-btn">
|
<button href="#" class="nav-btn">
|
||||||
<div class="user-avatar small">
|
<div class="user-avatar small">
|
||||||
<img src="https://www.gravatar.com/avatar/{{ User.MD5 }}?s=50"/>
|
<img src="https://www.gravatar.com/avatar/{{ User.MD5 }}?s=50"/>
|
||||||
|
{{if User.GetUnreadNotifications() > 0}}<span>{{User.GetUnreadNotifications()}}</span>{{end}}
|
||||||
</div>
|
</div>
|
||||||
<span class="user-info" title="{{ User.Username}}">
|
<span class="user-info" title="{{ User.Username}}">
|
||||||
<span class="hide-md">{{User.Username}}</span>
|
<span class="hide-md">{{User.Username}}</span>
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
<tr>
|
<tr>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{if _ + 1 == len(GetCategories(true, false)) }}
|
{{if _ + 1 == len(GetCategories(true, false)) }}
|
||||||
|
{{ if _% 3 != 2}}{{ if _% 3 == 0}}<td></td>{{end}}<td></td>{{end}}
|
||||||
</tr>{{end}}
|
</tr>{{end}}
|
||||||
{{ end }}
|
{{ end }}
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -44,6 +45,9 @@
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
{{ if Search.UserName != ""}}
|
||||||
|
<div class="user-search-notice">{{T("browsing_user_torrents", Search.UserID, Search.UserName, Search.UserName)|raw}} ({{Navigation.TotalItem}})</div>
|
||||||
|
{{end}}
|
||||||
<div class="pagination">
|
<div class="pagination">
|
||||||
{{ genNav(Navigation, URL, 33)|raw }}
|
{{ genNav(Navigation, URL, 33)|raw }}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
{{ if isset(treeviewData)}}
|
{{ if isset(treeviewData)}}
|
||||||
{{ range index, folder := treeviewData.Folder.Folders }}
|
{{ range index, folder := treeviewData.Folder.Folders }}
|
||||||
{{ folderId := treeviewData.IdentifierChain+"_"+index }}
|
{{ folderId := treeviewData.IdentifierChain+"_"+index }}
|
||||||
<tr class="tr-filelist tr-folder" style="padding-left: {{ treeviewData.NestLevel * 2.5 }}%;">
|
<tr class="tr-filelist tr-folder>
|
||||||
<td><label for="contents_{{folderId}}">{{folder.FolderName}}</label></td>
|
<td style="padding-left: {{ treeviewData.NestLevel * 2.5 }}%;"><label for="contents_{{folderId}}">{{folder.FolderName}}</label></td>
|
||||||
<td>{{ fileSize(folder.TotalSize(), T) }}</td>
|
<td>{{ fileSize(folder.TotalSize(), T) }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -19,7 +19,7 @@
|
||||||
{{ range _, file := treeviewData.Folder.Files }}
|
{{ range _, file := treeviewData.Folder.Files }}
|
||||||
<tr class="tr-filelist tr-file">
|
<tr class="tr-filelist tr-file">
|
||||||
<td style="padding-left: {{ treeviewData.NestLevel * 2.5 }}%;">{{file.Filename()}}</td>
|
<td style="padding-left: {{ treeviewData.NestLevel * 2.5 }}%;">{{file.Filename()}}</td>
|
||||||
<td>{{fileSize(file.Filesize, T)}}</td>
|
<td>{{fileSize(file.Filesize, T, true)}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
<div id="admin-header">
|
<div id="admin-header">
|
||||||
<a href="{{URL.Parse("/mod/")}}" class="nav-btn{{if URL.String() == "/mod/"}} active{{end}}">{{ T("moderation")}}</a>
|
<a href="{{URL.Parse("/mod/")}}" class="nav-btn{{if URL.String() == "/mod/"}} active{{end}}">{{ T("moderation")}}</a>
|
||||||
<a href="{{URL.Parse("/mod/torrents")}}" class="nav-btn{{if kilo_strcmp(URL.String(), "/mod/torrent", 12,5) }} active{{end}}">{{ T("torrents")}}</a>
|
<a href="{{URL.Parse("/mod/torrents")}}" class="nav-btn{{if strcmp(URL.String(), "/mod/torrent", 12,5) }} active{{end}}">{{ T("torrents")}}</a>
|
||||||
<a href="{{URL.Parse("/mod/users")}}" class="nav-btn{{if URL.String() == "/mod/users"}} active{{end}}">{{ T("users")}}</a>
|
<a href="{{URL.Parse("/mod/users")}}" class="nav-btn{{if URL.String() == "/mod/users"}} active{{end}}">{{ T("users")}}</a>
|
||||||
<a href="{{URL.Parse("/mod/comments")}}" class="nav-btn{{if URL.String() == "/mod/comments"}} active{{end}}">{{ T("comments")}}</a>
|
<a href="{{URL.Parse("/mod/comments")}}" class="nav-btn{{if URL.String() == "/mod/comments"}} active{{end}}">{{ T("comments")}}</a>
|
||||||
<a href="{{URL.Parse("/mod/oauth_client")}}" class="nav-btn{{if kilo_strcmp(URL.String(), "/mod/oauth_client", 17, 5) }} active{{end}}">{{ T("oauth_clients_list")}}</a>
|
<a href="{{URL.Parse("/mod/oauth_client")}}" class="nav-btn{{if strcmp(URL.String(), "/mod/oauth_client", 17, 5) }} active{{end}}">{{ T("oauth_clients_list")}}</a>
|
||||||
<a href="{{URL.Parse("/mod/announcement")}}" class="nav-btn{{if kilo_strcmp(URL.String(), "/mod/announcement", 17, 5) }} active{{end}}">{{ T("announcements")}}</a>
|
<a href="{{URL.Parse("/mod/announcement")}}" class="nav-btn{{if strcmp(URL.String(), "/mod/announcement", 17, 5) }} active{{end}}">{{ T("announcements")}}</a>
|
||||||
<a href="{{URL.Parse("/mod/reports")}}" class="nav-btn{{if URL.String() == "/mod/reports"}} active{{end}}">{{ T("torrent_reports")}}</a>
|
<a href="{{URL.Parse("/mod/reports")}}" class="nav-btn{{if URL.String() == "/mod/reports"}} active{{end}}">{{ T("torrent_reports")}}</a>
|
||||||
<a href="{{URL.Parse("/mod/reassign")}}" class="nav-btn{{if URL.String() == "/mod/reassign"}} active{{end}}">{{ T("torrent_reassign")}}</a>
|
<a href="{{URL.Parse("/mod/reassign")}}" class="nav-btn{{if URL.String() == "/mod/reassign"}} active{{end}}">{{ T("torrent_reassign")}}</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -13,19 +13,21 @@
|
||||||
<p class="profile-usertitle-job">
|
<p class="profile-usertitle-job">
|
||||||
{{T(UserProfile.GetRole())}}
|
{{T(UserProfile.GetRole())}}
|
||||||
</p>
|
</p>
|
||||||
<p class="profile-usertitle-uploadcount">{{ T("torrents_uploaded") }}:<span>{{ NbTorrents }}</span></p>
|
<p class="profile-usertitle-uploadcount">{{T("followers")}}: <b>{{len(UserProfile.Followers)}}</b><br/>{{ T("torrents_uploaded") }}:<b>{{ NbTorrents[0] }}</b><br>{{T("size")}}: <b>{{fileSize(NbTorrents[1], T, false)}}</b></p>
|
||||||
</div>
|
</div>
|
||||||
<!-- END SIDEBAR USER TITLE -->
|
<!-- END SIDEBAR USER TITLE -->
|
||||||
<!-- SIDEBAR BUTTONS -->
|
<!-- SIDEBAR BUTTONS -->
|
||||||
<div class="profile-usermenu">
|
<div class="profile-usermenu">
|
||||||
{{if User.ID > 0 }}
|
{{if UserProfile.ID > 0 && !User.CurrentUserIdentical(UserProfile.ID) }}
|
||||||
{{if !User.CurrentUserIdentical(UserProfile.ID) }}
|
{{if User.ID > 0 }}
|
||||||
{{if !User.IsFollower(UserProfile.ID)}}
|
{{if !User.IsFollower(UserProfile.ID)}}
|
||||||
<a class="form-input" href="/user/{{UserProfile.ID}}/{{UserProfile.Username}}/follow" class="form-input btn-green">{{ T("follow")}}</a>
|
<a class="form-input" href="/user/{{UserProfile.ID}}/{{UserProfile.Username}}/follow" class="form-input btn-green">{{ T("follow")}}</a>
|
||||||
{{else}}
|
{{else}}
|
||||||
<a class="form-input" href="/user/{{UserProfile.ID}}/{{UserProfile.Username}}/follow" class="form-input btn-orange">{{ T("unfollow")}}</a>
|
<a class="form-input" href="/user/{{UserProfile.ID}}/{{UserProfile.Username}}/follow" class="form-input btn-orange">{{ T("unfollow")}}</a>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{end}}
|
{{else}}
|
||||||
|
<a class="form-input" href="/login?redirectTo=/user/{{UserProfile.ID}}/{{UserProfile.Username}}/follow">{{T("follow")}}</a>
|
||||||
|
{{end}}
|
||||||
{{end}}
|
{{end}}
|
||||||
{{ if User.ID > 0 && (User.CurrentUserIdentical(UserProfile.ID) || User.CurrentOrAdmin(UserProfile.ID)) }}
|
{{ if User.ID > 0 && (User.CurrentUserIdentical(UserProfile.ID) || User.CurrentOrAdmin(UserProfile.ID)) }}
|
||||||
<a class="form-input btn-green" href="/user/{{ UserProfile.ID }}/{{ UserProfile.Username }}">
|
<a class="form-input btn-green" href="/user/{{ UserProfile.ID }}/{{ UserProfile.Username }}">
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{{ extends "layouts/index_site" }}
|
{{ extends "layouts/index_site" }}
|
||||||
{{ import "layouts/partials/helpers/search" }}
|
{{ import "layouts/partials/helpers/search" }}
|
||||||
{{block title()}}{{ T("home")}}{{end}}
|
{{block title()}}{{if Search.UserName == ""}}{{ T("home")}}{{else}}{{Search.UserName}}{{end}}{{end}}
|
||||||
{{block contclass()}}{{if User.HasAdmin() }}content-admin{{end}}{{end}}
|
{{block contclass()}}{{if User.HasAdmin() }}content-admin{{end}}{{end}}
|
||||||
{{block content_body()}}
|
{{block content_body()}}
|
||||||
{{ if OldNav || Theme == "classic"}}
|
{{ if OldNav || Theme == "classic"}}
|
||||||
|
@ -91,7 +91,7 @@
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td class="tr-size home-td hide-xs">
|
<td class="tr-size home-td hide-xs">
|
||||||
{{ fileSize(.Filesize, T) }}
|
{{ fileSize(.Filesize, T, true) }}
|
||||||
</td>
|
</td>
|
||||||
{{if .StatsObsolete[0] }}
|
{{if .StatsObsolete[0] }}
|
||||||
<td class="tr-se home-td hide-smol">-</td>
|
<td class="tr-se home-td hide-smol">-</td>
|
||||||
|
|
|
@ -50,10 +50,10 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="table-checkboxes">
|
<div class="table-checkboxes">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<input type="checkbox" value="true" name="remake" id="remake" class="form-torrent-remake"/><label for="remake">{{ T("mark_as_remake")}}</label>
|
<input type="checkbox" value="true" name="remake" id="remake" class="form-torrent-remake"/ {{if Form.Remake}}checked{{end}}><label for="remake">{{ T("mark_as_remake")}}</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<input type="checkbox" value="true" name="hidden" id="hidden" class="form-torrent-hidden {{ if User.ID == 0 }}hidden{{end}}" {{ if User.ID == 0 }}disabled checked{{end}}><label for="hidden" {{ if User.ID == 0 }}class="hidden"{{end}}>{{ T("upload_as_anon")}}</label>
|
<input type="checkbox" value="true" name="hidden" id="hidden" class="form-torrent-hidden {{ if User.ID == 0 }}hidden{{end}}" {{ if User.ID == 0}}disabled checked{{else if Form.Hidden }}checked{{end}}><label for="hidden" {{ if User.ID == 0 }}class="hidden"{{end}}>{{ T("upload_as_anon")}}</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
{{block title()}}{{Torrent.Name}}{{end}}
|
{{block title()}}{{Torrent.Name}}{{end}}
|
||||||
{{block content_body()}}
|
{{block content_body()}}
|
||||||
<div style="text-align: left;" class="box {{if Torrent.Status == 2}}torrent-remake{{else if Torrent.Status == 3}}torrent-trusted{{else if Torrent.Status == 4}}torrent-aplus{{end}}">
|
<div style="text-align: left;" class="box {{if Torrent.Status == 2}}torrent-remake{{else if Torrent.Status == 3}}torrent-trusted{{else if Torrent.Status == 4}}torrent-aplus{{end}}">
|
||||||
<div id="torrent-name" class="{{if Torrent.Status == 2}}remake{{else if Torrent.Status == 3}}trusted{{else if Torrent.Status == 4}}aplus{{end}}">
|
<div id="torrent-name" class="{{if Torrent.Status == 2}}remake{{else if Torrent.Status == 3}}trusted{{else if Torrent.Status == 4}}aplus{{else if Torrent.Status == 5}}locked{{end}}">
|
||||||
<h1 style="text-align: center;" class="torrent-hr">{{Torrent.Name}}</h1>
|
<h1 style="text-align: center;" class="torrent-hr">{{Torrent.Name}}</h1>
|
||||||
</div>
|
</div>
|
||||||
<br/>
|
<br/>
|
||||||
|
@ -28,8 +28,14 @@
|
||||||
{{else}}
|
{{else}}
|
||||||
<td class="torrent-view-td torrent-info-data uploader-link">
|
<td class="torrent-view-td torrent-info-data uploader-link">
|
||||||
{{ genUploaderLink(Torrent.UploaderID, Torrent.UploaderName, Torrent.Hidden)|raw }}
|
{{ genUploaderLink(Torrent.UploaderID, Torrent.UploaderName, Torrent.Hidden)|raw }}
|
||||||
{{if !Torrent.Hidden && Torrent.UploaderID != User.ID && User.ID > 0}}<a href="/user/{{Torrent.UploaderID}}/{{Torrent.UploaderName}}/follow?id={{Torrent.ID}}" id="subscribe-link">{{if User.IsFollower(Torrent.UploaderID)}}{{T("unfollow")}}{{else}}{{T("follow")}}{{end}}</a>{{end}}
|
{{if !Torrent.Hidden && Torrent.UploaderID != User.ID && Torrent.UploaderID != 0}}
|
||||||
</td>
|
{{if User.ID > 0}}
|
||||||
|
<a href="/user/{{Torrent.UploaderID}}/{{Torrent.UploaderName}}/follow?id={{Torrent.ID}}" id="subscribe-link">{{if User.IsFollower(Torrent.UploaderID)}}{{T("unfollow")}}{{else}}{{T("follow")}}{{end}}</a>
|
||||||
|
{{else}}
|
||||||
|
<a href="/login?redirectTo=/user/{{Torrent.UploaderID}}/{{Torrent.UploaderName}}/follow?id={{Torrent.ID}}" id="subscribe-link">{{T("follow")}}</a>
|
||||||
|
{{end}}
|
||||||
|
{{end}}
|
||||||
|
</td>
|
||||||
{{end}}
|
{{end}}
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
@ -46,7 +52,7 @@
|
||||||
</tr>
|
</tr>
|
||||||
<tr class="torrent-info-row">
|
<tr class="torrent-info-row">
|
||||||
<td class="torrent-info-td torrent-info-label">{{ T("size")}}:</td>
|
<td class="torrent-info-td torrent-info-label">{{ T("size")}}:</td>
|
||||||
<td class="torrent-view-td torrent-info-data">{{ fileSize(Torrent.Filesize, T) }}</td>
|
<td class="torrent-view-td torrent-info-data">{{ fileSize(Torrent.Filesize, T, true) }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{{ if len(Torrent.Languages) > 0 && Torrent.Languages[0] != "" }}
|
{{ if len(Torrent.Languages) > 0 && Torrent.Languages[0] != "" }}
|
||||||
<tr class="torrent-info-row">
|
<tr class="torrent-info-row">
|
||||||
|
@ -155,8 +161,8 @@
|
||||||
<a id="torrent-download-link" href="{{if Torrent.TorrentLink == ""}}/download/{{Torrent.Hash}}{{else}}{{Torrent.TorrentLink}}{{end}}" class="form-input download{{ if !torrentFileExists(Torrent.Hash, Torrent.TorrentLink)}} hidden{{end}}" style="float:left;height: auto;">
|
<a id="torrent-download-link" href="{{if Torrent.TorrentLink == ""}}/download/{{Torrent.Hash}}{{else}}{{Torrent.TorrentLink}}{{end}}" class="form-input download{{ if !torrentFileExists(Torrent.Hash, Torrent.TorrentLink)}} hidden{{end}}" style="float:left;height: auto;">
|
||||||
<div class="icon-floppy"></div>{{ T("torrent_file")}}
|
<div class="icon-floppy"></div>{{ T("torrent_file")}}
|
||||||
</a>
|
</a>
|
||||||
{{ if User.ID > 0}}
|
|
||||||
<a id="reportPopup" href="#" class="form-input">{{ T("report_btn") }}</a>
|
<a id="reportPopup" href="#" class="form-input">{{ T("report_btn") }}</a>
|
||||||
|
{{ if User.ID > 0}}
|
||||||
{{ if User.HasAdmin()}}
|
{{ if User.HasAdmin()}}
|
||||||
<form method="POST" action="/mod/torrent/delete" class="delete-form">
|
<form method="POST" action="/mod/torrent/delete" class="delete-form">
|
||||||
{{ yield csrf_field()}}
|
{{ yield csrf_field()}}
|
||||||
|
@ -211,11 +217,12 @@
|
||||||
<div class="torrent-info-box comment-box">
|
<div class="torrent-info-box comment-box">
|
||||||
<span class="comment-index">
|
<span class="comment-index">
|
||||||
<a href="#comment_{{idx}}">{{idx}}</a>
|
<a href="#comment_{{idx}}">{{idx}}</a>
|
||||||
<small style="padding-left: 4px;" class="date-full" title="{{formatDateRFC(element.Date)}}">{{formatDate(element.Date, false)}}</small>
|
<small style="padding-left: 4px;" class="date-full">{{formatDate(element.Date, false)}}</small>
|
||||||
</span>
|
</span>
|
||||||
<p><img src="https://www.gravatar.com/avatar/{{ element.UserAvatar }}"/>
|
<span class="comment-userinfo"><img src="{{ getAvatar(element.UserAvatar, 50) }}"/>
|
||||||
{{if element.UserID > 0}}<a href="/user/{{element.UserID}}/{{element.Username}}" class="comment-user">{{element.Username}}</a>{{if element.UserStatus != ""}}<span class="user-status">{{T(element.UserStatus)}}</span>{{end}}{{else}}
|
{{if element.UserID > 0}}<a href="/user/{{element.UserID}}/{{element.Username}}" class="comment-user">{{element.Username}}</a>{{if element.UserStatus != ""}}<span class="user-status">{{T(element.UserStatus)}}</span>{{end}}{{else}}
|
||||||
<span class="comment-user">れんちょん</span>{{end}}
|
<span class="comment-user">れんちょん</span>{{end}}
|
||||||
|
</span>
|
||||||
<div class="comment-content">{{element.Content|raw}}</div>
|
<div class="comment-content">{{element.Content|raw}}</div>
|
||||||
</div>
|
</div>
|
||||||
{{idx = idx + 1}}
|
{{idx = idx + 1}}
|
||||||
|
@ -233,6 +240,7 @@
|
||||||
<div class="comment-text">
|
<div class="comment-text">
|
||||||
<h3>{{ if User.ID > 0}} {{ T("submit_a_comment_as_username", User.Username) }} {{else}} {{ T("submit_a_comment_as_anonymous")|raw}} {{end}}</h3>
|
<h3>{{ if User.ID > 0}} {{ T("submit_a_comment_as_username", User.Username) }} {{else}} {{ T("submit_a_comment_as_anonymous")|raw}} {{end}}</h3>
|
||||||
<textarea style="height: 10rem;" placeholder="サンキュー" name="comment" class="form-input up-input"></textarea>
|
<textarea style="height: 10rem;" placeholder="サンキュー" name="comment" class="form-input up-input"></textarea>
|
||||||
|
<p class="not-important">{{T("comment_markdown_notice")}}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="comment-captcha">
|
<div class="comment-captcha">
|
||||||
{{ yield captcha(captchaid=CaptchaID)}}
|
{{ yield captcha(captchaid=CaptchaID)}}
|
||||||
|
@ -243,7 +251,6 @@
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{ if User.ID > 0 }}
|
|
||||||
<!-- Modal to report a torrent -->
|
<!-- Modal to report a torrent -->
|
||||||
<div id="modal_mod_tools" class="modal">
|
<div id="modal_mod_tools" class="modal">
|
||||||
<!-- Modal content -->
|
<!-- Modal content -->
|
||||||
|
@ -264,9 +271,15 @@
|
||||||
<label for="wrongcat">{{ T("wrong_category") }}</label><br />
|
<label for="wrongcat">{{ T("wrong_category") }}</label><br />
|
||||||
<input type="radio" name="report_type" value="duplicate_deprecated" id="dup" required/>
|
<input type="radio" name="report_type" value="duplicate_deprecated" id="dup" required/>
|
||||||
<label for="dup">{{ T("duplicate_deprecated") }}</label><br />
|
<label for="dup">{{ T("duplicate_deprecated") }}</label><br />
|
||||||
<div class="comment-captcha">
|
<input type="radio" name="report_type" value="other" id="other"" required/>
|
||||||
{{yield captcha(captchaid=CaptchaID)}}
|
<label for="other">{{ T("other") }}</label><br />
|
||||||
</div>
|
<h4>{{ T("report_message") }}</h4>
|
||||||
|
<input type="text" class="form-input" name="report_message" placeholder="(Optional, 60 characters max)" maxlength="60">
|
||||||
|
{{if User.ID == 0}}
|
||||||
|
<div class="comment-captcha" style="margin-top: 7px;">
|
||||||
|
{{yield captcha(captchaid=CaptchaID)}}
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<span>
|
<span>
|
||||||
|
@ -278,6 +291,7 @@
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{{ if User.ID > 0 }}
|
||||||
<!-- Modal to add a tag -->
|
<!-- Modal to add a tag -->
|
||||||
<div id="modal_tag_form" class="modal">
|
<div id="modal_tag_form" class="modal">
|
||||||
<!-- Modal content -->
|
<!-- Modal content -->
|
||||||
|
@ -311,6 +325,14 @@
|
||||||
{{end}}
|
{{end}}
|
||||||
{{ block footer_js()}}
|
{{ block footer_js()}}
|
||||||
<script type="text/javascript" src="{{ URL.Parse("/js/modal.js") }}"></script>
|
<script type="text/javascript" src="{{ URL.Parse("/js/modal.js") }}"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
// Modal initialization
|
||||||
|
Modal.Init({
|
||||||
|
elements: document.getElementsByClassName("modal"),
|
||||||
|
// order of apparition of the modals
|
||||||
|
button: ["#reportPopup", "#tagPopup"]
|
||||||
|
});
|
||||||
|
</script>
|
||||||
{{ if !torrentFileExists(Torrent.Hash, Torrent.TorrentLink)}}
|
{{ if !torrentFileExists(Torrent.Hash, Torrent.TorrentLink)}}
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
var torrentLink = document.getElementById("torrent-download-link"),
|
var torrentLink = document.getElementById("torrent-download-link"),
|
||||||
|
@ -338,7 +360,7 @@
|
||||||
Query.Get('/download/{{Torrent.Hash}}?js_query=true', function (data) {
|
Query.Get('/download/{{Torrent.Hash}}?js_query=true', function (data) {
|
||||||
if(typeof data.exists != "undefined" && data.exists == true) {
|
if(typeof data.exists != "undefined" && data.exists == true) {
|
||||||
torrentLink.innerHTML = oldDownloadHtml
|
torrentLink.innerHTML = oldDownloadHtml
|
||||||
torrentLink.style.opacity = 1
|
torrentLink.style = torrentLink.style + "opacity: 1!important;filter: grayscale(0);"
|
||||||
torrentLink.removeEventListener("click", function (e) {});
|
torrentLink.removeEventListener("click", function (e) {});
|
||||||
torrentLink.click();
|
torrentLink.click();
|
||||||
} else {
|
} else {
|
||||||
|
@ -381,6 +403,8 @@
|
||||||
downloads.innerHTML = oldStats[2]
|
downloads.innerHTML = oldStats[2]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{ if User.ID > 0 }}
|
{{ if User.ID > 0 }}
|
||||||
|
@ -413,7 +437,7 @@ Templates.Add("tag", function(tag) {
|
||||||
Modal.Init({
|
Modal.Init({
|
||||||
elements: document.getElementsByClassName("modal"),
|
elements: document.getElementsByClassName("modal"),
|
||||||
// order of apparition of the modals
|
// order of apparition of the modals
|
||||||
button: ["#reportPopup", "#tagPopup"]
|
button: ["#tagPopup"]
|
||||||
});
|
});
|
||||||
|
|
||||||
document.querySelector("#modal_tag_form form").addEventListener("submit", function(e) {
|
document.querySelector("#modal_tag_form form").addEventListener("submit", function(e) {
|
||||||
|
|
|
@ -3,25 +3,37 @@
|
||||||
{{block title()}}{{ T("profile_edit_page", User.Username) }}{{end}}
|
{{block title()}}{{ T("profile_edit_page", User.Username) }}{{end}}
|
||||||
{{ block profile_navigation()}}{{ yield profile_menu(route="profile") }}{{end}}
|
{{ block profile_navigation()}}{{ yield profile_menu(route="profile") }}{{end}}
|
||||||
{{block profile_content()}}
|
{{block profile_content()}}
|
||||||
{{ if len(User.Notifications) > 0}}
|
<table class="notification-table">
|
||||||
<div>
|
<thead>
|
||||||
<a href="/notifications?clear" class="btn btn-red pull-right"> {{ T("clear_notifications") }}</a>
|
<tr>
|
||||||
<div style="clear: both;"></div>
|
<th class="notification-status">{{T("status")}}</th>
|
||||||
</div>
|
<th class="notification-event">Event</th>
|
||||||
<table>
|
<th class="notification-date">{{T("date")}}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{{if len(User.Notifications) == 0}}
|
||||||
|
<tr><td colspan="3">{{T("no_notifications")}}</td></tr>
|
||||||
|
{{end}}
|
||||||
{{ range User.Notifications }}
|
{{ range User.Notifications }}
|
||||||
<tr>
|
<tr>
|
||||||
<td{{ if !.Read }} class="btn-orange"{{end}}>
|
<td class="notification-status {{ if !.Read }}notification-unread{{end}}">{{if .Read}}{{T("read")}}{{else}}{{T("unread")}}{{end}}</td>
|
||||||
<div style="padding: 0 1rem 1rem;">
|
<td class="notification-event">
|
||||||
<a href="{{ .URL }}?notif">
|
<a href="{{ .URL }}?notif">{{ .Content }}</a>
|
||||||
<h3>{{ .Content }}</h3>
|
</td>
|
||||||
</a>
|
{{if !.Date.IsZero()}}
|
||||||
</div>
|
<td class="notification-date date-full" title="{{formatDate(.Date, false)}}">{{formatDate(.Date, false)}}</td>
|
||||||
</td>
|
{{else}}
|
||||||
</tr>
|
<td class="notification-date">{{T("unknown")}}</td>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
</tr>
|
||||||
|
{{end}}
|
||||||
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
{{else}}
|
<div id="clear-notification">
|
||||||
<h2>{{ T("no_notifications") }}</h2>
|
<hr/>
|
||||||
{{end}}
|
<a href="/notifications?read_all" class="btn-grey form-input" style="float: left;"> {{ T("mark_notifications_as_read") }}</a>
|
||||||
|
<a href="/notifications?clear_all" class="btn-red form-input"> {{ T("clear_all_notifications") }}</a>
|
||||||
|
<a href="/notifications?clear" class="btn-green form-input"> {{ T("clear_notifications") }}</a>
|
||||||
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
|
@ -41,7 +41,7 @@
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td class="tr-size user-td hide-xs">
|
<td class="tr-size user-td hide-xs">
|
||||||
{{ fileSize(torrent.Filesize, T) }}
|
{{ fileSize(torrent.Filesize, T, true) }}
|
||||||
</td>
|
</td>
|
||||||
<td class="tr-date user-td date-short hide-smol" title="{{torrent.Date}}">{{formatDate(torrent.FullDate, true)}}</td>
|
<td class="tr-date user-td date-short hide-smol" title="{{torrent.Date}}">{{formatDate(torrent.FullDate, true)}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
|
@ -173,9 +173,14 @@ func userProfileBase(c *gin.Context, templateName string, userProfile *models.Us
|
||||||
} else {
|
} else {
|
||||||
_, userProfile.Torrents, nbTorrents, _ = search.ByQuery(c, 1, true, false, true)
|
_, userProfile.Torrents, nbTorrents, _ = search.ByQuery(c, 1, true, false, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var uploadedSize int64
|
||||||
|
for _, torrent := range userProfile.Torrents {
|
||||||
|
uploadedSize += torrent.Filesize
|
||||||
|
}
|
||||||
|
|
||||||
variables.Set("UserProfile", userProfile)
|
variables.Set("UserProfile", userProfile)
|
||||||
variables.Set("NbTorrents", nbTorrents)
|
variables.Set("NbTorrents", []int64{int64(nbTorrents),uploadedSize})
|
||||||
Render(c, path.Join(SiteDir, "user", templateName), variables)
|
Render(c, path.Join(SiteDir, "user", templateName), variables)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,6 @@ func templateFunctions(vars jet.VarMap) jet.VarMap {
|
||||||
vars.Set("FlagCode", flagCode)
|
vars.Set("FlagCode", flagCode)
|
||||||
vars.Set("getAvatar", getAvatar)
|
vars.Set("getAvatar", getAvatar)
|
||||||
vars.Set("torrentFileExists", torrentFileExists)
|
vars.Set("torrentFileExists", torrentFileExists)
|
||||||
vars.Set("formatDateRFC", formatDateRFC)
|
|
||||||
vars.Set("GetHostname", format.GetHostname)
|
vars.Set("GetHostname", format.GetHostname)
|
||||||
vars.Set("GetCategories", categories.GetSelect)
|
vars.Set("GetCategories", categories.GetSelect)
|
||||||
vars.Set("GetCategory", getCategory)
|
vars.Set("GetCategory", getCategory)
|
||||||
|
@ -52,10 +51,10 @@ func templateFunctions(vars jet.VarMap) jet.VarMap {
|
||||||
vars.Set("genUploaderLink", genUploaderLink)
|
vars.Set("genUploaderLink", genUploaderLink)
|
||||||
vars.Set("genActivityContent", genActivityContent)
|
vars.Set("genActivityContent", genActivityContent)
|
||||||
vars.Set("contains", contains)
|
vars.Set("contains", contains)
|
||||||
vars.Set("toString", toString)
|
vars.Set("strcmp", strcmp)
|
||||||
vars.Set("kilo_strcmp", kilo_strcmp)
|
vars.Set("strfind", strfind)
|
||||||
vars.Set("kilo_strfind", kilo_strfind)
|
vars.Set("rand", rand.Intn)
|
||||||
vars.Set("kilo_rand", kilo_rand)
|
vars.Set("toString", strconv.Itoa)
|
||||||
vars.Set("getDomainName", getDomainName)
|
vars.Set("getDomainName", getDomainName)
|
||||||
vars.Set("getThemeList", getThemeList)
|
vars.Set("getThemeList", getThemeList)
|
||||||
vars.Set("formatThemeName", formatThemeName)
|
vars.Set("formatThemeName", formatThemeName)
|
||||||
|
@ -196,13 +195,16 @@ func flagCode(languageCode string) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func getAvatar(hash string, size int) string {
|
func getAvatar(hash string, size int) string {
|
||||||
return "https://www.gravatar.com/avatar/" + hash + "?s=" + strconv.Itoa(size)
|
if hash != "" {
|
||||||
|
return "https://www.gravatar.com/avatar/" + hash + "?s=" + strconv.Itoa(size)
|
||||||
|
} else {
|
||||||
|
if config.IsSukebei() {
|
||||||
|
return "/img/sukebei_avatar_" + strconv.Itoa(size) + ".jpg"
|
||||||
|
}
|
||||||
|
return "/img/avatar_" + strconv.Itoa(size) + ".jpg"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func formatDateRFC(t time.Time) string {
|
|
||||||
// because time.* isn't available in templates...
|
|
||||||
return t.Format(time.RFC3339)
|
|
||||||
}
|
|
||||||
func getCategory(category string, keepParent bool) categories.Categories {
|
func getCategory(category string, keepParent bool) categories.Categories {
|
||||||
cats := categories.GetSelect(true, true)
|
cats := categories.GetSelect(true, true)
|
||||||
found := false
|
found := false
|
||||||
|
@ -251,8 +253,8 @@ func languageNameFromCode(languageCode string, T publicSettings.TemplateTfunc) s
|
||||||
}
|
}
|
||||||
return strings.Title(publicSettings.Translate(languageCode, string(T("language_code"))))
|
return strings.Title(publicSettings.Translate(languageCode, string(T("language_code"))))
|
||||||
}
|
}
|
||||||
func fileSize(filesize int64, T publicSettings.TemplateTfunc) template.HTML {
|
func fileSize(filesize int64, T publicSettings.TemplateTfunc, showUnknown bool) template.HTML {
|
||||||
if filesize == 0 {
|
if showUnknown && filesize == 0 {
|
||||||
return T("unknown")
|
return T("unknown")
|
||||||
}
|
}
|
||||||
return template.HTML(format.FileSize(filesize))
|
return template.HTML(format.FileSize(filesize))
|
||||||
|
@ -348,11 +350,7 @@ func torrentFileExists(hash string, TorrentLink string) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func toString(number int) string {
|
func strcmp(str1 string, str2 string, end int, start int) bool {
|
||||||
return strconv.Itoa(number)
|
|
||||||
}
|
|
||||||
|
|
||||||
func kilo_strcmp(str1 string, str2 string, end int, start int) bool {
|
|
||||||
//Compare two strings but has length arguments
|
//Compare two strings but has length arguments
|
||||||
|
|
||||||
len1 := len(str1)
|
len1 := len(str1)
|
||||||
|
@ -376,7 +374,7 @@ func kilo_strcmp(str1 string, str2 string, end int, start int) bool {
|
||||||
return strings.Compare(str1[start:end], str2[start:end]) == 0
|
return strings.Compare(str1[start:end], str2[start:end]) == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func kilo_strfind(str1 string, searchfor string, start int) bool {
|
func strfind(str1 string, searchfor string, start int) bool {
|
||||||
//Search a string inside another with start parameter
|
//Search a string inside another with start parameter
|
||||||
//start parameter indicates where we start searching
|
//start parameter indicates where we start searching
|
||||||
|
|
||||||
|
@ -390,10 +388,6 @@ func kilo_strfind(str1 string, searchfor string, start int) bool {
|
||||||
return strings.Contains(str1[start:len1], searchfor)
|
return strings.Contains(str1[start:len1], searchfor)
|
||||||
}
|
}
|
||||||
|
|
||||||
func kilo_rand(max int) int {
|
|
||||||
return rand.Intn(max)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getDomainName() string {
|
func getDomainName() string {
|
||||||
domain := config.Get().Cookies.DomainName
|
domain := config.Get().Cookies.DomainName
|
||||||
if config.Get().Environment == "DEVELOPMENT" {
|
if config.Get().Environment == "DEVELOPMENT" {
|
||||||
|
@ -408,7 +402,7 @@ func getThemeList() ([]string) {
|
||||||
themeList := []string{}
|
themeList := []string{}
|
||||||
|
|
||||||
filepath.Walk(searchDir, func(path string, f os.FileInfo, err error) error {
|
filepath.Walk(searchDir, func(path string, f os.FileInfo, err error) error {
|
||||||
if kilo_strfind(path, ".css", len(searchDir)) {
|
if strfind(path, ".css", len(searchDir)) {
|
||||||
//we only want .css file
|
//we only want .css file
|
||||||
|
|
||||||
fileName := path[len(searchDir):strings.Index(path, ".css")]
|
fileName := path[len(searchDir):strings.Index(path, ".css")]
|
||||||
|
|
|
@ -175,12 +175,12 @@ func TestGetAvatar(t *testing.T) {
|
||||||
{
|
{
|
||||||
Test: "",
|
Test: "",
|
||||||
Size: 0,
|
Size: 0,
|
||||||
Expected: "https://www.gravatar.com/avatar/?s=0",
|
Expected: "/img/avatar_0.jpg",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Test: "",
|
Test: "",
|
||||||
Size: 100,
|
Size: 100,
|
||||||
Expected: "https://www.gravatar.com/avatar/?s=100",
|
Expected: "/img/avatar_100.jpg",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Test: "test",
|
Test: "test",
|
||||||
|
@ -200,31 +200,7 @@ func TestGetAvatar(t *testing.T) {
|
||||||
t.Errorf("Unexpected value from the function getAvatar, got '%s', wanted '%s' for '%s' and '%d'", value, test.Expected, test.Test, test.Size)
|
t.Errorf("Unexpected value from the function getAvatar, got '%s', wanted '%s' for '%s' and '%d'", value, test.Expected, test.Test, test.Size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFormatDateRFC(t *testing.T) {
|
|
||||||
location, _ := time.LoadLocation("UTC")
|
|
||||||
var tests = []struct {
|
|
||||||
Test time.Time
|
|
||||||
Expected string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
Test: time.Date(2016, 5, 4, 3, 2, 1, 10, location),
|
|
||||||
Expected: "2016-05-04T03:02:01Z",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Test: time.Now(),
|
|
||||||
Expected: time.Now().Format(time.RFC3339),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, test := range tests {
|
|
||||||
value := formatDateRFC(test.Test)
|
|
||||||
if value != test.Expected {
|
|
||||||
t.Errorf("Unexpected value from the function formatDateRFC, got '%s', wanted '%s' for '%s'", value, test.Expected, test.Test.String())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetCategory(t *testing.T) {
|
func TestGetCategory(t *testing.T) {
|
||||||
var tests = []struct {
|
var tests = []struct {
|
||||||
|
@ -382,22 +358,35 @@ func TestLanguageNameFromCode(t *testing.T) {
|
||||||
func TestFileSize(t *testing.T) {
|
func TestFileSize(t *testing.T) {
|
||||||
var tests = []struct {
|
var tests = []struct {
|
||||||
TestSize int64
|
TestSize int64
|
||||||
|
TestShowUnknown bool
|
||||||
Expected template.HTML
|
Expected template.HTML
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
TestSize: 0,
|
TestSize: 0,
|
||||||
|
TestShowUnknown: true,
|
||||||
Expected: template.HTML("Unknown"),
|
Expected: template.HTML("Unknown"),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
TestSize: 0,
|
||||||
|
TestShowUnknown: false,
|
||||||
|
Expected: template.HTML("0.0 B"),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
TestSize: 10,
|
TestSize: 10,
|
||||||
|
TestShowUnknown: false,
|
||||||
|
Expected: template.HTML("10.0 B"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
TestSize: 10,
|
||||||
|
TestShowUnknown: true,
|
||||||
Expected: template.HTML("10.0 B"),
|
Expected: template.HTML("10.0 B"),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
T := mockupTemplateT(t)
|
T := mockupTemplateT(t)
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
value := fileSize(test.TestSize, T)
|
value := fileSize(test.TestSize, T, test.TestShowUnknown)
|
||||||
if value != test.Expected {
|
if value != test.Expected {
|
||||||
t.Errorf("Unexpected value from the function languageName, got '%s', wanted '%s' for '%d'", value, test.Expected, test.TestSize)
|
t.Errorf("Unexpected value from the function fileSize, got '%s', wanted '%s' for '%d' with '%d'", value, test.Expected, test.TestSize, test.TestShowUnknown)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -624,90 +613,94 @@ func testTorrentFileExists(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Testkilo_strcmp(t *testing.T) {
|
func Teststrcmp(t *testing.T) {
|
||||||
var tests = []struct {
|
var tests = []struct {
|
||||||
TestString string
|
TestString string
|
||||||
TestString2 string
|
TestString2 string
|
||||||
|
TestEnd int
|
||||||
|
TestStart int
|
||||||
Expected bool
|
Expected bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
TestString: "kilo",
|
TestString: "kilo",
|
||||||
TestString2: "kilo",
|
TestString2: "kilo",
|
||||||
|
TestEnd: -1,
|
||||||
|
TestStart: 0,
|
||||||
Expected: true,
|
Expected: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
TestString: "kilo",
|
TestString: "kilo",
|
||||||
TestString2: "loki", // Clearly not the same level
|
TestString2: "loki",
|
||||||
|
TestEnd: -1,
|
||||||
|
TestStart: 0,
|
||||||
Expected: false,
|
Expected: false,
|
||||||
},
|
},
|
||||||
}
|
|
||||||
for _, test := range tests {
|
|
||||||
value := kilo_strcmp(test.TestString, test.TestString2, -1, 0)
|
|
||||||
if value != test.Expected {
|
|
||||||
t.Errorf("Unexpected value from the function languageName, got '%t', wanted '%t'", value, test.Expected, test.TestString, test.TestString)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestToString(t *testing.T) {
|
|
||||||
var tests = []struct {
|
|
||||||
TestInt int
|
|
||||||
Expected string
|
|
||||||
}{
|
|
||||||
{
|
{
|
||||||
TestInt: 0,
|
TestString: "superkilo", //compare "superkilo" to "kilo"
|
||||||
Expected: "0",
|
TestString2: "kilo",
|
||||||
|
TestEnd: -1,
|
||||||
|
TestStart: 0,
|
||||||
|
Expected: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
TestString: "superkilo", //compare "kilo" to "kilo"
|
||||||
|
TestString2: "kilo",
|
||||||
|
TestEnd: -1,
|
||||||
|
TestStart: 6,
|
||||||
|
Expected: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
TestString: "superkill", //compare "kil" to "kil"
|
||||||
|
TestString2: "kilo",
|
||||||
|
TestEnd: 8,
|
||||||
|
TestStart: 6,
|
||||||
|
Expected: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
value := toString(test.TestInt)
|
value := strcmp(test.TestString, test.TestString2, -1, 0)
|
||||||
if value != test.Expected {
|
if value != test.Expected {
|
||||||
t.Errorf("Unexpected value from the function languageName, got '%t', wanted '%t'", value, test.Expected)
|
t.Errorf("Unexpected value from the function strcmp, got '%t', wanted '%t'", value, test.Expected, test.TestString, test.TestString)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Testkilo_strfind(t *testing.T) {
|
func Teststrfind(t *testing.T) {
|
||||||
var tests = []struct {
|
var tests = []struct {
|
||||||
TestString string
|
TestString string
|
||||||
TestString2 string
|
TestString2 string
|
||||||
Expected bool
|
TestStart int
|
||||||
|
Match bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
TestString: "kilo",
|
TestString: "kilo",
|
||||||
TestString2: "kilo",
|
TestString2: "kilo",
|
||||||
Expected: true,
|
TestStart: 0,
|
||||||
|
Match: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
TestString: "kilo",
|
TestString: "kilo",
|
||||||
TestString2: "loki", // Clearly not the same level
|
TestString2: "loki",
|
||||||
Expected: false,
|
TestStart: 0,
|
||||||
|
Match: false,
|
||||||
},
|
},
|
||||||
}
|
|
||||||
for _, test := range tests {
|
|
||||||
value := kilo_strfind(test.TestString, test.TestString2, 0)
|
|
||||||
if value != test.Expected {
|
|
||||||
t.Errorf("Unexpected value from the function languageName, got '%t', wanted '%t'", value, test.Expected, test.TestString, test.TestString)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRand(t *testing.T) {
|
|
||||||
var tests = []struct {
|
|
||||||
TestInt int
|
|
||||||
TestInt2 int
|
|
||||||
Expected int
|
|
||||||
}{
|
|
||||||
{
|
{
|
||||||
TestInt: 0,
|
TestString: "akumeme",
|
||||||
TestInt2: 1,
|
TestString2: "meme",
|
||||||
Expected: 1,
|
TestStart: 0,
|
||||||
|
Match: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
TestString: "memeaku",
|
||||||
|
TestString2: "meme",
|
||||||
|
TestStart: 4, //Search "meme" in "aku", obviously not there
|
||||||
|
Match: false,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
value := kilo_rand(1)
|
value := strfind(test.TestString, test.TestString2, test.TestStart)
|
||||||
if value != test.Expected {
|
if value != test.Match {
|
||||||
//t.Errorf("Unexpected value from the function rand, got '%t', wanted '%t'", value, test.Expected)
|
t.Errorf("Unexpected value from the function strfind, got '%t', wanted '%t'", value, test.Match, test.TestString, test.TestString)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -727,6 +720,7 @@ func TestRand(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func TestGetTheme(t *testing.T) {
|
func TestGetTheme(t *testing.T) {
|
||||||
var tests = []struct {
|
var tests = []struct {
|
||||||
|
@ -741,12 +735,27 @@ func TestRand(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func testformatThemeName(t *testing.T) {
|
func testformatThemeName(t *testing.T) {
|
||||||
var tests = []struct {
|
var tests = []struct {
|
||||||
domainName string
|
TestPath string
|
||||||
|
Expected string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
domainName: "test",
|
TestPath: "g",
|
||||||
|
Expected: "/g/",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
TestPath: "v",
|
||||||
|
Expected: "/v/",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
TestPath: "my_theme",
|
||||||
|
Expected: "My Theme",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
TestPath: "tomorrow",
|
||||||
|
Expected: "Tomorrow",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
|
@ -758,25 +767,35 @@ func TestRand(t *testing.T) {
|
||||||
T = func(id string, args ...interface{}) template.HTML {
|
T = func(id string, args ...interface{}) template.HTML {
|
||||||
return template.HTML(fmt.Sprintf(Ts(id), args...))
|
return template.HTML(fmt.Sprintf(Ts(id), args...))
|
||||||
}
|
}
|
||||||
value := formatThemeName("path", T)
|
value := formatThemeName(test.TestPath, T)
|
||||||
if value != test.domainName {
|
if value != test.Expected {
|
||||||
|
t.Errorf("Unexpected value from the function formatThemeName, got '%t' from '%s', wanted '%t'", value, test.TestPath, test.Expected)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func testFormatDate(t *testing.T) {
|
func testFormatDate(t *testing.T) {
|
||||||
|
UTC, _ := time.LoadLocation("")
|
||||||
var tests = []struct {
|
var tests = []struct {
|
||||||
domainName string
|
TestDate time.Time
|
||||||
|
TestFullDate bool
|
||||||
|
Expected string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
domainName: "test",
|
TestDate: time.Date(2017, 11, 1, 0, 0, 0, 0, UTC),
|
||||||
|
TestFullDate: false,
|
||||||
|
Expected: "Nov 1, 2017",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
TestDate: time.Date(2017, 11, 1, 0, 0, 0, 0, UTC),
|
||||||
|
TestFullDate: true,
|
||||||
|
Expected: "11/1/2017, 0:00:00 AM UTC+0",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
value := formatDate(time.Now(), false)
|
value := formatDate(test.TestDate, test.TestFullDate)
|
||||||
if value != test.domainName {
|
if value != test.Expected {
|
||||||
|
t.Errorf("Unexpected value from the function formatDate, got '%t' from '%s' and '%d', wanted '%t'", value, test.TestDate, test.TestFullDate, test.Expected)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,12 +63,12 @@ func walkDirTest(dir string, t *testing.T) {
|
||||||
fakeTorrentRequest := &torrentValidator.TorrentRequest{Name: "test", Magnet: "", Category: "", Remake: false, Description: "", Status: 1, Hidden: false, CaptchaID: "", WebsiteLink: "", Languages: nil, Infohash: "", SubCategoryID: 0, CategoryID: 0, Filesize: 0, Filepath: "", FileList: nil, Trackers: nil, Tags: torrentValidator.TagsRequest{}}
|
fakeTorrentRequest := &torrentValidator.TorrentRequest{Name: "test", Magnet: "", Category: "", Remake: false, Description: "", Status: 1, Hidden: false, CaptchaID: "", WebsiteLink: "", Languages: nil, Infohash: "", SubCategoryID: 0, CategoryID: 0, Filesize: 0, Filepath: "", FileList: nil, Trackers: nil, Tags: torrentValidator.TagsRequest{}}
|
||||||
fakeLogin := &userValidator.LoginForm{"test", "test", "/", "false"}
|
fakeLogin := &userValidator.LoginForm{"test", "test", "/", "false"}
|
||||||
fakeRegistration := &userValidator.RegistrationForm{"test", "", "test", "test", "xxxx", "1"}
|
fakeRegistration := &userValidator.RegistrationForm{"test", "", "test", "test", "xxxx", "1"}
|
||||||
fakeReport := &models.TorrentReport{1, "test", 1, 1, time.Now(), fakeTorrent, fakeUser}
|
fakeReport := &models.TorrentReport{1, "test", "test", 1, 1, time.Now(), fakeTorrent, fakeUser}
|
||||||
fakeOauthForm := apiValidator.CreateForm{"", "f", []string{fu}, []string{}, []string{}, "", "fedr", fu, fu, fu, fu, []string{em}, ""}
|
fakeOauthForm := apiValidator.CreateForm{"", "f", []string{fu}, []string{}, []string{}, "", "fedr", fu, fu, fu, fu, []string{em}, ""}
|
||||||
fakeOauthModel := fakeOauthForm.Bind(&models.OauthClient{})
|
fakeOauthModel := fakeOauthForm.Bind(&models.OauthClient{})
|
||||||
fakeClient := client.Client{"", "", "", []string{""}, []string{""}, []string{""}, "", "", "", "", "", "", []string{""}, false}
|
fakeClient := client.Client{"", "", "", []string{""}, []string{""}, []string{""}, "", "", "", "", "", "", []string{""}, false}
|
||||||
fakeAnnouncement := announcementValidator.CreateForm{1, "", 2}
|
fakeAnnouncement := announcementValidator.CreateForm{1, "", 2}
|
||||||
fakeNotification := &models.Notification{1, "test", true, "test", "test", time.Now(), 1}
|
fakeNotification := &models.Notification{1, "test", true, "test", "test", time.Now(), time.Now(), 1}
|
||||||
|
|
||||||
contextvariables := ContextTest{
|
contextvariables := ContextTest{
|
||||||
"dumps.jet.html": func(variables jet.VarMap) jet.VarMap {
|
"dumps.jet.html": func(variables jet.VarMap) jet.VarMap {
|
||||||
|
@ -85,17 +85,17 @@ func walkDirTest(dir string, t *testing.T) {
|
||||||
return variables
|
return variables
|
||||||
},
|
},
|
||||||
"edit.jet.html": func(variables jet.VarMap) jet.VarMap {
|
"edit.jet.html": func(variables jet.VarMap) jet.VarMap {
|
||||||
variables.Set("NbTorrents", 0)
|
variables.Set("NbTorrents", []int64{0,0})
|
||||||
variables.Set("Form", fakeTorrentRequest)
|
variables.Set("Form", fakeTorrentRequest)
|
||||||
variables.Set("Languages", publicSettings.Languages{*fakeLanguage, *fakeLanguage})
|
variables.Set("Languages", publicSettings.Languages{*fakeLanguage, *fakeLanguage})
|
||||||
return variables
|
return variables
|
||||||
},
|
},
|
||||||
"torrents.jet.html": func(variables jet.VarMap) jet.VarMap {
|
"torrents.jet.html": func(variables jet.VarMap) jet.VarMap {
|
||||||
variables.Set("NbTorrents", 0)
|
variables.Set("NbTorrents", []int64{0,0})
|
||||||
return variables
|
return variables
|
||||||
},
|
},
|
||||||
"profile.jet.html": func(variables jet.VarMap) jet.VarMap {
|
"profile.jet.html": func(variables jet.VarMap) jet.VarMap {
|
||||||
variables.Set("NbTorrents", 0)
|
variables.Set("NbTorrents", []int64{0,0})
|
||||||
return variables
|
return variables
|
||||||
},
|
},
|
||||||
"upload.jet.html": func(variables jet.VarMap) jet.VarMap {
|
"upload.jet.html": func(variables jet.VarMap) jet.VarMap {
|
||||||
|
@ -103,7 +103,7 @@ func walkDirTest(dir string, t *testing.T) {
|
||||||
return variables
|
return variables
|
||||||
},
|
},
|
||||||
"view.jet.html": func(variables jet.VarMap) jet.VarMap {
|
"view.jet.html": func(variables jet.VarMap) jet.VarMap {
|
||||||
variables.Set("NbTorrents", 0)
|
variables.Set("NbTorrents", []int64{0,0})
|
||||||
variables.Set("Torrent", fakeTorrent.ToJSON())
|
variables.Set("Torrent", fakeTorrent.ToJSON())
|
||||||
variables.Set("CaptchaID", "xxxxxx")
|
variables.Set("CaptchaID", "xxxxxx")
|
||||||
variables.Set("RootFolder", filelist.FileListToFolder(fakeTorrent.FileList, "root"))
|
variables.Set("RootFolder", filelist.FileListToFolder(fakeTorrent.FileList, "root"))
|
||||||
|
@ -153,7 +153,7 @@ func walkDirTest(dir string, t *testing.T) {
|
||||||
return variables
|
return variables
|
||||||
},
|
},
|
||||||
"notifications.jet.html": func(variables jet.VarMap) jet.VarMap {
|
"notifications.jet.html": func(variables jet.VarMap) jet.VarMap {
|
||||||
variables.Set("NbTorrents", 0)
|
variables.Set("NbTorrents", []int64{0,0})
|
||||||
return variables
|
return variables
|
||||||
},
|
},
|
||||||
"report.jet.html": func(variables jet.VarMap) jet.VarMap {
|
"report.jet.html": func(variables jet.VarMap) jet.VarMap {
|
||||||
|
|
|
@ -65,3 +65,24 @@
|
||||||
## 2017/10/28
|
## 2017/10/28
|
||||||
* + hours_minutes_ago
|
* + hours_minutes_ago
|
||||||
* + days_hours_ago
|
* + days_hours_ago
|
||||||
|
* + status
|
||||||
|
* + event
|
||||||
|
* + read
|
||||||
|
* + unread
|
||||||
|
* + clear_all_notifications
|
||||||
|
* ~ clear_notifications -> modified to "Clear **read** notification"
|
||||||
|
## 2017/10/29
|
||||||
|
* + report_message
|
||||||
|
* + other
|
||||||
|
* + read_notifications_cleared
|
||||||
|
* + notifications_read
|
||||||
|
* + mark_notifications_as_read
|
||||||
|
## 2017/10/31
|
||||||
|
* + followers
|
||||||
|
* ~ description_markdown_notice -> comment_markdown_notice
|
||||||
|
* + browsing_user_torrents
|
||||||
|
* + delete_all_reports
|
||||||
|
## 2017/11/02
|
||||||
|
* + duration
|
||||||
|
* - removed: delay
|
||||||
|
* + create_anouncement_success
|
||||||
|
|
|
@ -139,6 +139,10 @@
|
||||||
"id": "torrents",
|
"id": "torrents",
|
||||||
"translation": "Torrents"
|
"translation": "Torrents"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "followers",
|
||||||
|
"translation": "Followers"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "follow",
|
"id": "follow",
|
||||||
"translation": "Follow"
|
"translation": "Follow"
|
||||||
|
@ -532,8 +536,8 @@
|
||||||
"translation": "Torrent Description"
|
"translation": "Torrent Description"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "description_markdown_notice",
|
"id": "comment_markdown_notice",
|
||||||
"translation": "Markdown can be used in descriptions."
|
"translation": "Markdown can be used in comments."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "show_all",
|
"id": "show_all",
|
||||||
|
@ -775,6 +779,10 @@
|
||||||
"id": "report_type",
|
"id": "report_type",
|
||||||
"translation": "Report type"
|
"translation": "Report type"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "report_message",
|
||||||
|
"translation": "Report message"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "illegal_content",
|
"id": "illegal_content",
|
||||||
"translation": "Illegal content"
|
"translation": "Illegal content"
|
||||||
|
@ -791,6 +799,10 @@
|
||||||
"id": "duplicate_deprecated",
|
"id": "duplicate_deprecated",
|
||||||
"translation": "Duplicate / Deprecated"
|
"translation": "Duplicate / Deprecated"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "other",
|
||||||
|
"translation": "Other"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "captcha",
|
"id": "captcha",
|
||||||
"translation": "Captcha"
|
"translation": "Captcha"
|
||||||
|
@ -829,12 +841,28 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "clear_notifications",
|
"id": "clear_notifications",
|
||||||
"translation": "Clear Notifications"
|
"translation": "Clear read notifications"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "clear_all_notifications",
|
||||||
|
"translation": "Clear all notifications"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "mark_notifications_as_read",
|
||||||
|
"translation": "Mark notifications as read"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "notifications_cleared",
|
"id": "notifications_cleared",
|
||||||
"translation": "Notifications erased!"
|
"translation": "Notifications erased!"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "read_notifications_cleared",
|
||||||
|
"translation": "Read notifications erased!"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "notifications_read",
|
||||||
|
"translation": "All notifications marked as read!"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "my_notifications",
|
"id": "my_notifications",
|
||||||
"translation": "My Notifications"
|
"translation": "My Notifications"
|
||||||
|
@ -955,6 +983,10 @@
|
||||||
"id": "delete_report",
|
"id": "delete_report",
|
||||||
"translation": "Delete Report"
|
"translation": "Delete Report"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "delete_all_reports",
|
||||||
|
"translation": "Delete all reports"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "comment_deleted",
|
"id": "comment_deleted",
|
||||||
"translation": "Comment has been deleted!"
|
"translation": "Comment has been deleted!"
|
||||||
|
@ -1927,6 +1959,10 @@
|
||||||
"id": "announcement",
|
"id": "announcement",
|
||||||
"translation": "Announcement"
|
"translation": "Announcement"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "create_anouncement_success",
|
||||||
|
"translation": "Announcement successfully created"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "update_client_failed",
|
"id": "update_client_failed",
|
||||||
"translation": "Update of the client has failed!"
|
"translation": "Update of the client has failed!"
|
||||||
|
@ -2092,8 +2128,8 @@
|
||||||
"translation": "Message"
|
"translation": "Message"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "delay",
|
"id": "duration",
|
||||||
"translation": "Delay"
|
"translation": "Duration (Hours)"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "update_annoucement_panel",
|
"id": "update_annoucement_panel",
|
||||||
|
@ -2179,6 +2215,10 @@
|
||||||
"id": "search_from_specific_user",
|
"id": "search_from_specific_user",
|
||||||
"translation": "Search from %s"
|
"translation": "Search from %s"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "browsing_user_torrents",
|
||||||
|
"translation": "Browsing <a href=\"/user/%d/%s\">%s</a>'s torrents"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "hours_minutes_ago",
|
"id": "hours_minutes_ago",
|
||||||
"translation": "{0} hours {1} minutes ago"
|
"translation": "{0} hours {1} minutes ago"
|
||||||
|
@ -2186,6 +2226,21 @@
|
||||||
{
|
{
|
||||||
"id": "days_hours_ago",
|
"id": "days_hours_ago",
|
||||||
"translation": "{0} days {1} hours ago"
|
"translation": "{0} days {1} hours ago"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "status",
|
||||||
|
"translation": "Status"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "event",
|
||||||
|
"translation": "Event"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "read",
|
||||||
|
"translation": "Read"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "unread",
|
||||||
|
"translation": "Unread"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -73,6 +73,11 @@ func ByQuery(c *gin.Context, pagenum int, withUser bool, deleted bool, hidden bo
|
||||||
torrentParam.Hidden = hidden
|
torrentParam.Hidden = hidden
|
||||||
torrentParam.Full = withUser
|
torrentParam.Full = withUser
|
||||||
torrentParam.Deleted = deleted
|
torrentParam.Deleted = deleted
|
||||||
|
|
||||||
|
if torrentParam.Abort {
|
||||||
|
return torrentParam, []models.Torrent{}, 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
if found, ok := cache.C.Get(torrentParam.Identifier()); ok {
|
if found, ok := cache.C.Get(torrentParam.Identifier()); ok {
|
||||||
log.Infof("Retrieve results from Cache in %s", torrentParam.Identifier())
|
log.Infof("Retrieve results from Cache in %s", torrentParam.Identifier())
|
||||||
torrentCache := found.(*TorrentCache)
|
torrentCache := found.(*TorrentCache)
|
||||||
|
|
|
@ -48,6 +48,7 @@ type TorrentParam struct {
|
||||||
Dlsite string
|
Dlsite string
|
||||||
VideoQuality string
|
VideoQuality string
|
||||||
Tags Tags
|
Tags Tags
|
||||||
|
Abort bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Identifier returns a unique identifier for the struct
|
// Identifier returns a unique identifier for the struct
|
||||||
|
@ -136,6 +137,8 @@ func (p *TorrentParam) FromRequest(c *gin.Context) {
|
||||||
user, _, _, err := users.FindByUsername(username)
|
user, _, _, err := users.FindByUsername(username)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
p.UserID = uint32(user.ID)
|
p.UserID = uint32(user.ID)
|
||||||
|
} else {
|
||||||
|
p.Abort = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// For other functions, we need to set userID in the request query
|
// For other functions, we need to set userID in the request query
|
||||||
|
|
|
@ -4,5 +4,5 @@ package announcementValidator
|
||||||
type CreateForm struct {
|
type CreateForm struct {
|
||||||
ID uint `validate:"-"`
|
ID uint `validate:"-"`
|
||||||
Message string `validate:"required,min=5" form:"message"`
|
Message string `validate:"required,min=5" form:"message"`
|
||||||
Delay int `validate:"omitempty,min=1" form:"delay"`
|
Duration int `validate:"omitempty,min=1" form:"duration"`
|
||||||
}
|
}
|
||||||
|
|
Référencer dans un nouveau ticket