This is an automated email from the ASF dual-hosted git repository.
shuai pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/incubator-answer.git
The following commit(s) were added to refs/heads/dev by this push:
new a8e008de feat: Support related and hot questions template
a8e008de is described below
commit a8e008de0702f76733c79ae784357469b4bb496c
Author: sy-records <[email protected]>
AuthorDate: Tue Oct 15 19:20:04 2024 +0800
feat: Support related and hot questions template
---
cmd/wire_gen.go | 2 +-
internal/controller/template_controller.go | 68 ++++++++++++++++++++++--------
ui/template/hot-question.html | 42 ++++++++++++++++++
ui/template/question-detail.html | 10 +++--
ui/template/question.html | 4 +-
ui/template/related-question.html | 42 ++++++++++++++++++
6 files changed, 146 insertions(+), 22 deletions(-)
diff --git a/cmd/wire_gen.go b/cmd/wire_gen.go
index 978ab23b..d8e6c744 100644
--- a/cmd/wire_gen.go
+++ b/cmd/wire_gen.go
@@ -277,7 +277,7 @@ func initApplication(debug bool, serverConf *conf.Server,
dbConf *data.Database,
avatarMiddleware := middleware.NewAvatarMiddleware(serviceConf,
uploaderService)
shortIDMiddleware :=
middleware.NewShortIDMiddleware(siteInfoCommonService)
templateRenderController :=
templaterender.NewTemplateRenderController(questionService, userService,
tagService, answerService, commentService, siteInfoCommonService, questionRepo)
- templateController :=
controller.NewTemplateController(templateRenderController,
siteInfoCommonService, eventQueueService, userService)
+ templateController :=
controller.NewTemplateController(templateRenderController,
siteInfoCommonService, eventQueueService, userService, questionService)
templateRouter := router.NewTemplateRouter(templateController,
templateRenderController, siteInfoController, authUserMiddleware)
connectorController :=
controller.NewConnectorController(siteInfoCommonService, emailService,
userExternalLoginService)
userCenterLoginService :=
user_external_login2.NewUserCenterLoginService(userRepo, userCommon,
userExternalLoginRepo, userActiveActivityRepo, siteInfoCommonService)
diff --git a/internal/controller/template_controller.go
b/internal/controller/template_controller.go
index 56a38f00..5a63e6de 100644
--- a/internal/controller/template_controller.go
+++ b/internal/controller/template_controller.go
@@ -22,6 +22,7 @@ package controller
import (
"encoding/json"
"fmt"
+ "github.com/apache/incubator-answer/internal/base/middleware"
"github.com/apache/incubator-answer/internal/service/content"
"github.com/apache/incubator-answer/internal/service/event_queue"
"github.com/apache/incubator-answer/plugin"
@@ -58,6 +59,7 @@ type TemplateController struct {
siteInfoService siteinfo_common.SiteInfoCommonService
eventQueueService event_queue.EventQueueService
userService *content.UserService
+ questionService *content.QuestionService
}
// NewTemplateController new controller
@@ -66,6 +68,7 @@ func NewTemplateController(
siteInfoService siteinfo_common.SiteInfoCommonService,
eventQueueService event_queue.EventQueueService,
userService *content.UserService,
+ questionService *content.QuestionService,
) *TemplateController {
script, css := GetStyle()
return &TemplateController{
@@ -75,6 +78,7 @@ func NewTemplateController(
siteInfoService: siteInfoService,
eventQueueService: eventQueueService,
userService: userService,
+ questionService: questionService,
}
}
func GetStyle() (script []string, css string) {
@@ -146,6 +150,14 @@ func (tc *TemplateController) Index(ctx *gin.Context) {
return
}
+ hotQuestionReq := &schema.QuestionPageReq{
+ Page: 1,
+ PageSize: 6,
+ OrderCond: "hot",
+ InDays: 7,
+ }
+ hotQuestion, _, _ := tc.templateRenderController.Index(ctx,
hotQuestionReq)
+
siteInfo := tc.SiteInfo(ctx)
siteInfo.Canonical = siteInfo.General.SiteUrl
@@ -156,10 +168,11 @@ func (tc *TemplateController) Index(ctx *gin.Context) {
}
siteInfo.Title = ""
tc.html(ctx, http.StatusOK, "question.html", siteInfo, gin.H{
- "data": data,
- "useTitle": UrlUseTitle,
- "page": templaterender.Paginator(page, req.PageSize, count),
- "path": "questions",
+ "data": data,
+ "useTitle": UrlUseTitle,
+ "page": templaterender.Paginator(page, req.PageSize,
count),
+ "path": "questions",
+ "hotQuestion": hotQuestion,
})
}
@@ -177,6 +190,15 @@ func (tc *TemplateController) QuestionList(ctx
*gin.Context) {
tc.Page404(ctx)
return
}
+
+ hotQuestionReq := &schema.QuestionPageReq{
+ Page: 1,
+ PageSize: 6,
+ OrderCond: "hot",
+ InDays: 7,
+ }
+ hotQuestion, _, _ := tc.templateRenderController.Index(ctx,
hotQuestionReq)
+
siteInfo := tc.SiteInfo(ctx)
siteInfo.Canonical = fmt.Sprintf("%s/questions",
siteInfo.General.SiteUrl)
if page > 1 {
@@ -190,13 +212,14 @@ func (tc *TemplateController) QuestionList(ctx
*gin.Context) {
}
siteInfo.Title = fmt.Sprintf("%s - %s",
translator.Tr(handler.GetLang(ctx), constant.QuestionsTitleTrKey),
siteInfo.General.Name)
tc.html(ctx, http.StatusOK, "question.html", siteInfo, gin.H{
- "data": data,
- "useTitle": UrlUseTitle,
- "page": templaterender.Paginator(page, req.PageSize, count),
+ "data": data,
+ "useTitle": UrlUseTitle,
+ "page": templaterender.Paginator(page, req.PageSize,
count),
+ "hotQuestion": hotQuestion,
})
}
-func (tc *TemplateController) QuestionInfoeRdirect(ctx *gin.Context, siteInfo
*schema.TemplateSiteInfoResp, correctTitle bool) (jump bool, url string) {
+func (tc *TemplateController) QuestionInfoRedirect(ctx *gin.Context, siteInfo
*schema.TemplateSiteInfoResp, correctTitle bool) (jump bool, url string) {
questionID := ctx.Param("id")
title := ctx.Param("title")
answerID := uid.DeShortID(title)
@@ -316,7 +339,7 @@ func (tc *TemplateController) QuestionInfo(ctx
*gin.Context) {
}
siteInfo := tc.SiteInfo(ctx)
- jump, jumpurl := tc.QuestionInfoeRdirect(ctx, siteInfo, correctTitle)
+ jump, jumpurl := tc.QuestionInfoRedirect(ctx, siteInfo, correctTitle)
if jump {
ctx.Redirect(http.StatusFound, jumpurl)
return
@@ -337,7 +360,6 @@ func (tc *TemplateController) QuestionInfo(ctx
*gin.Context) {
}
// comments
-
objectIDs := []string{uid.DeShortID(id)}
for _, answer := range answers {
answerID := uid.DeShortID(answer.ID)
@@ -348,6 +370,17 @@ func (tc *TemplateController) QuestionInfo(ctx
*gin.Context) {
tc.Page404(ctx)
return
}
+
+ UrlUseTitle := false
+ if siteInfo.SiteSeo.Permalink == constant.PermalinkQuestionIDAndTitle ||
+ siteInfo.SiteSeo.Permalink ==
constant.PermalinkQuestionIDAndTitleByShortID {
+ UrlUseTitle = true
+ }
+
+ //related question
+ userID := middleware.GetLoginUserIDFromContext(ctx)
+ relatedQuestion, _, _ := tc.questionService.SimilarQuestion(ctx, id,
userID)
+
siteInfo.Canonical = fmt.Sprintf("%s/questions/%s/%s",
siteInfo.General.SiteUrl, id, encodeTitle)
if siteInfo.SiteSeo.Permalink == constant.PermalinkQuestionID ||
siteInfo.SiteSeo.Permalink == constant.PermalinkQuestionIDByShortID {
siteInfo.Canonical = fmt.Sprintf("%s/questions/%s",
siteInfo.General.SiteUrl, id)
@@ -389,7 +422,6 @@ func (tc *TemplateController) QuestionInfo(ctx
*gin.Context) {
item.Author.URL = fmt.Sprintf("%s/users/%s",
siteInfo.General.SiteUrl, answer.UserInfo.Username)
answerList = append(answerList, item)
}
-
}
jsonLD.MainEntity.SuggestedAnswer = answerList
jsonLDStr, err := json.Marshal(jsonLD)
@@ -405,12 +437,14 @@ func (tc *TemplateController) QuestionInfo(ctx
*gin.Context) {
siteInfo.Keywords = strings.Replace(strings.Trim(fmt.Sprint(tags),
"[]"), " ", ",", -1)
siteInfo.Title = fmt.Sprintf("%s - %s", detail.Title,
siteInfo.General.Name)
tc.html(ctx, http.StatusOK, "question-detail.html", siteInfo, gin.H{
- "id": id,
- "answerid": answerid,
- "detail": detail,
- "answers": answers,
- "comments": comments,
- "noindex": detail.Show == entity.QuestionHide,
+ "id": id,
+ "answerid": answerid,
+ "detail": detail,
+ "answers": answers,
+ "comments": comments,
+ "noindex": detail.Show == entity.QuestionHide,
+ "useTitle": UrlUseTitle,
+ "relatedQuestion": relatedQuestion,
})
}
diff --git a/ui/template/hot-question.html b/ui/template/hot-question.html
new file mode 100644
index 00000000..23981926
--- /dev/null
+++ b/ui/template/hot-question.html
@@ -0,0 +1,42 @@
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+{{define "hot-question"}}
+<div class="card">
+ <div class="text-nowrap text-capitalize card-header">{{translator $.language
"ui.question.hot_questions"}}</div>
+ <div class="list-group list-group-flush">
+ {{ range .hotQuestion }}
+ {{if $.useTitle }}
+ <a class="list-group-item list-group-item-action"
href="{{$.baseURL}}/questions/{{.ID}}/{{urlTitle .Title}}">
+ {{else}}
+ <a class="list-group-item list-group-item-action"
href="{{$.baseURL}}/questions/{{.ID}}">
+ {{end}}
+ <div class="link-dark">{{ .Title }}</div>
+ {{if ne 0 .AnswerCount}}
+ <div class="d-flex align-items-center small mt-1 link-secondary">
+ <i class="br bi-chat-square-text-fill"></i>
+ <span class="ms-1">{{translator $.language "ui.question.x_answers"
"count" .AnswerCount}}</span>
+ </div>
+ {{end}}
+ </a>
+ {{ end }}
+ </div>
+</div>
+{{end}}
diff --git a/ui/template/question-detail.html b/ui/template/question-detail.html
index 2134a04f..d0e6933d 100644
--- a/ui/template/question-detail.html
+++ b/ui/template/question-detail.html
@@ -24,7 +24,11 @@
<div class="mb-5 mb-md-0 col-xxl-7 col-lg-8 col-sm-12">
<div>
<h1 class="h3 mb-3 text-wrap text-break">
+ {{if $.useTitle }}
+ <a class="link-dark"
href="{{$.baseURL}}/questions/{{.detail.ID}}/{{urlTitle
.detail.Title}}">{{.detail.Title}}</a>
+ {{else}}
<a class="link-dark"
href="{{$.baseURL}}/questions/{{.detail.ID}}">{{.detail.Title}}</a>
+ {{end}}
</h1>
<div
class="d-flex flex-wrap align-items-center small mb-3
text-secondary">
@@ -116,7 +120,7 @@
<h5 class="mb-0">{{.detail.AnswerCount}} Answers</h5>
</div>
{{range .answers}}
- <div id="10020000000000930" class="answer-item py-4">
+ <div class="answer-item py-4">
<article class="fmt">
{{formatLinkNofollow .HTML}}
</article>
@@ -192,8 +196,8 @@
</div>
{{end}}
</div>
- <div class="mt-5 mt-lg-0 col-xxl-3 col-lg-4 col-sm-12">
-
+ <div class="page-right-side mt-4 mt-xl-0 col">
+ {{template "related-question" .}}
</div>
</div>
</div>
diff --git a/ui/template/question.html b/ui/template/question.html
index 40c645ed..058645e5 100644
--- a/ui/template/question.html
+++ b/ui/template/question.html
@@ -94,7 +94,9 @@
</div>
</div>
</div>
- <div class="mt-5 mt-lg-0 col-xxl-3 col-lg-4 col-sm-12"></div>
+ <div class="page-right-side mt-4 mt-xl-0 col">
+ {{template "hot-question" .}}
+ </div>
</div>
</div>
{{template "footer" .}}
diff --git a/ui/template/related-question.html
b/ui/template/related-question.html
new file mode 100644
index 00000000..c93ccc8d
--- /dev/null
+++ b/ui/template/related-question.html
@@ -0,0 +1,42 @@
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+{{define "related-question"}}
+<div class="card">
+ <div class="card-header">{{translator $.language
"ui.related_question.title"}}</div>
+ <div class="list-group list-group-flush">
+ {{ range .relatedQuestion }}
+ {{if $.useTitle }}
+ <a class="list-group-item list-group-item-action"
href="{{$.baseURL}}/questions/{{.ID}}/{{urlTitle .Title}}">
+ {{else}}
+ <a class="list-group-item list-group-item-action"
href="{{$.baseURL}}/questions/{{.ID}}">
+ {{end}}
+ <div class="link-dark">{{ .Title }}</div>
+ {{if ne 0 .AnswerCount}}
+ <div class="mt-1 small me-2 link-secondary">
+ <i class="br bi-chat-square-text-fill me-1"></i>
+ <span>{{ .AnswerCount }} {{translator $.language
"ui.related_question.answers"}}</span>
+ </div>
+ {{end}}
+ </a>
+ {{ end }}
+ </div>
+</div>
+{{end}}