Albirew/nyaa-pantsu
Albirew
/
nyaa-pantsu
Archivé
1
0
Bifurcation 0

Merge pull request #1698 from NyaaPantsu/fix

Redesign of notification page, lots of fixes & lots of improvements
Cette révision appartient à :
kilo 2017-11-02 04:45:40 +01:00 révisé par GitHub
révision 6f47f1b77d
Signature inconnue de Forgejo
ID de la clé GPG: 4AEE18F83AFDEB23
52 fichiers modifiés avec 693 ajouts et 331 suppressions

Voir le fichier

@ -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)

Voir le fichier

@ -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)
}

Voir le fichier

@ -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")
}

Voir le fichier

@ -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() {

Voir le fichier

@ -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)

Voir le fichier

@ -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
}

Voir le fichier

@ -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")

Voir le fichier

@ -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

Voir le fichier

@ -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)
}

Voir le fichier

@ -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 {

Voir le fichier

@ -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()

Voir le fichier

@ -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

Voir le fichier

@ -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
}
}

Voir le fichier

@ -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")

Voir le fichier

@ -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
}

Voir le fichier

@ -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(),

Voir le fichier

@ -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,
) {

Voir le fichier

@ -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
}

Voir le fichier

@ -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 {

Voir le fichier

@ -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;
}

Voir le fichier

@ -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;
}

BIN
public/img/avatar_130.jpg Fichier normal

Fichier binaire non affiché.

Après

Largeur:  |  Hauteur:  |  Taille: 14 KiB

BIN
public/img/avatar_50.jpg Fichier normal

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

Voir le fichier

@ -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 {

Voir le fichier

@ -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}}

Voir le fichier

@ -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>

Voir le fichier

@ -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}}

Voir le fichier

@ -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>

Voir le fichier

@ -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>

Voir le fichier

@ -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()}}

Voir le fichier

@ -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>

Voir le fichier

@ -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>

Voir le fichier

@ -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>

Voir le fichier

@ -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 }}

Voir le fichier

@ -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>

Voir le fichier

@ -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 }}">

Voir le fichier

@ -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>

Voir le fichier

@ -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>

Voir le fichier

@ -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) {

Voir le fichier

@ -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}}

Voir le fichier

@ -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>

Voir le fichier

@ -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)
}

Voir le fichier

@ -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")]

Voir le fichier

@ -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)
}
}
}

Voir le fichier

@ -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 {

Voir le fichier

@ -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

Voir le fichier

@ -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"
}
]

Voir le fichier

@ -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)

Voir le fichier

@ -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

Voir le fichier

@ -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"`
}