configui/configui.go

219 lines
4.6 KiB
Go
Raw Normal View History

package configui
import (
2021-11-03 19:35:51 +00:00
"bytes"
"embed"
"encoding/json"
"errors"
"fmt"
"html/template"
2021-11-03 19:35:51 +00:00
"net/http"
"os"
2021-11-03 10:08:37 +00:00
"time"
2021-11-03 19:35:51 +00:00
"kumoly.io/lib/klog"
"kumoly.io/tools/configui/public"
)
var UNIX_SHELL = "sh"
var WIN_SHELL = "cmd"
2021-10-24 07:15:21 +00:00
const version = "v0.1.3"
2021-10-23 16:49:44 +00:00
//go:embed templates
var tmplFS embed.FS
var Ext2Mode map[string]string = map[string]string{
"go": "golang",
"log": "sh",
"txt": "text",
"yml": "yaml",
"conf": "ini",
2021-10-24 06:32:55 +00:00
"md": "markdown",
}
type ConfigUI struct {
AppName string `json:"app_name"`
2021-11-03 19:35:51 +00:00
Prod bool `json:"production"`
2021-10-24 07:06:02 +00:00
BaseUrl string `json:"base_url"`
ConfigPath string `json:"config_path"`
NoReconfig bool `json:"no_reconfig"`
AllowIP string `json:"allow_ip"`
2021-11-03 10:08:37 +00:00
CmdTimeout string `json:"timeout"`
cmdTimeout time.Duration
Files []*File `json:"files"`
fileIndex map[string]int
ResultBellow bool `json:"result_bellow"`
HideConfig bool `json:"hide_config"`
// Should be in main app
2021-11-03 19:35:51 +00:00
LogPath string `json:"log_path"`
LogLevel int `json:"log_level"`
TmplFS embed.FS `json:"-"`
tmpl *template.Template
2021-11-03 19:35:51 +00:00
PublicFS embed.FS `json:"-"`
log *klog.Logger `json:"-"`
ksrv_log *klog.Logger `json:"-"`
f *os.File `json:"-"`
}
func New() *ConfigUI {
tmpl := template.Must(template.New("").Funcs(template.FuncMap{
"step": func(from, to, step uint) []uint {
items := []uint{}
for i := from; i <= to; i += step {
items = append(items, i)
}
return items
},
}).ParseFS(tmplFS, "templates/*.tmpl", "templates/**/*.tmpl"))
return &ConfigUI{
2021-11-03 10:08:37 +00:00
fileIndex: map[string]int{},
2021-11-03 19:35:51 +00:00
Prod: true,
2021-11-03 10:08:37 +00:00
AppName: "ConfigUI",
BaseUrl: "/",
PublicFS: public.FS,
TmplFS: tmplFS,
tmpl: tmpl,
CmdTimeout: "10s",
cmdTimeout: time.Second * 10,
2021-11-03 19:35:51 +00:00
LogLevel: klog.Lerror | klog.Linfo,
log: klog.Sub("ConfigUI"),
}
}
func (cui *ConfigUI) File(file_name string) (*File, error) {
if file_name == cui.AppName {
return &File{
2021-11-03 19:35:51 +00:00
Path: cui.ConfigPath,
Name: cui.AppName,
Lang: "json",
owner: cui,
}, nil
}
index, ok := cui.fileIndex[file_name]
if !ok {
return nil, errors.New("no file found")
}
return cui.Files[index], nil
}
func (cui *ConfigUI) LoadConfig(confstr string) error {
tmpConf := &ConfigUI{}
err := json.Unmarshal([]byte(confstr), tmpConf)
if err != nil {
return nil
}
// construct fileIndex
tmpIndex := map[string]int{}
for i, f := range tmpConf.Files {
if f.Name == "" {
f.Name = f.Path
}
2021-11-03 19:35:51 +00:00
f.owner = cui
tmpIndex[f.Name] = i
}
// copy
cui.fileIndex = tmpIndex
cui.Files = tmpConf.Files
cui.AllowIP = tmpConf.AllowIP
2021-11-03 19:35:51 +00:00
cui.Prod = tmpConf.Prod
cui.ConfigPath = tmpConf.ConfigPath
cui.HideConfig = tmpConf.HideConfig
cui.NoReconfig = tmpConf.NoReconfig
2021-11-03 19:35:51 +00:00
cui.AppName = tmpConf.AppName
2021-11-03 19:35:51 +00:00
if cui.AppName == "" {
cui.AppName = "ConfigUI"
}
2021-10-24 07:06:02 +00:00
cui.BaseUrl = tmpConf.BaseUrl
2021-10-24 07:15:21 +00:00
if cui.BaseUrl == "" {
cui.BaseUrl = "/"
}
2021-11-03 19:35:51 +00:00
2021-11-03 10:08:37 +00:00
ct, err := time.ParseDuration(tmpConf.CmdTimeout)
if err != nil || cui.CmdTimeout == "" {
cui.CmdTimeout = "10s"
cui.cmdTimeout = time.Second * 10
} else {
cui.CmdTimeout = tmpConf.CmdTimeout
cui.cmdTimeout = ct
}
2021-11-03 19:35:51 +00:00
cui.log = klog.Sub(cui.AppName)
// NOT implemented
cui.ResultBellow = tmpConf.ResultBellow
2021-11-03 19:35:51 +00:00
cui.LogLevel = tmpConf.LogLevel
cui.LogPath = tmpConf.LogPath
cui.setLog()
// fmt.Printf("%+v", cui)
return nil
}
2021-11-03 19:35:51 +00:00
func (cui *ConfigUI) setLog() {
var err error
if cui.f != nil {
cui.f.Close()
}
if cui.LogPath != "" {
cui.f, err = os.OpenFile(cui.LogPath, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
cui.log.Error(err)
}
cui.log.SetErrOutput(cui.f)
cui.log.SetOutput(cui.f)
cui.log.Reload()
if cui.ksrv_log != nil {
cui.ksrv_log.SetErrOutput(cui.f)
cui.ksrv_log.SetOutput(cui.f)
cui.ksrv_log.Reload()
}
} else {
cui.log.SetErrOutput(os.Stderr)
cui.log.SetOutput(os.Stderr)
cui.log.Reload()
if cui.ksrv_log != nil {
cui.ksrv_log.SetErrOutput(os.Stderr)
cui.ksrv_log.SetOutput(os.Stderr)
cui.ksrv_log.Reload()
}
}
}
func (cui *ConfigUI) Config() ([]byte, error) {
return json.MarshalIndent(cui, "", " ")
}
func (cui *ConfigUI) AppendFile(file *File) error {
if file.Name == "" {
file.Name = file.Path
}
2021-11-03 19:35:51 +00:00
file.owner = cui
i, ok := cui.fileIndex[file.Name]
if ok {
return fmt.Errorf("%v already exists at %d", file.Name, i)
}
cui.fileIndex[file.Name] = len(cui.Files)
cui.Files = append(cui.Files, file)
return nil
}
2021-11-03 19:35:51 +00:00
func (cui *ConfigUI) Parse(w http.ResponseWriter, name string, data interface{}) error {
buf := &bytes.Buffer{}
err := cui.tmpl.ExecuteTemplate(buf, "home", data)
if err != nil {
panic(err)
}
_, err = w.Write(buf.Bytes())
return err
}