From 835e85b5ce9921ffd4d50b90b706e02685167331 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Justin=20Nu=C3=9F?= <nuss.justin@gmail.com>
Date: Thu, 24 Jul 2014 22:31:59 +0200
Subject: [PATCH] Fix #281. Add mouse-over precise time and on-click switch
 listener.

---
 conf/app.ini               |  6 +++++
 modules/base/tool.go       | 10 +++++--
 modules/setting/setting.go | 53 ++++++++++++++++++++++++++++++++++++++
 public/js/app.js           | 14 ++++++++++
 4 files changed, 81 insertions(+), 2 deletions(-)

diff --git a/conf/app.ini b/conf/app.ini
index 96e320375b..77090c46f0 100644
--- a/conf/app.ini
+++ b/conf/app.ini
@@ -192,6 +192,12 @@ MAX_SIZE
 ; Max number of files per upload. Defaults to 10
 MAX_FILES =
 
+[time]
+; Specifies the format for fully outputed dates. Defaults to RFC1123
+; Special supported values are ANSIC, UnixDate, RubyDate, RFC822, RFC822Z, RFC850, RFC1123, RFC1123Z, RFC3339, RFC3339Nano, Kitchen, Stamp, StampMilli, StampMicro and StampNano
+; For more information about the format see http://golang.org/pkg/time/#pkg-constants
+FORMAT = 
+
 [log]
 ROOT_PATH =
 ; Either "console", "file", "conn", "smtp" or "database", default is "console"
diff --git a/modules/base/tool.go b/modules/base/tool.go
index 9635f13e0f..f2a4059a6c 100644
--- a/modules/base/tool.go
+++ b/modules/base/tool.go
@@ -12,6 +12,7 @@ import (
 	"encoding/hex"
 	"fmt"
 	"hash"
+	"html/template"
 	"math"
 	"strconv"
 	"strings"
@@ -239,8 +240,8 @@ func TimeSincePro(then time.Time) string {
 	return strings.TrimPrefix(timeStr, ", ")
 }
 
-// TimeSince calculates the time interval and generate user-friendly string.
-func TimeSince(then time.Time) string {
+// timeSince calculates the time interval and generate user-friendly string.
+func timeSince(then time.Time) string {
 	now := time.Now()
 
 	lbl := "ago"
@@ -290,6 +291,11 @@ func TimeSince(then time.Time) string {
 	}
 }
 
+// TimeSince calculates the time interval and generate user-friendly string.
+func TimeSince(t time.Time) template.HTML {
+	return template.HTML(fmt.Sprintf(`<span class="time-since" title="%s">%s</span>`, t.Format(setting.TimeFormat), timeSince(t)))
+}
+
 const (
 	Byte  = 1
 	KByte = Byte * 1024
diff --git a/modules/setting/setting.go b/modules/setting/setting.go
index 48b17f95cf..06c6b0e8af 100644
--- a/modules/setting/setting.go
+++ b/modules/setting/setting.go
@@ -11,6 +11,7 @@ import (
 	"path"
 	"path/filepath"
 	"strings"
+	"time"
 
 	"github.com/Unknwon/com"
 	"github.com/Unknwon/goconfig"
@@ -78,6 +79,9 @@ var (
 	AttachmentMaxFiles     int
 	AttachmentEnabled      bool
 
+	// Time settings.
+	TimeFormat string
+
 	// Cache settings.
 	Cache        cache.Cache
 	CacheAdapter string
@@ -179,6 +183,55 @@ func NewConfigContext() {
 	AttachmentMaxFiles = Cfg.MustInt("attachment", "MAX_FILES", 10)
 	AttachmentEnabled = Cfg.MustBool("attachment", "ENABLE", true)
 
+	TimeFormat = Cfg.MustValue("time", "FORMAT", time.RFC1123)
+
+	switch TimeFormat {
+	case "ANSIC":
+		TimeFormat = time.ANSIC
+
+	case "UnixDate":
+		TimeFormat = time.UnixDate
+
+	case "RubyDate":
+		TimeFormat = time.RubyDate
+
+	case "RFC822":
+		TimeFormat = time.RFC822
+
+	case "RFC822Z":
+		TimeFormat = time.RFC822Z
+
+	case "RFC850":
+		TimeFormat = time.RFC850
+
+	case "RFC1123":
+		TimeFormat = time.RFC1123
+
+	case "RFC1123Z":
+		TimeFormat = time.RFC1123Z
+
+	case "RFC3339":
+		TimeFormat = time.RFC3339
+
+	case "RFC3339Nano":
+		TimeFormat = time.RFC3339Nano
+
+	case "Kitchen":
+		TimeFormat = time.Kitchen
+
+	case "Stamp":
+		TimeFormat = time.Stamp
+
+	case "StampMilli":
+		TimeFormat = time.StampMilli
+
+	case "StampMicro":
+		TimeFormat = time.StampMicro
+
+	case "StampNano":
+		TimeFormat = time.StampNano
+	}
+
 	if err = os.MkdirAll(AttachmentPath, os.ModePerm); err != nil {
 		log.Fatal("Could not create directory %s: %s", AttachmentPath, err)
 	}
diff --git a/public/js/app.js b/public/js/app.js
index 7ffcbd4a3e..cdc7d26b0d 100644
--- a/public/js/app.js
+++ b/public/js/app.js
@@ -960,6 +960,18 @@ function initOrganization() {
     console.log("init script : organization done");
 }
 
+function initTimeSwitch() {
+    $(".time-since[title]").on("click", function() {
+        var $this = $(this);
+
+        var title = $this.attr("title");
+        var text = $this.text();
+
+        $this.text(title);
+        $this.attr("title", text);
+    });
+}
+
 (function ($) {
     $(function () {
         initCore();
@@ -988,6 +1000,8 @@ function initOrganization() {
         if ($('#body-nav').hasClass("org-nav")) {
             initOrganization();
         }
+
+        initTimeSwitch();
     });
 })(jQuery);