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)
|
||||
}
|
||||
}
|
||||
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{
|
||||
ID: announcement.ID,
|
||||
Message: announcement.Content,
|
||||
Delay: delay,
|
||||
Duration: duration,
|
||||
}
|
||||
c.Bind(form)
|
||||
if form.Delay == 0 {
|
||||
form.Delay = delay
|
||||
if form.Duration == 0 {
|
||||
form.Duration = duration
|
||||
}
|
||||
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
|
||||
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 {
|
||||
// Error, we add it as a message
|
||||
messages.AddErrorT("errors", "create_failed")
|
||||
|
@ -120,7 +121,7 @@ func postAnnouncement(c *gin.Context) {
|
|||
|
||||
// deleteAnnouncement : Controller for deleting an announcement
|
||||
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))
|
||||
if err != nil {
|
||||
c.AbortWithStatus(http.StatusNotFound)
|
||||
|
|
|
@ -146,7 +146,7 @@ func torrentManyAction(c *gin.Context) {
|
|||
query.Append("torrent_id", torrentID)
|
||||
reports, _, _ := reports.FindOrderBy(query, "", 0, 0)
|
||||
for _, report := range reports {
|
||||
report.Delete(false)
|
||||
report.Delete()
|
||||
}
|
||||
messages.AddInfoTf("infos", "torrent_reports_deleted", torrent.Name)
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package moderatorController
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"html"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
@ -39,13 +38,16 @@ func TorrentReportListPanel(c *gin.Context) {
|
|||
func TorrentReportDeleteModPanel(c *gin.Context) {
|
||||
id := c.PostForm("id")
|
||||
|
||||
fmt.Println(id)
|
||||
idNum, _ := strconv.ParseUint(id, 10, 64)
|
||||
_, _, _ = reports.Delete(uint(idNum))
|
||||
/* 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)
|
||||
if c.Request.URL.Query()["all"] != nil {
|
||||
reports.DeleteAll()
|
||||
} else {
|
||||
idNum, _ := strconv.ParseUint(id, 10, 64)
|
||||
_, _, _ = reports.Delete(uint(idNum))
|
||||
/* 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")
|
||||
}
|
||||
|
|
|
@ -129,26 +129,19 @@ func TorrentDeleteModPanel(c *gin.Context) {
|
|||
var err error
|
||||
if definitely != nil {
|
||||
_, _, 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"
|
||||
} else {
|
||||
_, _, 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 torrent.Uploader == nil {
|
||||
torrent.Uploader = &models.User{}
|
||||
|
@ -176,7 +169,7 @@ func DeleteTagsModPanel(c *gin.Context) {
|
|||
|
||||
// TorrentBlockModPanel : Controller to lock torrents, redirecting to previous page
|
||||
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))
|
||||
var returnRoute, action string
|
||||
if torrent.IsDeleted() {
|
||||
|
|
|
@ -21,7 +21,7 @@ func ReportTorrentHandler(c *gin.Context) {
|
|||
messages := msg.GetMessages(c)
|
||||
captchaError := "?reported"
|
||||
currentUser := router.GetUser(c)
|
||||
if currentUser.NeedsCaptcha() {
|
||||
if currentUser.ID == 0 {
|
||||
userCaptcha := captcha.Extract(c)
|
||||
if !captcha.Authenticate(userCaptcha) {
|
||||
captchaError = "?badcaptcha"
|
||||
|
@ -33,7 +33,11 @@ func ReportTorrentHandler(c *gin.Context) {
|
|||
messages.Error(err)
|
||||
}
|
||||
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)
|
||||
if err != nil {
|
||||
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)})
|
||||
|
||||
//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
|
||||
}
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ func TorrentDeleteUserPanel(c *gin.Context) {
|
|||
query.Append("torrent_id", id)
|
||||
torrentReports, _, _ := reports.FindOrderBy(query, "", 0, 0)
|
||||
for _, report := range torrentReports {
|
||||
report.Delete(false)
|
||||
report.Delete()
|
||||
}
|
||||
}
|
||||
c.Redirect(http.StatusSeeOther, "/?deleted")
|
||||
|
|
|
@ -40,9 +40,9 @@ func ViewHandler(c *gin.Context) {
|
|||
// Retrieve the torrent
|
||||
torrent, err := torrents.FindByID(uint(id))
|
||||
|
||||
// If come from notification, toggle the notification as read
|
||||
if c.Request.URL.Query()["notif"] != nil && user.ID > 0 {
|
||||
notifications.ToggleReadNotification(torrent.Identifier(), user.ID)
|
||||
// Toggle the notifications related to this torrent as read
|
||||
if user.ID > 0 {
|
||||
notifications.ToggleReadNotification(torrent.Identifier(), user)
|
||||
}
|
||||
|
||||
// If torrent not found, display 404
|
||||
|
|
|
@ -15,7 +15,7 @@ func UserFollowHandler(c *gin.Context) {
|
|||
id, _ := strconv.ParseUint(c.Param("id"), 10, 32)
|
||||
currentUser := router.GetUser(c)
|
||||
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)) {
|
||||
followAction = "followed"
|
||||
currentUser.SetFollow(user)
|
||||
|
@ -28,5 +28,8 @@ func UserFollowHandler(c *gin.Context) {
|
|||
if c.Query("id") != "" {
|
||||
url = "/view/" + c.Query("id") + "?" + followAction
|
||||
}
|
||||
if currentUser.ID == 0 {
|
||||
url = "/login"
|
||||
}
|
||||
c.Redirect(http.StatusSeeOther, url)
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@ import (
|
|||
"net/http"
|
||||
|
||||
"github.com/NyaaPantsu/nyaa/controllers/router"
|
||||
"github.com/NyaaPantsu/nyaa/models"
|
||||
"github.com/NyaaPantsu/nyaa/models/notifications"
|
||||
"github.com/NyaaPantsu/nyaa/models/users"
|
||||
"github.com/NyaaPantsu/nyaa/templates"
|
||||
|
@ -190,9 +189,13 @@ func UserProfileFormHandler(c *gin.Context) {
|
|||
validator.ValidateForm(&userForm, messages)
|
||||
if !messages.HasErrors() {
|
||||
if userForm.Email != userProfile.Email {
|
||||
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
|
||||
if currentUser.HasAdmin() {
|
||||
userProfile.Email = userForm.Email
|
||||
} 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))
|
||||
if err != nil {
|
||||
|
@ -204,6 +207,7 @@ func UserProfileFormHandler(c *gin.Context) {
|
|||
}
|
||||
if !messages.HasErrors() {
|
||||
messages.AddInfoT("infos", "profile_updated")
|
||||
userProfile = user
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -215,11 +219,13 @@ func UserProfileFormHandler(c *gin.Context) {
|
|||
func UserNotificationsHandler(c *gin.Context) {
|
||||
currentUser := router.GetUser(c)
|
||||
if currentUser.ID > 0 {
|
||||
messages := msg.GetMessages(c)
|
||||
if c.Request.URL.Query()["clear"] != nil {
|
||||
notifications.DeleteAllNotifications(currentUser.ID)
|
||||
messages.AddInfoT("infos", "notifications_cleared")
|
||||
currentUser.Notifications = []models.Notification{}
|
||||
notifications.DeleteNotifications(currentUser, false)
|
||||
|
||||
} 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)
|
||||
} else {
|
||||
|
|
|
@ -12,6 +12,9 @@ import (
|
|||
// When a new comment is added this is called
|
||||
func NewCommentEvent(comment *models.Comment, torrent *models.Torrent) {
|
||||
comment.Torrent = torrent
|
||||
if comment.UserID == torrent.UploaderID {
|
||||
return
|
||||
}
|
||||
url := "/view/" + strconv.FormatUint(uint64(torrent.ID), 10)
|
||||
if torrent.UploaderID > 0 {
|
||||
torrent.Uploader.ParseSettings()
|
||||
|
|
|
@ -15,13 +15,14 @@ type Notification struct {
|
|||
Identifier string
|
||||
URL string
|
||||
Expire time.Time
|
||||
Date time.Time
|
||||
UserID uint
|
||||
// User *User `gorm:"AssociationForeignKey:UserID;ForeignKey:user_id"` // Don't think that we need it here
|
||||
}
|
||||
|
||||
// NewNotification : Create a new 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
|
||||
|
|
|
@ -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
|
||||
func ToggleReadNotification(identifier string, id uint) { //
|
||||
models.ORM.Model(&models.Notification{}).Where("identifier = ? AND user_id = ?", identifier, id).Updates(models.Notification{Read: true})
|
||||
func ToggleReadNotification(identifier string, user *models.User) { //
|
||||
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
|
||||
func DeleteAllNotifications(id uint) { //
|
||||
models.ORM.Where("user_id = ?", id).Delete(&models.Notification{})
|
||||
// MarkAllNotificationsAsRead : Force every notification as read
|
||||
func MarkAllNotificationsAsRead(user *models.User) { //
|
||||
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
|
||||
func UpdateAnnouncement(announcement *models.Notification, form *announcementValidator.CreateForm) error {
|
||||
announcement.Content = form.Message
|
||||
if form.Delay > 0 {
|
||||
announcement.Expire = time.Now().AddDate(0, 0, form.Delay)
|
||||
if form.Duration > 0 {
|
||||
announcement.Expire = time.Now().Add(time.Hour * time.Duration(form.Duration))
|
||||
}
|
||||
if models.ORM.Model(announcement).UpdateColumn(announcement).Error != nil {
|
||||
return errors.New("Announcement was not updated")
|
||||
|
|
|
@ -11,8 +11,9 @@ import (
|
|||
// User can be null (anonymous reports)
|
||||
// FIXME can't preload field Torrents for models.TorrentReport
|
||||
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"`
|
||||
Message string `gorm:"column:message"`
|
||||
TorrentID uint `gorm:"column:torrent_id"`
|
||||
UserID uint `gorm:"column:user_id"`
|
||||
|
||||
|
@ -31,6 +32,7 @@ func (report TorrentReport) TableName() string {
|
|||
type TorrentReportJSON struct {
|
||||
ID uint `json:"id"`
|
||||
Description string `json:"description"`
|
||||
Message string `json:"message"`
|
||||
Torrent TorrentJSON `json:"torrent"`
|
||||
User UserJSON `json:"user"`
|
||||
}
|
||||
|
@ -45,7 +47,7 @@ func (report *TorrentReport) ToJSON() TorrentReportJSON {
|
|||
if report.User != nil {
|
||||
u = report.User.ToJSON()
|
||||
}
|
||||
json := TorrentReportJSON{report.ID, report.Description, t, u}
|
||||
json := TorrentReportJSON{report.ID, report.Description, report.Message, t, u}
|
||||
return json
|
||||
}
|
||||
|
||||
|
@ -59,9 +61,6 @@ func TorrentReportsToJSON(reports []TorrentReport) []TorrentReportJSON {
|
|||
}
|
||||
|
||||
// Delete : Delete torrent report
|
||||
func (report *TorrentReport) Delete(definitely bool) (int, error) {
|
||||
if definitely {
|
||||
return 0, ORM.Unscoped().Delete(report).Error
|
||||
}
|
||||
return http.StatusOK, nil
|
||||
func (report *TorrentReport) Delete() (int, error) {
|
||||
return http.StatusOK, ORM.Unscoped().Delete(report).Error
|
||||
}
|
||||
|
|
|
@ -7,9 +7,10 @@ import (
|
|||
"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{
|
||||
Description: desc,
|
||||
Message: message,
|
||||
TorrentID: torrent.ID,
|
||||
UserID: user.ID,
|
||||
CreatedAt: time.Now(),
|
||||
|
|
|
@ -20,31 +20,22 @@ type Query interface {
|
|||
Prepend(string, ...interface{})
|
||||
}
|
||||
|
||||
// Delete : Delete a torrent report by id
|
||||
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
|
||||
db := models.ORM
|
||||
if definitely {
|
||||
db = models.ORM.Unscoped()
|
||||
}
|
||||
db := models.ORM.Unscoped()
|
||||
if db.First(&torrentReport, id).RecordNotFound() {
|
||||
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.StatusOK, nil
|
||||
}
|
||||
|
||||
func DeleteAll() {
|
||||
models.ORM.Delete(&models.TorrentReport{})
|
||||
}
|
||||
|
||||
func findOrderBy(parameters Query, orderBy string, limit int, offset int, countAll bool) (
|
||||
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
|
||||
t.Trackers = v.Encode()
|
||||
}
|
||||
|
@ -517,3 +525,12 @@ func (t *Torrent) DeleteTags() {
|
|||
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 {
|
||||
font-size: 9pt;
|
||||
margin: 2px 3px;
|
||||
margin: 0 3px 2px 3px;
|
||||
color: #8a8a8a;
|
||||
}
|
||||
|
||||
|
@ -346,10 +346,11 @@ select.form-input {
|
|||
color: #292929;
|
||||
background: #fd6b6b;
|
||||
padding: 1px 4px;
|
||||
border-radius: 7px;
|
||||
font-size: 10px;
|
||||
font-size: 8px;
|
||||
top: 37px;
|
||||
right: 19px;
|
||||
right: 22px;
|
||||
max-height: 17px;
|
||||
line-height: 10px;
|
||||
}
|
||||
|
||||
#content {
|
||||
|
@ -662,6 +663,9 @@ th {
|
|||
.website-nav table {
|
||||
width: auto;
|
||||
}
|
||||
.website-nav table tr {
|
||||
background: none!important;
|
||||
}
|
||||
.website-nav #nav-category-list {
|
||||
width: 70%;
|
||||
margin-bottom: 7px;
|
||||
|
@ -758,6 +762,9 @@ html, body {
|
|||
.header .h-user>a.nav-btn {
|
||||
padding: 0!important;
|
||||
}
|
||||
.user-avatar span {
|
||||
right: 25px;
|
||||
}
|
||||
.nav-btn.log-in span {
|
||||
display: none;
|
||||
}
|
||||
|
@ -901,6 +908,9 @@ html, body {
|
|||
.header .h-user .user-avatar {
|
||||
margin: 0;
|
||||
}
|
||||
.user-avatar span {
|
||||
right: 20px;
|
||||
}
|
||||
.header .h-user {
|
||||
max-width: 46px;
|
||||
width: auto;
|
||||
|
@ -944,7 +954,9 @@ html, body {
|
|||
.header .h-user .nav-btn {
|
||||
height: 57px;
|
||||
}
|
||||
|
||||
.user-avatar span {
|
||||
right: 14px;
|
||||
}
|
||||
h3 {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
@ -1062,8 +1074,7 @@ html, body {
|
|||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.profile-usertitle-uploadcount span {
|
||||
font-weight: bold;
|
||||
.profile-usertitle-uploadcount b {
|
||||
margin-left: 2px;
|
||||
}
|
||||
|
||||
|
@ -1182,7 +1193,7 @@ html, body {
|
|||
.comment-box {
|
||||
padding: 0 7px;
|
||||
margin: 10px 30px 0 30px;
|
||||
min-height: 70px;
|
||||
min-height: 67px;
|
||||
word-break: break-word;
|
||||
text-align: justify;
|
||||
}
|
||||
|
@ -1191,11 +1202,16 @@ html, body {
|
|||
margin-top: 9px;
|
||||
}
|
||||
|
||||
.comment-box .comment-user {
|
||||
font-size: 12px;
|
||||
.comment-box .comment-userinfo {
|
||||
display: block;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.comment-box span+p img {
|
||||
.comment-box .comment-user {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.comment-userinfo img {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
float: left;
|
||||
|
@ -1215,6 +1231,11 @@ html, body {
|
|||
margin-left: 4px;
|
||||
}
|
||||
|
||||
.comment-content {
|
||||
max-width: 100%;
|
||||
max-height: 500px;
|
||||
}
|
||||
|
||||
.comment-content :last-child {
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
@ -1226,8 +1247,12 @@ html, body {
|
|||
padding-bottom: 5px;
|
||||
}
|
||||
|
||||
.comment-form textarea {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.comment-form h3 {
|
||||
margin-bottom: 8px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.comment-index {
|
||||
|
@ -1276,7 +1301,7 @@ div.profile-content.box>nav>ul>a>li {
|
|||
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;
|
||||
}
|
||||
|
||||
|
@ -1538,7 +1563,9 @@ input.filelist-checkbox:checked+table.table-filelist {
|
|||
.modal-body :first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.modal-body h4 {
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
/* Modal Footer */
|
||||
|
||||
|
@ -1560,7 +1587,7 @@ input.filelist-checkbox:checked+table.table-filelist {
|
|||
margin-top: 7px;
|
||||
padding: 0.7em 1.5em;
|
||||
background: none;
|
||||
border: 1px solid white;
|
||||
border: 1px solid black;
|
||||
border-radius: 3px;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
|
@ -1757,11 +1784,11 @@ input.filelist-checkbox:checked+table.table-filelist {
|
|||
padding: 0 10px 10px;
|
||||
}
|
||||
|
||||
.btn-blue:hover, .btn-red:hover, .btn-green:hover, .btn-orange:hover {
|
||||
[class^="btn-"]:hover {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.btn-blue, .btn-red, .btn-green, .btn-orange {
|
||||
[class^="btn-"] {
|
||||
font-weight: bold;
|
||||
color: white;
|
||||
}
|
||||
|
@ -2196,6 +2223,9 @@ iframe {
|
|||
height: 36px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.adminNav {
|
||||
margin: 12px 0 5px 0px;
|
||||
}
|
||||
|
||||
|
||||
table.multiple-upload {
|
||||
|
@ -2299,6 +2329,11 @@ table.multiple-upload {
|
|||
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 {
|
||||
font-weight: bold;
|
||||
background-color: #ffe0bf;
|
||||
|
@ -2348,6 +2383,61 @@ form.delete-form button.form-input.btn-red {
|
|||
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 */
|
||||
|
||||
html[lang="ja-jp"] .form-refine span.spacing {
|
||||
|
|
|
@ -26,7 +26,7 @@ body, .header {
|
|||
font-family: Arial, sans-serif!important;
|
||||
}
|
||||
.torrent-info-data {
|
||||
width: 59%;
|
||||
width: 52%;
|
||||
}
|
||||
#torrent-view-data {
|
||||
margin-left: 10px;
|
||||
|
@ -37,8 +37,8 @@ body, .header {
|
|||
width: 87%;
|
||||
}
|
||||
|
||||
.comment-box p:nth-child(2) {
|
||||
margin-top: auto;
|
||||
.comment-userinfo {
|
||||
margin-top: 0!important;
|
||||
}
|
||||
|
||||
.form-refine span.spacing {
|
||||
|
@ -54,7 +54,7 @@ body, .header {
|
|||
|
||||
#sort-list-order {
|
||||
width: auto;
|
||||
margin-left: 4px;
|
||||
margin-left: 3px;
|
||||
}
|
||||
|
||||
a {
|
||||
|
@ -63,12 +63,12 @@ a {
|
|||
.sukebei a {
|
||||
color: #660000;
|
||||
}
|
||||
a:hover {
|
||||
a:hover, .h-nav a:hover, .h-nav:active a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.upload-form-table .checkbox-container+input {
|
||||
width: 385px;
|
||||
width: 385px;1
|
||||
}
|
||||
.upload-form-table .table-checkboxes {
|
||||
padding: 3px 0!important;
|
||||
|
@ -95,7 +95,7 @@ th.tr-name a {
|
|||
font-size: 0.9em;
|
||||
}
|
||||
.tr-links {
|
||||
width: 29px;
|
||||
width: 22px;
|
||||
text-align: right;
|
||||
}
|
||||
.tr-links .icon-magnet::before {
|
||||
|
@ -158,7 +158,7 @@ th.tr-name a {
|
|||
}
|
||||
.header .container>div {
|
||||
line-height: 40px;
|
||||
padding: 0 0.2rem;
|
||||
padding: 0 0.4rem;
|
||||
}
|
||||
|
||||
.header .nav-btn {
|
||||
|
@ -245,6 +245,8 @@ select.form-input {
|
|||
}
|
||||
.sukebei .pagination span:hover {
|
||||
background-color: #993333;
|
||||
color: white;
|
||||
font-weight: normal;
|
||||
}
|
||||
.website-nav .pagination p {
|
||||
display: none;
|
||||
|
@ -254,7 +256,7 @@ select.form-input {
|
|||
padding-top: 4px!important;
|
||||
}
|
||||
.website-nav .pagination {
|
||||
padding: .5rem;
|
||||
padding: .5rem 0 0rem 0;
|
||||
font-size: 1em;
|
||||
}
|
||||
.website-nav .pagination a {
|
||||
|
@ -327,7 +329,7 @@ span.comment-index+p {
|
|||
margin-top: 0;
|
||||
}
|
||||
|
||||
span.comment-index+p a {
|
||||
.comment-user {
|
||||
font-weight: bold;
|
||||
padding-top: 2px;
|
||||
font-size: .9em;
|
||||
|
@ -335,12 +337,11 @@ span.comment-index+p a {
|
|||
text-decoration: none;
|
||||
line-height: 22px;
|
||||
}
|
||||
span.comment-index+p a:hover {
|
||||
.comment-user:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.comment-index {
|
||||
margin: 3px 0 0 0;
|
||||
margin: 1px 0;
|
||||
}
|
||||
|
||||
#solution {
|
||||
|
@ -382,6 +383,7 @@ span.comment-index+p a:hover {
|
|||
|
||||
#description-box {
|
||||
font-size: 0.8em;
|
||||
border-radius: 5px;
|
||||
}
|
||||
.form-input {
|
||||
border-color: #c4c4c4 !important;
|
||||
|
@ -395,6 +397,11 @@ span.comment-index+p a:hover {
|
|||
width: 24px;
|
||||
margin-top: 8px;
|
||||
}
|
||||
.user-avatar span {
|
||||
font-size: 8px;
|
||||
top: 20px;
|
||||
right: 9px;
|
||||
}
|
||||
|
||||
.torrent-info-data.uploader-link {
|
||||
font-weight: bold;
|
||||
|
@ -402,13 +409,16 @@ span.comment-index+p a:hover {
|
|||
.torrent-info-data.uploader-anon {
|
||||
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;
|
||||
}
|
||||
|
||||
#torrent-description-hr {
|
||||
margin-top: 40px;
|
||||
}
|
||||
.torrent-hr {
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.comment-submit h3 {
|
||||
font-size: 1em;
|
||||
|
@ -451,7 +461,7 @@ span.comment-index+p a:hover {
|
|||
float: left;
|
||||
}
|
||||
.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 {
|
||||
opacity: 0.6!important;
|
||||
|
@ -489,12 +499,17 @@ th {
|
|||
td {
|
||||
font-size: 0.9em;
|
||||
padding: 2px 0!important;
|
||||
|
||||
}
|
||||
.results td {
|
||||
.results td, .profile-content td {
|
||||
border-bottom: 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 {
|
||||
color: #106655;
|
||||
}
|
||||
|
@ -558,35 +573,39 @@ td.tr-size {
|
|||
.container.bottom {
|
||||
padding: 5px 10px;
|
||||
padding-top: 0;
|
||||
margin-top: -8px;
|
||||
margin-top: -11px;
|
||||
}
|
||||
.container.bottom .pagination {
|
||||
border-top: none;
|
||||
padding: 0;
|
||||
padding: 0 14px;
|
||||
}
|
||||
.container.bottom .pagination p {
|
||||
margin: 4px 0 6px 0px;
|
||||
margin: 2px 0 4px 0px
|
||||
}
|
||||
.bottom.center {
|
||||
width: 87%;
|
||||
max-width: 1328px;
|
||||
padding: 0 8px;
|
||||
}
|
||||
}
|
||||
.content > .centered {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
#content > .centered {
|
||||
width: 87%;
|
||||
width: 87%;
|
||||
max-width: 1328px;
|
||||
padding: 0 8px;
|
||||
}
|
||||
|
||||
.pagination .active, .pagination .active:hover {
|
||||
background: #fbfbfb;
|
||||
font-weight: bold;
|
||||
background: none!important;
|
||||
font-weight: bold!important;
|
||||
border: none;
|
||||
color: #106655;
|
||||
cursor: text;
|
||||
}
|
||||
.sukebei .pagination .active, .pagination .active:hover {
|
||||
color: #111111!important;
|
||||
}
|
||||
|
||||
a.nav-btn.log-in {
|
||||
|
@ -713,3 +732,49 @@ span.tag {
|
|||
.torrent-info-data #subscribe-link::before, .torrent-info-data #subscribe-link:: after {
|
||||
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 {
|
||||
background-color: #d02727;
|
||||
color: #272727;
|
||||
}
|
||||
|
||||
.header .h-user .user-menu {
|
||||
|
@ -102,6 +103,9 @@ td.tr-le, .error-text {
|
|||
.sukebei .btn-red {
|
||||
color: #c5c8c6;
|
||||
}
|
||||
.btn-grey {
|
||||
background-color: #777777;
|
||||
}
|
||||
|
||||
.alt-colors tr:nth-child(even) {
|
||||
background: hsla(244, 11%, 21%, 0.2);
|
||||
|
@ -348,5 +352,13 @@ span.tag {
|
|||
}
|
||||
|
||||
#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";
|
||||
|
||||
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
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -11,11 +11,11 @@
|
|||
{{ yield errors(name="Message")}}
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="delay">{{ T("delay")}} ({{ Form.Delay }} {{ T("days") }})</label>
|
||||
<input type="text" name="delay" id="delay" class="form-input up-input" placeholder="{{ T("delay")}}">
|
||||
{{ yield errors(name="Delay")}}
|
||||
<label for="duration">{{ T("duration")}})</label>
|
||||
<input type="text" name="duration" id="duration" class="form-input up-input" value="1">
|
||||
{{ yield errors(name="Duration")}}
|
||||
</div>
|
||||
<button type="submit" class="form-input up-input btn-green">{{ T("save_changes")}}</button>
|
||||
</form>
|
||||
</div>
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
<td class="tr-size home-td">
|
||||
<form method="POST" action="/mod/torrent/delete">
|
||||
<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>
|
||||
</td>
|
||||
</tr>
|
||||
|
@ -33,19 +33,19 @@
|
|||
</tbody>
|
||||
</table>
|
||||
<nav class="adminNav" aria-label="Page navigation">
|
||||
<ul class="pagination">
|
||||
<li><a href="/mod/torrents">{{T("more")}}</a></li>
|
||||
<a href="/mod/torrents">{{T("more")}}</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
<hr />
|
||||
|
||||
<h3 id="torrents">{{ T("last_reports") }}</h3>
|
||||
<table class="table">
|
||||
<table class="torrent-report-table">
|
||||
<thead class="torrent-info">
|
||||
<tr>
|
||||
<th class="tr-name">{{ T("name") }}</th>
|
||||
<th class="tr-actions">{{ T("username") }}</th>
|
||||
<th class="tr-actions">{{ T("reason") }}</th>
|
||||
<th class="td-report-message">{{ T("message") }}</th>
|
||||
<th class="tr-actions">{{ T("actions") }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
@ -58,6 +58,7 @@
|
|||
</td>
|
||||
<td class="tr-size home-td">{{.User.Username}}</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">
|
||||
<form method="POST" action="/mod/report/delete" >
|
||||
<input type="hidden" name="id" value="{{ .ID }}">
|
||||
|
@ -69,9 +70,7 @@
|
|||
</tbody>
|
||||
</table>
|
||||
<nav class="adminNav" aria-label="Page navigation">
|
||||
<ul class="pagination">
|
||||
<li><a href="/mod/reports">{{ T("more") }}</a></li>
|
||||
</ul>
|
||||
<a href="/mod/reports">{{ T("more") }}</a>
|
||||
</nav>
|
||||
<hr />
|
||||
<h3 id="users">{{ T("last_users") }}</h3>
|
||||
|
@ -91,7 +90,7 @@
|
|||
<td class="tr-size home-td">{{if .ID > 0}}
|
||||
<form method="POST" action="/user/{{.ID}}/{{.Username }}/delete" >
|
||||
{{ 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>
|
||||
{{end}}
|
||||
</td>
|
||||
|
@ -100,8 +99,7 @@
|
|||
</tbody>
|
||||
</table>
|
||||
<nav class="adminNav" aria-label="Page navigation">
|
||||
<ul class="pagination">
|
||||
<li><a href="/mod/users">{{ T("more") }} </a></li>
|
||||
<a href="/mod/users">{{ T("more") }} </a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
<hr />
|
||||
|
@ -136,8 +134,7 @@
|
|||
</tbody>
|
||||
</table>
|
||||
<nav class="adminNav" aria-label="Page navigation">
|
||||
<ul class="pagination">
|
||||
<li><a href="/mod/comments">{{ T("more") }}</a></li>
|
||||
<a href="/mod/comments">{{ T("more") }}</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
|
|
|
@ -3,12 +3,13 @@
|
|||
{{ block content_body()}}
|
||||
<div class="results box">
|
||||
<h1>{{ T("reports_list") }}</h1>
|
||||
<table class="table">
|
||||
<table class="torrent-report-table">
|
||||
<thead class="torrent-info">
|
||||
<tr>
|
||||
<th class="tr-name">{{ T("name") }}</th>
|
||||
<th class="tr-actions">{{ T("username") }}</th>
|
||||
<th class="tr-actions">{{ T("reason") }}</th>
|
||||
<th class="td-report-message">{{ T("message") }}</th>
|
||||
<th class="tr-actions">{{ T("actions") }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
@ -21,10 +22,11 @@
|
|||
</td>
|
||||
<td class="tr-size home-td">{{.User.Username}}</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">
|
||||
<form method="POST" action="/mod/torrent/delete">
|
||||
<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 method="POST" action="/mod/report/delete">
|
||||
<input type="hidden" name="id" value="{{ .ID }}">
|
||||
|
@ -35,5 +37,9 @@
|
|||
{{end}}
|
||||
</tbody>
|
||||
</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>
|
||||
{{end}}
|
||||
|
|
|
@ -54,18 +54,15 @@
|
|||
{{ .Uploader.Username }}
|
||||
</a> {{ else }}れんちょん{{end}}
|
||||
</td>
|
||||
<td class="tr-actions home-td">
|
||||
<a href="/torrent/block?id={{ .ID }}" class="form-input btn-orange" onclick="if (!confirm('{{ T(" are_you_sure ")}}')) return false;">
|
||||
{{ if .IsBlocked }}
|
||||
{{ T("torrent_unblock") }}
|
||||
{{else}}
|
||||
{{ T("torrent_block") }}
|
||||
{{end}}
|
||||
</a>
|
||||
<td class="tr-actions home-td"> <form></form>
|
||||
<form method="POST" action="/mod/torrent/block" class="delete-form">
|
||||
<input type="hidden" name="id" value="{{ .ID }}">
|
||||
<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>
|
||||
</form>
|
||||
<form method="POST" action="/mod/torrent/delete" class="delete-form">
|
||||
<input type="hidden" name="id" value="{{ .ID }}">
|
||||
{{ 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>
|
||||
|
||||
</td>
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
{{if .ID > 0}}
|
||||
<form method="POST" action="/user/{{.ID}}/{{.Username }}/delete">
|
||||
{{ 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>
|
||||
{{end}}
|
||||
</td>
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
{{block menu()}}{{end}}
|
||||
</nav>
|
||||
<div id="header-height-offset"></div>
|
||||
{{ AdType := kilo_rand(2) }}
|
||||
{{ AdType := rand(2) }}
|
||||
<div id="content" class="{{ block contclass()}}{{end}}">
|
||||
<div class="content container center">
|
||||
{{ yield infos()}}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{{block ad_wide(Type=0)}}
|
||||
{{ if !kilo_strcmp(URL.String(), "/mod", 4, 1) }}
|
||||
{{ if !strcmp(URL.String(), "/mod", 4, 1) }}
|
||||
{{if Type == 0}}
|
||||
{{ aAdsId := Sukebei() ? 634159 : 634157 }}
|
||||
<iframe data-aa='{{aAdsId}}' src='//ad.a-ads.com/{{aAdsId}}?size=728x90' scrolling='no'></iframe>
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
<button href="#" class="nav-btn">
|
||||
<div class="user-avatar small">
|
||||
<img src="https://www.gravatar.com/avatar/{{ User.MD5 }}?s=50"/>
|
||||
{{if User.GetUnreadNotifications() > 0}}<span>{{User.GetUnreadNotifications()}}</span>{{end}}
|
||||
</div>
|
||||
<span class="user-info" title="{{ User.Username}}">
|
||||
<span class="hide-md">{{User.Username}}</span>
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
<tr>
|
||||
{{end}}
|
||||
{{if _ + 1 == len(GetCategories(true, false)) }}
|
||||
{{ if _% 3 != 2}}{{ if _% 3 == 0}}<td></td>{{end}}<td></td>{{end}}
|
||||
</tr>{{end}}
|
||||
{{ end }}
|
||||
</tr>
|
||||
|
@ -44,6 +45,9 @@
|
|||
</tr>
|
||||
</tbody>
|
||||
</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">
|
||||
{{ genNav(Navigation, URL, 33)|raw }}
|
||||
</div>
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
{{ if isset(treeviewData)}}
|
||||
{{ range index, folder := treeviewData.Folder.Folders }}
|
||||
{{ folderId := treeviewData.IdentifierChain+"_"+index }}
|
||||
<tr class="tr-filelist tr-folder" style="padding-left: {{ treeviewData.NestLevel * 2.5 }}%;">
|
||||
<td><label for="contents_{{folderId}}">{{folder.FolderName}}</label></td>
|
||||
<tr class="tr-filelist tr-folder>
|
||||
<td style="padding-left: {{ treeviewData.NestLevel * 2.5 }}%;"><label for="contents_{{folderId}}">{{folder.FolderName}}</label></td>
|
||||
<td>{{ fileSize(folder.TotalSize(), T) }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
@ -19,7 +19,7 @@
|
|||
{{ range _, file := treeviewData.Folder.Files }}
|
||||
<tr class="tr-filelist tr-file">
|
||||
<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>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
<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/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/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/announcement")}}" class="nav-btn{{if kilo_strcmp(URL.String(), "/mod/announcement", 17, 5) }} active{{end}}">{{ T("announcements")}}</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 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/reassign")}}" class="nav-btn{{if URL.String() == "/mod/reassign"}} active{{end}}">{{ T("torrent_reassign")}}</a>
|
||||
</div>
|
||||
|
|
|
@ -13,19 +13,21 @@
|
|||
<p class="profile-usertitle-job">
|
||||
{{T(UserProfile.GetRole())}}
|
||||
</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>
|
||||
<!-- END SIDEBAR USER TITLE -->
|
||||
<!-- SIDEBAR BUTTONS -->
|
||||
<div class="profile-usermenu">
|
||||
{{if User.ID > 0 }}
|
||||
{{if !User.CurrentUserIdentical(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>
|
||||
{{else}}
|
||||
<a class="form-input" href="/user/{{UserProfile.ID}}/{{UserProfile.Username}}/follow" class="form-input btn-orange">{{ T("unfollow")}}</a>
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{if UserProfile.ID > 0 && !User.CurrentUserIdentical(UserProfile.ID) }}
|
||||
{{if User.ID > 0 }}
|
||||
{{if !User.IsFollower(UserProfile.ID)}}
|
||||
<a class="form-input" href="/user/{{UserProfile.ID}}/{{UserProfile.Username}}/follow" class="form-input btn-green">{{ T("follow")}}</a>
|
||||
{{else}}
|
||||
<a class="form-input" href="/user/{{UserProfile.ID}}/{{UserProfile.Username}}/follow" class="form-input btn-orange">{{ T("unfollow")}}</a>
|
||||
{{end}}
|
||||
{{else}}
|
||||
<a class="form-input" href="/login?redirectTo=/user/{{UserProfile.ID}}/{{UserProfile.Username}}/follow">{{T("follow")}}</a>
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{ if User.ID > 0 && (User.CurrentUserIdentical(UserProfile.ID) || User.CurrentOrAdmin(UserProfile.ID)) }}
|
||||
<a class="form-input btn-green" href="/user/{{ UserProfile.ID }}/{{ UserProfile.Username }}">
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{{ extends "layouts/index_site" }}
|
||||
{{ 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 content_body()}}
|
||||
{{ if OldNav || Theme == "classic"}}
|
||||
|
@ -91,7 +91,7 @@
|
|||
</a>
|
||||
</td>
|
||||
<td class="tr-size home-td hide-xs">
|
||||
{{ fileSize(.Filesize, T) }}
|
||||
{{ fileSize(.Filesize, T, true) }}
|
||||
</td>
|
||||
{{if .StatsObsolete[0] }}
|
||||
<td class="tr-se home-td hide-smol">-</td>
|
||||
|
|
|
@ -50,10 +50,10 @@
|
|||
</div>
|
||||
<div class="table-checkboxes">
|
||||
<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 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>
|
||||
</td>
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
{{block title()}}{{Torrent.Name}}{{end}}
|
||||
{{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 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>
|
||||
</div>
|
||||
<br/>
|
||||
|
@ -28,8 +28,14 @@
|
|||
{{else}}
|
||||
<td class="torrent-view-td torrent-info-data uploader-link">
|
||||
{{ 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}}
|
||||
</td>
|
||||
{{if !Torrent.Hidden && Torrent.UploaderID != User.ID && Torrent.UploaderID != 0}}
|
||||
{{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}}
|
||||
</tr>
|
||||
|
||||
|
@ -46,7 +52,7 @@
|
|||
</tr>
|
||||
<tr class="torrent-info-row">
|
||||
<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>
|
||||
{{ if len(Torrent.Languages) > 0 && Torrent.Languages[0] != "" }}
|
||||
<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;">
|
||||
<div class="icon-floppy"></div>{{ T("torrent_file")}}
|
||||
</a>
|
||||
{{ if User.ID > 0}}
|
||||
<a id="reportPopup" href="#" class="form-input">{{ T("report_btn") }}</a>
|
||||
{{ if User.ID > 0}}
|
||||
{{ if User.HasAdmin()}}
|
||||
<form method="POST" action="/mod/torrent/delete" class="delete-form">
|
||||
{{ yield csrf_field()}}
|
||||
|
@ -211,11 +217,12 @@
|
|||
<div class="torrent-info-box comment-box">
|
||||
<span class="comment-index">
|
||||
<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>
|
||||
<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}}
|
||||
<span class="comment-user">れんちょん</span>{{end}}
|
||||
<span class="comment-user">れんちょん</span>{{end}}
|
||||
</span>
|
||||
<div class="comment-content">{{element.Content|raw}}</div>
|
||||
</div>
|
||||
{{idx = idx + 1}}
|
||||
|
@ -233,6 +240,7 @@
|
|||
<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>
|
||||
<textarea style="height: 10rem;" placeholder="サンキュー" name="comment" class="form-input up-input"></textarea>
|
||||
<p class="not-important">{{T("comment_markdown_notice")}}</p>
|
||||
</div>
|
||||
<div class="comment-captcha">
|
||||
{{ yield captcha(captchaid=CaptchaID)}}
|
||||
|
@ -243,7 +251,6 @@
|
|||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{{ if User.ID > 0 }}
|
||||
<!-- Modal to report a torrent -->
|
||||
<div id="modal_mod_tools" class="modal">
|
||||
<!-- Modal content -->
|
||||
|
@ -264,9 +271,15 @@
|
|||
<label for="wrongcat">{{ T("wrong_category") }}</label><br />
|
||||
<input type="radio" name="report_type" value="duplicate_deprecated" id="dup" required/>
|
||||
<label for="dup">{{ T("duplicate_deprecated") }}</label><br />
|
||||
<div class="comment-captcha">
|
||||
{{yield captcha(captchaid=CaptchaID)}}
|
||||
</div>
|
||||
<input type="radio" name="report_type" value="other" id="other"" required/>
|
||||
<label for="other">{{ T("other") }}</label><br />
|
||||
<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 class="modal-footer">
|
||||
<span>
|
||||
|
@ -278,6 +291,7 @@
|
|||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{{ if User.ID > 0 }}
|
||||
<!-- Modal to add a tag -->
|
||||
<div id="modal_tag_form" class="modal">
|
||||
<!-- Modal content -->
|
||||
|
@ -311,6 +325,14 @@
|
|||
{{end}}
|
||||
{{ block footer_js()}}
|
||||
<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)}}
|
||||
<script type="text/javascript">
|
||||
var torrentLink = document.getElementById("torrent-download-link"),
|
||||
|
@ -338,7 +360,7 @@
|
|||
Query.Get('/download/{{Torrent.Hash}}?js_query=true', function (data) {
|
||||
if(typeof data.exists != "undefined" && data.exists == true) {
|
||||
torrentLink.innerHTML = oldDownloadHtml
|
||||
torrentLink.style.opacity = 1
|
||||
torrentLink.style = torrentLink.style + "opacity: 1!important;filter: grayscale(0);"
|
||||
torrentLink.removeEventListener("click", function (e) {});
|
||||
torrentLink.click();
|
||||
} else {
|
||||
|
@ -381,6 +403,8 @@
|
|||
downloads.innerHTML = oldStats[2]
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
</script>
|
||||
{{end}}
|
||||
{{ if User.ID > 0 }}
|
||||
|
@ -413,7 +437,7 @@ Templates.Add("tag", function(tag) {
|
|||
Modal.Init({
|
||||
elements: document.getElementsByClassName("modal"),
|
||||
// order of apparition of the modals
|
||||
button: ["#reportPopup", "#tagPopup"]
|
||||
button: ["#tagPopup"]
|
||||
});
|
||||
|
||||
document.querySelector("#modal_tag_form form").addEventListener("submit", function(e) {
|
||||
|
|
|
@ -3,25 +3,37 @@
|
|||
{{block title()}}{{ T("profile_edit_page", User.Username) }}{{end}}
|
||||
{{ block profile_navigation()}}{{ yield profile_menu(route="profile") }}{{end}}
|
||||
{{block profile_content()}}
|
||||
{{ if len(User.Notifications) > 0}}
|
||||
<div>
|
||||
<a href="/notifications?clear" class="btn btn-red pull-right"> {{ T("clear_notifications") }}</a>
|
||||
<div style="clear: both;"></div>
|
||||
</div>
|
||||
<table>
|
||||
<table class="notification-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="notification-status">{{T("status")}}</th>
|
||||
<th class="notification-event">Event</th>
|
||||
<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 }}
|
||||
<tr>
|
||||
<td{{ if !.Read }} class="btn-orange"{{end}}>
|
||||
<div style="padding: 0 1rem 1rem;">
|
||||
<a href="{{ .URL }}?notif">
|
||||
<h3>{{ .Content }}</h3>
|
||||
</a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
<tr>
|
||||
<td class="notification-status {{ if !.Read }}notification-unread{{end}}">{{if .Read}}{{T("read")}}{{else}}{{T("unread")}}{{end}}</td>
|
||||
<td class="notification-event">
|
||||
<a href="{{ .URL }}?notif">{{ .Content }}</a>
|
||||
</td>
|
||||
{{if !.Date.IsZero()}}
|
||||
<td class="notification-date date-full" title="{{formatDate(.Date, false)}}">{{formatDate(.Date, false)}}</td>
|
||||
{{else}}
|
||||
<td class="notification-date">{{T("unknown")}}</td>
|
||||
{{end}}
|
||||
</tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
</table>
|
||||
{{else}}
|
||||
<h2>{{ T("no_notifications") }}</h2>
|
||||
{{end}}
|
||||
<div id="clear-notification">
|
||||
<hr/>
|
||||
<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}}
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
</a>
|
||||
</td>
|
||||
<td class="tr-size user-td hide-xs">
|
||||
{{ fileSize(torrent.Filesize, T) }}
|
||||
{{ fileSize(torrent.Filesize, T, true) }}
|
||||
</td>
|
||||
<td class="tr-date user-td date-short hide-smol" title="{{torrent.Date}}">{{formatDate(torrent.FullDate, true)}}</td>
|
||||
</tr>
|
||||
|
|
|
@ -173,9 +173,14 @@ func userProfileBase(c *gin.Context, templateName string, userProfile *models.Us
|
|||
} else {
|
||||
_, 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("NbTorrents", nbTorrents)
|
||||
variables.Set("NbTorrents", []int64{int64(nbTorrents),uploadedSize})
|
||||
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("getAvatar", getAvatar)
|
||||
vars.Set("torrentFileExists", torrentFileExists)
|
||||
vars.Set("formatDateRFC", formatDateRFC)
|
||||
vars.Set("GetHostname", format.GetHostname)
|
||||
vars.Set("GetCategories", categories.GetSelect)
|
||||
vars.Set("GetCategory", getCategory)
|
||||
|
@ -52,10 +51,10 @@ func templateFunctions(vars jet.VarMap) jet.VarMap {
|
|||
vars.Set("genUploaderLink", genUploaderLink)
|
||||
vars.Set("genActivityContent", genActivityContent)
|
||||
vars.Set("contains", contains)
|
||||
vars.Set("toString", toString)
|
||||
vars.Set("kilo_strcmp", kilo_strcmp)
|
||||
vars.Set("kilo_strfind", kilo_strfind)
|
||||
vars.Set("kilo_rand", kilo_rand)
|
||||
vars.Set("strcmp", strcmp)
|
||||
vars.Set("strfind", strfind)
|
||||
vars.Set("rand", rand.Intn)
|
||||
vars.Set("toString", strconv.Itoa)
|
||||
vars.Set("getDomainName", getDomainName)
|
||||
vars.Set("getThemeList", getThemeList)
|
||||
vars.Set("formatThemeName", formatThemeName)
|
||||
|
@ -196,13 +195,16 @@ func flagCode(languageCode string) 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 {
|
||||
cats := categories.GetSelect(true, true)
|
||||
found := false
|
||||
|
@ -251,8 +253,8 @@ func languageNameFromCode(languageCode string, T publicSettings.TemplateTfunc) s
|
|||
}
|
||||
return strings.Title(publicSettings.Translate(languageCode, string(T("language_code"))))
|
||||
}
|
||||
func fileSize(filesize int64, T publicSettings.TemplateTfunc) template.HTML {
|
||||
if filesize == 0 {
|
||||
func fileSize(filesize int64, T publicSettings.TemplateTfunc, showUnknown bool) template.HTML {
|
||||
if showUnknown && filesize == 0 {
|
||||
return T("unknown")
|
||||
}
|
||||
return template.HTML(format.FileSize(filesize))
|
||||
|
@ -348,11 +350,7 @@ func torrentFileExists(hash string, TorrentLink string) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
func toString(number int) string {
|
||||
return strconv.Itoa(number)
|
||||
}
|
||||
|
||||
func kilo_strcmp(str1 string, str2 string, end int, start int) bool {
|
||||
func strcmp(str1 string, str2 string, end int, start int) bool {
|
||||
//Compare two strings but has length arguments
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
//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)
|
||||
}
|
||||
|
||||
func kilo_rand(max int) int {
|
||||
return rand.Intn(max)
|
||||
}
|
||||
|
||||
func getDomainName() string {
|
||||
domain := config.Get().Cookies.DomainName
|
||||
if config.Get().Environment == "DEVELOPMENT" {
|
||||
|
@ -408,7 +402,7 @@ func getThemeList() ([]string) {
|
|||
themeList := []string{}
|
||||
|
||||
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
|
||||
|
||||
fileName := path[len(searchDir):strings.Index(path, ".css")]
|
||||
|
|
|
@ -175,12 +175,12 @@ func TestGetAvatar(t *testing.T) {
|
|||
{
|
||||
Test: "",
|
||||
Size: 0,
|
||||
Expected: "https://www.gravatar.com/avatar/?s=0",
|
||||
Expected: "/img/avatar_0.jpg",
|
||||
},
|
||||
{
|
||||
Test: "",
|
||||
Size: 100,
|
||||
Expected: "https://www.gravatar.com/avatar/?s=100",
|
||||
Expected: "/img/avatar_100.jpg",
|
||||
},
|
||||
{
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
var tests = []struct {
|
||||
|
@ -382,22 +358,35 @@ func TestLanguageNameFromCode(t *testing.T) {
|
|||
func TestFileSize(t *testing.T) {
|
||||
var tests = []struct {
|
||||
TestSize int64
|
||||
TestShowUnknown bool
|
||||
Expected template.HTML
|
||||
}{
|
||||
{
|
||||
TestSize: 0,
|
||||
TestShowUnknown: true,
|
||||
Expected: template.HTML("Unknown"),
|
||||
},
|
||||
{
|
||||
TestSize: 0,
|
||||
TestShowUnknown: false,
|
||||
Expected: template.HTML("0.0 B"),
|
||||
},
|
||||
{
|
||||
TestSize: 10,
|
||||
TestShowUnknown: false,
|
||||
Expected: template.HTML("10.0 B"),
|
||||
},
|
||||
{
|
||||
TestSize: 10,
|
||||
TestShowUnknown: true,
|
||||
Expected: template.HTML("10.0 B"),
|
||||
},
|
||||
}
|
||||
T := mockupTemplateT(t)
|
||||
for _, test := range tests {
|
||||
value := fileSize(test.TestSize, T)
|
||||
value := fileSize(test.TestSize, T, test.TestShowUnknown)
|
||||
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 {
|
||||
TestString string
|
||||
TestString2 string
|
||||
TestEnd int
|
||||
TestStart int
|
||||
Expected bool
|
||||
}{
|
||||
{
|
||||
TestString: "kilo",
|
||||
TestString2: "kilo",
|
||||
TestEnd: -1,
|
||||
TestStart: 0,
|
||||
Expected: true,
|
||||
},
|
||||
{
|
||||
TestString: "kilo",
|
||||
TestString2: "loki", // Clearly not the same level
|
||||
TestString: "kilo",
|
||||
TestString2: "loki",
|
||||
TestEnd: -1,
|
||||
TestStart: 0,
|
||||
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,
|
||||
Expected: "0",
|
||||
TestString: "superkilo", //compare "superkilo" to "kilo"
|
||||
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 {
|
||||
value := toString(test.TestInt)
|
||||
value := 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)
|
||||
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 {
|
||||
TestString string
|
||||
TestString2 string
|
||||
Expected bool
|
||||
TestStart int
|
||||
Match bool
|
||||
}{
|
||||
{
|
||||
TestString: "kilo",
|
||||
TestString2: "kilo",
|
||||
Expected: true,
|
||||
TestStart: 0,
|
||||
Match: true,
|
||||
},
|
||||
{
|
||||
TestString: "kilo",
|
||||
TestString2: "loki", // Clearly not the same level
|
||||
Expected: false,
|
||||
TestString2: "loki",
|
||||
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,
|
||||
TestInt2: 1,
|
||||
Expected: 1,
|
||||
TestString: "akumeme",
|
||||
TestString2: "meme",
|
||||
TestStart: 0,
|
||||
Match: true,
|
||||
},
|
||||
{
|
||||
TestString: "memeaku",
|
||||
TestString2: "meme",
|
||||
TestStart: 4, //Search "meme" in "aku", obviously not there
|
||||
Match: false,
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
value := kilo_rand(1)
|
||||
if value != test.Expected {
|
||||
//t.Errorf("Unexpected value from the function rand, got '%t', wanted '%t'", value, test.Expected)
|
||||
value := strfind(test.TestString, test.TestString2, test.TestStart)
|
||||
if value != test.Match {
|
||||
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) {
|
||||
var tests = []struct {
|
||||
|
@ -741,12 +735,27 @@ func TestRand(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
func testformatThemeName(t *testing.T) {
|
||||
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 {
|
||||
|
@ -758,25 +767,35 @@ func TestRand(t *testing.T) {
|
|||
T = func(id string, args ...interface{}) template.HTML {
|
||||
return template.HTML(fmt.Sprintf(Ts(id), args...))
|
||||
}
|
||||
value := formatThemeName("path", T)
|
||||
if value != test.domainName {
|
||||
|
||||
value := formatThemeName(test.TestPath, T)
|
||||
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) {
|
||||
UTC, _ := time.LoadLocation("")
|
||||
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 {
|
||||
value := formatDate(time.Now(), false)
|
||||
if value != test.domainName {
|
||||
|
||||
value := formatDate(test.TestDate, test.TestFullDate)
|
||||
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{}}
|
||||
fakeLogin := &userValidator.LoginForm{"test", "test", "/", "false"}
|
||||
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}, ""}
|
||||
fakeOauthModel := fakeOauthForm.Bind(&models.OauthClient{})
|
||||
fakeClient := client.Client{"", "", "", []string{""}, []string{""}, []string{""}, "", "", "", "", "", "", []string{""}, false}
|
||||
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{
|
||||
"dumps.jet.html": func(variables jet.VarMap) jet.VarMap {
|
||||
|
@ -85,17 +85,17 @@ func walkDirTest(dir string, t *testing.T) {
|
|||
return variables
|
||||
},
|
||||
"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("Languages", publicSettings.Languages{*fakeLanguage, *fakeLanguage})
|
||||
return variables
|
||||
},
|
||||
"torrents.jet.html": func(variables jet.VarMap) jet.VarMap {
|
||||
variables.Set("NbTorrents", 0)
|
||||
variables.Set("NbTorrents", []int64{0,0})
|
||||
return variables
|
||||
},
|
||||
"profile.jet.html": func(variables jet.VarMap) jet.VarMap {
|
||||
variables.Set("NbTorrents", 0)
|
||||
variables.Set("NbTorrents", []int64{0,0})
|
||||
return variables
|
||||
},
|
||||
"upload.jet.html": func(variables jet.VarMap) jet.VarMap {
|
||||
|
@ -103,7 +103,7 @@ func walkDirTest(dir string, t *testing.T) {
|
|||
return variables
|
||||
},
|
||||
"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("CaptchaID", "xxxxxx")
|
||||
variables.Set("RootFolder", filelist.FileListToFolder(fakeTorrent.FileList, "root"))
|
||||
|
@ -153,7 +153,7 @@ func walkDirTest(dir string, t *testing.T) {
|
|||
return variables
|
||||
},
|
||||
"notifications.jet.html": func(variables jet.VarMap) jet.VarMap {
|
||||
variables.Set("NbTorrents", 0)
|
||||
variables.Set("NbTorrents", []int64{0,0})
|
||||
return variables
|
||||
},
|
||||
"report.jet.html": func(variables jet.VarMap) jet.VarMap {
|
||||
|
|
|
@ -65,3 +65,24 @@
|
|||
## 2017/10/28
|
||||
* + hours_minutes_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",
|
||||
"translation": "Torrents"
|
||||
},
|
||||
{
|
||||
"id": "followers",
|
||||
"translation": "Followers"
|
||||
},
|
||||
{
|
||||
"id": "follow",
|
||||
"translation": "Follow"
|
||||
|
@ -532,8 +536,8 @@
|
|||
"translation": "Torrent Description"
|
||||
},
|
||||
{
|
||||
"id": "description_markdown_notice",
|
||||
"translation": "Markdown can be used in descriptions."
|
||||
"id": "comment_markdown_notice",
|
||||
"translation": "Markdown can be used in comments."
|
||||
},
|
||||
{
|
||||
"id": "show_all",
|
||||
|
@ -775,6 +779,10 @@
|
|||
"id": "report_type",
|
||||
"translation": "Report type"
|
||||
},
|
||||
{
|
||||
"id": "report_message",
|
||||
"translation": "Report message"
|
||||
},
|
||||
{
|
||||
"id": "illegal_content",
|
||||
"translation": "Illegal content"
|
||||
|
@ -791,6 +799,10 @@
|
|||
"id": "duplicate_deprecated",
|
||||
"translation": "Duplicate / Deprecated"
|
||||
},
|
||||
{
|
||||
"id": "other",
|
||||
"translation": "Other"
|
||||
},
|
||||
{
|
||||
"id": "captcha",
|
||||
"translation": "Captcha"
|
||||
|
@ -829,12 +841,28 @@
|
|||
},
|
||||
{
|
||||
"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",
|
||||
"translation": "Notifications erased!"
|
||||
},
|
||||
{
|
||||
"id": "read_notifications_cleared",
|
||||
"translation": "Read notifications erased!"
|
||||
},
|
||||
{
|
||||
"id": "notifications_read",
|
||||
"translation": "All notifications marked as read!"
|
||||
},
|
||||
{
|
||||
"id": "my_notifications",
|
||||
"translation": "My Notifications"
|
||||
|
@ -955,6 +983,10 @@
|
|||
"id": "delete_report",
|
||||
"translation": "Delete Report"
|
||||
},
|
||||
{
|
||||
"id": "delete_all_reports",
|
||||
"translation": "Delete all reports"
|
||||
},
|
||||
{
|
||||
"id": "comment_deleted",
|
||||
"translation": "Comment has been deleted!"
|
||||
|
@ -1927,6 +1959,10 @@
|
|||
"id": "announcement",
|
||||
"translation": "Announcement"
|
||||
},
|
||||
{
|
||||
"id": "create_anouncement_success",
|
||||
"translation": "Announcement successfully created"
|
||||
},
|
||||
{
|
||||
"id": "update_client_failed",
|
||||
"translation": "Update of the client has failed!"
|
||||
|
@ -2092,8 +2128,8 @@
|
|||
"translation": "Message"
|
||||
},
|
||||
{
|
||||
"id": "delay",
|
||||
"translation": "Delay"
|
||||
"id": "duration",
|
||||
"translation": "Duration (Hours)"
|
||||
},
|
||||
{
|
||||
"id": "update_annoucement_panel",
|
||||
|
@ -2179,6 +2215,10 @@
|
|||
"id": "search_from_specific_user",
|
||||
"translation": "Search from %s"
|
||||
},
|
||||
{
|
||||
"id": "browsing_user_torrents",
|
||||
"translation": "Browsing <a href=\"/user/%d/%s\">%s</a>'s torrents"
|
||||
},
|
||||
{
|
||||
"id": "hours_minutes_ago",
|
||||
"translation": "{0} hours {1} minutes ago"
|
||||
|
@ -2186,6 +2226,21 @@
|
|||
{
|
||||
"id": "days_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.Full = withUser
|
||||
torrentParam.Deleted = deleted
|
||||
|
||||
if torrentParam.Abort {
|
||||
return torrentParam, []models.Torrent{}, 0, nil
|
||||
}
|
||||
|
||||
if found, ok := cache.C.Get(torrentParam.Identifier()); ok {
|
||||
log.Infof("Retrieve results from Cache in %s", torrentParam.Identifier())
|
||||
torrentCache := found.(*TorrentCache)
|
||||
|
|
|
@ -48,6 +48,7 @@ type TorrentParam struct {
|
|||
Dlsite string
|
||||
VideoQuality string
|
||||
Tags Tags
|
||||
Abort bool
|
||||
}
|
||||
|
||||
// Identifier returns a unique identifier for the struct
|
||||
|
@ -136,6 +137,8 @@ func (p *TorrentParam) FromRequest(c *gin.Context) {
|
|||
user, _, _, err := users.FindByUsername(username)
|
||||
if err == nil {
|
||||
p.UserID = uint32(user.ID)
|
||||
} else {
|
||||
p.Abort = true
|
||||
}
|
||||
}
|
||||
// For other functions, we need to set userID in the request query
|
||||
|
|
|
@ -4,5 +4,5 @@ package announcementValidator
|
|||
type CreateForm struct {
|
||||
ID uint `validate:"-"`
|
||||
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