This is an automated email from the ASF dual-hosted git repository.

kumfo pushed a commit to branch feat/1.7.0/quicklinks
in repository https://gitbox.apache.org/repos/asf/answer.git

commit a6d95ae8f94a1648927d150426a74c2e9cae479f
Author: kumfo <ku...@sifou.com>
AuthorDate: Wed Aug 13 14:44:25 2025 +0800

    feat: add sidebar plugin
---
 cmd/wire_gen.go                                    |  3 +-
 internal/controller/controller.go                  |  1 +
 ...{controller.go => plugin_sidebar_controller.go} | 60 ++++++++++------------
 internal/router/plugin_api_router.go               |  6 +++
 plugin/config.go                                   | 30 +++++++----
 plugin/plugin.go                                   |  4 ++
 plugin/sidebar.go                                  | 37 +++++++++++++
 7 files changed, 96 insertions(+), 45 deletions(-)

diff --git a/cmd/wire_gen.go b/cmd/wire_gen.go
index 947b6605..ce352051 100644
--- a/cmd/wire_gen.go
+++ b/cmd/wire_gen.go
@@ -289,7 +289,8 @@ func initApplication(debug bool, serverConf *conf.Server, 
dbConf *data.Database,
        captchaController := controller.NewCaptchaController()
        embedController := controller.NewEmbedController()
        renderController := controller.NewRenderController()
-       pluginAPIRouter := router.NewPluginAPIRouter(connectorController, 
userCenterController, captchaController, embedController, renderController)
+       sidebarController := controller.NewSidebarController()
+       pluginAPIRouter := router.NewPluginAPIRouter(connectorController, 
userCenterController, captchaController, embedController, renderController, 
sidebarController)
        ginEngine := server.NewHTTPServer(debug, staticRouter, answerAPIRouter, 
swaggerRouter, uiRouter, authUserMiddleware, avatarMiddleware, 
shortIDMiddleware, templateRouter, pluginAPIRouter, uiConf)
        scheduledTaskManager := 
cron.NewScheduledTaskManager(siteInfoCommonService, questionService, 
fileRecordService, userAdminService, serviceConf)
        application := newApplication(serverConf, ginEngine, 
scheduledTaskManager)
diff --git a/internal/controller/controller.go 
b/internal/controller/controller.go
index cbf80f7f..b5c3f91c 100644
--- a/internal/controller/controller.go
+++ b/internal/controller/controller.go
@@ -53,4 +53,5 @@ var ProviderSetController = wire.NewSet(
        NewEmbedController,
        NewBadgeController,
        NewRenderController,
+       NewSidebarController,
 )
diff --git a/internal/controller/controller.go 
b/internal/controller/plugin_sidebar_controller.go
similarity index 50%
copy from internal/controller/controller.go
copy to internal/controller/plugin_sidebar_controller.go
index cbf80f7f..87186179 100644
--- a/internal/controller/controller.go
+++ b/internal/controller/plugin_sidebar_controller.go
@@ -19,38 +19,30 @@
 
 package controller
 
-import "github.com/google/wire"
-
-// ProviderSetController is controller providers.
-var ProviderSetController = wire.NewSet(
-       NewLangController,
-       NewCommentController,
-       NewReportController,
-       NewVoteController,
-       NewTagController,
-       NewFollowController,
-       NewCollectionController,
-       NewUserController,
-       NewQuestionController,
-       NewAnswerController,
-       NewSearchController,
-       NewRevisionController,
-       NewRankController,
-       NewReasonController,
-       NewNotificationController,
-       NewSiteInfoController,
-       NewDashboardController,
-       NewUploadController,
-       NewActivityController,
-       NewTemplateController,
-       NewConnectorController,
-       NewUserCenterController,
-       NewPermissionController,
-       NewUserPluginController,
-       NewReviewController,
-       NewCaptchaController,
-       NewMetaController,
-       NewEmbedController,
-       NewBadgeController,
-       NewRenderController,
+import (
+       "github.com/apache/answer/internal/base/handler"
+       "github.com/apache/answer/plugin"
+       "github.com/gin-gonic/gin"
 )
+
+// SidebarController is the controller for the sidebar plugin.
+type SidebarController struct{}
+
+// NewSidebarController creates a new instance of SidebarController.
+func NewSidebarController() *SidebarController {
+       return &SidebarController{}
+}
+
+// GetSidebarConfig retrieves the sidebar configuration from the registered 
sidebar plugins.
+func (uc *SidebarController) GetSidebarConfig(ctx *gin.Context) {
+       resp := &plugin.SidebarConfig{}
+       _ = plugin.CallSidebar(func(fn plugin.Sidebar) error {
+               cfg, err := fn.GetSidebarConfig()
+               if err != nil {
+                       return err
+               }
+               resp = cfg
+               return nil
+       })
+       handler.HandleResponse(ctx, nil, resp)
+}
diff --git a/internal/router/plugin_api_router.go 
b/internal/router/plugin_api_router.go
index ce5062ba..3b74b3dd 100644
--- a/internal/router/plugin_api_router.go
+++ b/internal/router/plugin_api_router.go
@@ -30,6 +30,7 @@ type PluginAPIRouter struct {
        captchaController    *controller.CaptchaController
        embedController      *controller.EmbedController
        renderController     *controller.RenderController
+       sidebarController    *controller.SidebarController
 }
 
 func NewPluginAPIRouter(
@@ -38,6 +39,7 @@ func NewPluginAPIRouter(
        captchaController *controller.CaptchaController,
        embedController *controller.EmbedController,
        renderController *controller.RenderController,
+       sidebarController *controller.SidebarController,
 ) *PluginAPIRouter {
        return &PluginAPIRouter{
                connectorController:  connectorController,
@@ -45,6 +47,7 @@ func NewPluginAPIRouter(
                captchaController:    captchaController,
                embedController:      embedController,
                renderController:     renderController,
+               sidebarController:    sidebarController,
        }
 }
 
@@ -68,6 +71,9 @@ func (pr *PluginAPIRouter) RegisterUnAuthConnectorRouter(r 
*gin.RouterGroup) {
        r.GET("/captcha/config", pr.captchaController.GetCaptchaConfig)
        r.GET("/embed/config", pr.embedController.GetEmbedConfig)
        r.GET("/render/config", pr.renderController.GetRenderConfig)
+
+       // sidebar plugin
+       r.GET("/sidebar/config", pr.sidebarController.GetSidebarConfig)
 }
 
 func (pr *PluginAPIRouter) RegisterAuthUserConnectorRouter(r *gin.RouterGroup) 
{
diff --git a/plugin/config.go b/plugin/config.go
index b03e794e..849ad617 100644
--- a/plugin/config.go
+++ b/plugin/config.go
@@ -23,16 +23,17 @@ type ConfigType string
 type InputType string
 
 const (
-       ConfigTypeInput    ConfigType = "input"
-       ConfigTypeTextarea ConfigType = "textarea"
-       ConfigTypeCheckbox ConfigType = "checkbox"
-       ConfigTypeRadio    ConfigType = "radio"
-       ConfigTypeSelect   ConfigType = "select"
-       ConfigTypeUpload   ConfigType = "upload"
-       ConfigTypeTimezone ConfigType = "timezone"
-       ConfigTypeSwitch   ConfigType = "switch"
-       ConfigTypeButton   ConfigType = "button"
-       ConfigTypeLegend   ConfigType = "legend"
+       ConfigTypeInput       ConfigType = "input"
+       ConfigTypeTextarea    ConfigType = "textarea"
+       ConfigTypeCheckbox    ConfigType = "checkbox"
+       ConfigTypeRadio       ConfigType = "radio"
+       ConfigTypeSelect      ConfigType = "select"
+       ConfigTypeUpload      ConfigType = "upload"
+       ConfigTypeTimezone    ConfigType = "timezone"
+       ConfigTypeSwitch      ConfigType = "switch"
+       ConfigTypeButton      ConfigType = "button"
+       ConfigTypeLegend      ConfigType = "legend"
+       ConfigTypeTagSelector ConfigType = "tag_selector"
 )
 
 const (
@@ -105,6 +106,15 @@ type OnCompleteAction struct {
        RefreshFormConfig  bool `json:"refresh_form_config"`
 }
 
+// TagSelectorOption represents a tag option in the tag selector config value 
field
+type TagSelectorOption struct {
+       TagID       string `json:"tag_id"`
+       SlugName    string `json:"slug_name"`
+       DisplayName string `json:"display_name"`
+       Recommend   bool   `json:"recommend"`
+       Reserved    bool   `json:"reserved"`
+}
+
 type Config interface {
        Base
 
diff --git a/plugin/plugin.go b/plugin/plugin.go
index a9e17310..26684835 100644
--- a/plugin/plugin.go
+++ b/plugin/plugin.go
@@ -126,6 +126,10 @@ func Register(p Base) {
        if _, ok := p.(KVStorage); ok {
                registerKVStorage(p.(KVStorage))
        }
+
+       if _, ok := p.(Sidebar); ok {
+               registerSidebar(p.(Sidebar))
+       }
 }
 
 type Stack[T Base] struct {
diff --git a/plugin/sidebar.go b/plugin/sidebar.go
new file mode 100644
index 00000000..690a70d9
--- /dev/null
+++ b/plugin/sidebar.go
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+// Package plugin
+package plugin
+
+type SidebarConfig struct {
+       Tags      []*TagSelectorOption `json:"tags"`
+       LinksText string               `json:"links_text"`
+}
+
+type Sidebar interface {
+       Base
+       GetSidebarConfig() (sidebarConfig *SidebarConfig, err error)
+}
+
+var (
+       // CallRender is a function that calls all registered parsers
+       CallSidebar,
+       registerSidebar = MakePlugin[Sidebar](false)
+)

Reply via email to