answer/internal/router/ui.go

161 lines
3.8 KiB
Go

package router
import (
"embed"
"fmt"
"io/fs"
"math/rand"
"net/http"
"os"
"github.com/answerdev/answer/i18n"
"github.com/answerdev/answer/internal/base/handler"
"github.com/answerdev/answer/internal/base/translator"
"github.com/answerdev/answer/ui"
"github.com/gin-gonic/gin"
"github.com/segmentfault/pacman/errors"
"github.com/segmentfault/pacman/log"
)
const UIIndexFilePath = "build/index.html"
const UIRootFilePath = "build"
const UIStaticPath = "build/static"
// UIRouter is an interface that provides ui static file routers
type UIRouter struct {
}
// NewUIRouter creates a new UIRouter instance with the embed resources
func NewUIRouter() *UIRouter {
return &UIRouter{}
}
// _resource is an interface that provides static file, it's a private interface
type _resource struct {
fs embed.FS
}
// Open to implement the interface by http.FS required
func (r *_resource) Open(name string) (fs.File, error) {
name = fmt.Sprintf(UIStaticPath+"/%s", name)
log.Debugf("open static path %s", name)
return r.fs.Open(name)
}
// Register a new static resource which generated by ui directory
func (a *UIRouter) Register(r *gin.Engine) {
staticPath := os.Getenv("ANSWER_STATIC_PATH")
r.StaticFS("/i18n/", http.FS(i18n.I18n))
// if ANSWER_STATIC_PATH is set and not empty, ignore embed resource
if staticPath != "" {
info, err := os.Stat(staticPath)
if err != nil || !info.IsDir() {
log.Error(err)
} else {
log.Debugf("registering static path %s", staticPath)
r.LoadHTMLGlob(staticPath + "/*.html")
r.Static("/static", staticPath+"/static")
r.NoRoute(func(c *gin.Context) {
c.HTML(http.StatusOK, "index.html", gin.H{})
})
// return immediately if the static path is set
return
}
}
// handle the static file by default ui static files
r.StaticFS("/static", http.FS(&_resource{
fs: ui.Build,
}))
// Install godoc
// @Summary Install
// @Description Install
// @Tags Install
// @Accept json
// @Produce json
// @Success 200 {object} handler.RespBody{}
// @Router /install [get]
r.GET("/install", func(c *gin.Context) {
filePath := ""
var file []byte
var err error
filePath = "build/index.html"
c.Header("content-type", "text/html;charset=utf-8")
file, err = ui.Build.ReadFile(filePath)
if err != nil {
log.Error(err)
c.Status(http.StatusNotFound)
return
}
c.String(http.StatusOK, string(file))
})
r.GET("/installation/language/options", func(c *gin.Context) {
handler.HandleResponse(c, nil, translator.LanguageOptions)
})
r.POST("/installation/db/check", func(c *gin.Context) {
num := rand.Intn(10)
if num > 5 {
err := errors.BadRequest("connection error")
handler.HandleResponse(c, err, gin.H{})
} else {
handler.HandleResponse(c, nil, gin.H{
"connection_success": true,
})
}
})
r.POST("/installation/config-file/check", func(c *gin.Context) {
num := rand.Intn(10)
if num > 5 {
handler.HandleResponse(c, nil, gin.H{
"exist": true,
})
} else {
handler.HandleResponse(c, nil, gin.H{
"exist": false,
})
}
})
r.POST("/installation/init", func(c *gin.Context) {
handler.HandleResponse(c, nil, gin.H{})
})
r.POST("/installation/base-info", func(c *gin.Context) {
handler.HandleResponse(c, nil, gin.H{})
})
// specify the not router for default routes and redirect
r.NoRoute(func(c *gin.Context) {
name := c.Request.URL.Path
filePath := ""
var file []byte
var err error
switch name {
case "/favicon.ico":
c.Header("content-type", "image/vnd.microsoft.icon")
filePath = UIRootFilePath + name
case "/manifest.json":
filePath = UIRootFilePath + name
default:
filePath = UIIndexFilePath
c.Header("content-type", "text/html;charset=utf-8")
}
file, err = ui.Build.ReadFile(filePath)
if err != nil {
log.Error(err)
c.Status(http.StatusNotFound)
return
}
c.String(http.StatusOK, string(file))
})
}