diff --git a/main.go b/main.go index bcf1332..8f9b931 100644 --- a/main.go +++ b/main.go @@ -32,7 +32,6 @@ func main() { r := gin.Default() r.LoadHTMLGlob("templates/*") - r.Static("/static", "./public") r.Use(gin.Recovery()) r.Use(middleware.XssPreventionHeaders()) @@ -40,6 +39,8 @@ func main() { r.Use(middleware.OptionsMiddleware()) r.Use(middleware.Ratelimit()) + r.GET("/static/*filepath", routes.StaticContent) + r.GET("/robots.txt", func(c *gin.Context) { c.String(200, "User-agent: *\nDisallow: /") }) diff --git a/public/icons/sort.svg b/public/icons/sort.svg new file mode 100644 index 0000000..774757a --- /dev/null +++ b/public/icons/sort.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/question.css b/public/question.css index 87f54ef..cf25d6c 100644 --- a/public/question.css +++ b/public/question.css @@ -111,6 +111,42 @@ img { margin-bottom: 1rem; } +.answers-header { + display: flex; + justify-content: space-between; + align-items: center; +} + +.answers-header .sorting form { + display: flex; + align-items: center; + gap: .5rem; +} + +.answers-header select { + border: 0; + border-radius: 5px; + padding: 0.5rem; + background-color: var(--meta-bg); + color: var(--text-color); + height: 2rem; +} + +.answers-header button { + width: 2rem; + border: 0; + height: 2rem; + border-radius: 5px; + background-color: var(--meta-bg); + color: var(--text-color); + font-size: 1.5rem; + cursor: pointer; + + display: flex; + justify-content: center; + align-items: center; +} + @media only screen and (max-width: 800px) { body { padding-left: 1rem; diff --git a/src/routes/question.go b/src/routes/question.go index 36d8fdf..0571153 100644 --- a/src/routes/question.go +++ b/src/routes/question.go @@ -21,6 +21,13 @@ import ( var codeBlockRegex = regexp.MustCompile(`(?s)
(.+?)<\/code><\/pre>`)
 var questionCodeBlockRegex = regexp.MustCompile(`(?s)
(.+?)
`) +var soSortValues = map[string]string{ + "votes": "scoredesc", + "trending": "trending", + "newest": "modifieddesc", + "oldest": "createdasc", +} + func ViewQuestion(c *gin.Context) { client := resty.New() @@ -36,7 +43,17 @@ func ViewQuestion(c *gin.Context) { questionTitle := c.Param("title") - soLink := fmt.Sprintf("https://stackoverflow.com/questions/%s/%s", questionId, questionTitle) + sortValue := c.Query("sort_by") + if sortValue == "" { + sortValue = "votes" + } + + soSortValue, ok := soSortValues[sortValue] + if !ok { + soSortValue = soSortValues["votes"] + } + + soLink := fmt.Sprintf("https://stackoverflow.com/questions/%s/%s?answertab=%s", questionId, questionTitle, soSortValue) resp, err := client.R().Get(soLink) if err != nil { @@ -251,6 +268,7 @@ func ViewQuestion(c *gin.Context) { "imagePolicy": imagePolicy, "theme": c.MustGet("theme").(string), "currentUrl": fmt.Sprintf("%s/questions/%s/%s", os.Getenv("APP_URL"), questionId, questionTitle), + "sortValue": sortValue, }) } diff --git a/src/routes/static.go b/src/routes/static.go new file mode 100644 index 0000000..b5934a3 --- /dev/null +++ b/src/routes/static.go @@ -0,0 +1,14 @@ +package routes + +import ( + "fmt" + "strings" + + "github.com/gin-gonic/gin" +) + +func StaticContent(c *gin.Context) { + cleanFilePath := strings.ReplaceAll(c.Param("filepath"), "..", "") + + c.File(fmt.Sprintf("./public/%s", cleanFilePath)) +} diff --git a/templates/question.html b/templates/question.html index 57cb8eb..d62bc50 100644 --- a/templates/question.html +++ b/templates/question.html @@ -38,13 +38,30 @@

{{ .question.Body }}
- {{ if .question.Comments }} - {{ template "comments.html" .question }} - {{end}} - + {{ if .question.Comments }} {{ template "comments.html" + .question }} {{end}}
-

Answers

+
+

Answers

+
+
+ + +
+
+
{{ range $answer := .answers }}
- {{ if $answer.Comments }} - {{ template "comments.html" $answer }} + {{ if $answer.Comments }} {{ template "comments.html" $answer }} {{end}}