pull/36/head
Evan Chen 2021-10-22 13:20:59 +08:00
parent a956221c4e
commit 38cc74dd6f
10 changed files with 180 additions and 166 deletions

11
app.go
View File

@ -14,6 +14,7 @@ type ActiveFile struct {
Name string Name string
Action string Action string
Content string Content string
Order int
} }
type Editor struct { type Editor struct {
@ -41,9 +42,15 @@ func (cui *ConfigUI) App(w http.ResponseWriter, r *http.Request) {
Files = append(Files, ActiveFile{ Files = append(Files, ActiveFile{
Name: cui.Files[i].Name, Name: cui.Files[i].Name,
Path: cui.Files[i].Path, Path: cui.Files[i].Path,
Order: cui.Files[i].Order,
}) })
} }
sort.Slice(Files, func(i, j int) bool { return Files[i].Name < Files[j].Name }) sort.Slice(Files, func(i, j int) bool {
if Files[i].Order == Files[j].Order {
return Files[i].Name < Files[j].Name
}
return Files[i].Order < Files[j].Order
})
plat := "unix" plat := "unix"
if runtime.GOOS == "windows" { if runtime.GOOS == "windows" {
plat = "windows" plat = "windows"
@ -65,7 +72,7 @@ func (cui *ConfigUI) App(w http.ResponseWriter, r *http.Request) {
file, err := cui.File(name) file, err := cui.File(name)
if name == "" || err != nil { if name == "" || err != nil {
tmp, err = cui.Config() tmp, err = cui.Config()
data.File.Name = "ConfigUI" data.File.Name = cui.AppName
data.File.Path = ":mem:" data.File.Path = ":mem:"
data.Editor.Lang = "json" data.Editor.Lang = "json"
if name != "" { if name != "" {

View File

@ -95,6 +95,7 @@ func main() {
cui.LogPath = flagLogFile cui.LogPath = flagLogFile
cui.ConfigPath = flagConfigPath cui.ConfigPath = flagConfigPath
cui.NoReconfig = flagNoReconfig
// setup routes // setup routes
server := &http.Server{ server := &http.Server{

View File

@ -97,6 +97,9 @@ func (cui *ConfigUI) LoadConfig(confstr string) error {
cui.HideConfig = tmpConf.HideConfig cui.HideConfig = tmpConf.HideConfig
cui.LogPath = tmpConf.LogPath cui.LogPath = tmpConf.LogPath
cui.NoReconfig = tmpConf.NoReconfig cui.NoReconfig = tmpConf.NoReconfig
cui.AppName = tmpConf.AppName
// NOT implemented
cui.ResultBellow = tmpConf.ResultBellow cui.ResultBellow = tmpConf.ResultBellow
cui.SilentSysOut = tmpConf.SilentSysOut cui.SilentSysOut = tmpConf.SilentSysOut
// fmt.Printf("%+v", cui) // fmt.Printf("%+v", cui)

View File

@ -15,9 +15,13 @@ type File struct {
Path string `json:"path"` Path string `json:"path"`
Name string `json:"name"` Name string `json:"name"`
Action string `json:"action"` Action string `json:"action"`
// RO is readonly
RO bool `json:"ro"` RO bool `json:"ro"`
Lang string `json:"lang"` Lang string `json:"lang"`
// Order order of the display on ui
Order int `json:"order"`
// used for parsing post data // used for parsing post data
Data string `json:"data"` Data string `json:"data"`
@ -39,7 +43,6 @@ func (f *File) Write(data []byte) error {
if f.RO { if f.RO {
return errors.New("this file has readonly set") return errors.New("this file has readonly set")
} }
log.Println("dfsdf")
f.lock.Lock() f.lock.Lock()
defer f.lock.Unlock() defer f.lock.Unlock()
info, err := os.Stat(f.Path) info, err := os.Stat(f.Path)

View File

@ -1 +1,148 @@
package configui package configui
import (
"encoding/json"
"io/ioutil"
"net/http"
"os"
"path/filepath"
)
func (cui *ConfigUI) ListFiles(w http.ResponseWriter, r *http.Request) {
data, err := json.Marshal(cui.Files)
if err != nil {
panic(err)
}
w.Write(data)
}
func (cui *ConfigUI) GetFile(w http.ResponseWriter, r *http.Request) {
name := r.URL.Query().Get("name")
file, err := cui.File(name)
if err != nil {
response(w, 404, []byte("file not found"))
return
}
data, err := file.Read()
if err != nil {
panic(err)
}
response, err := json.Marshal(map[string]string{
"path": file.Path,
"name": file.Name,
"action": file.Action,
"data": string(data),
})
if err != nil {
panic(err)
}
w.Header().Set("Content-Type", "application/json")
w.Write(response)
}
func (cui *ConfigUI) PostFile(w http.ResponseWriter, r *http.Request) {
data, err := ioutil.ReadAll(r.Body)
r.Body.Close()
if err != nil {
panic(err)
}
f := File{}
if err := json.Unmarshal(data, &f); err != nil {
panic(err)
}
file, err := cui.File(f.Name)
if err != nil {
response(w, 404, []byte("file not found"))
return
}
if err := file.Write([]byte(f.Data)); err != nil {
panic(err)
}
w.Write([]byte("ok"))
}
func (cui *ConfigUI) Apply(w http.ResponseWriter, r *http.Request) {
name := r.URL.Query().Get("name")
file, err := cui.File(name)
if err != nil {
response(w, 404, []byte("file not found"))
return
}
result, err := file.Do()
if err != nil {
panic(err)
}
w.Write([]byte(result))
}
func (cui *ConfigUI) Download(w http.ResponseWriter, r *http.Request) {
if name := r.URL.Query().Get("name"); name != "" {
if name == cui.AppName {
data, err := cui.Config()
if err != nil {
panic(err)
}
w.Header().Set(
"Content-Disposition", `
attachment; filename="`+cui.AppName+`.json"`,
)
w.Write(data)
return
}
file, err := cui.File(name)
if err != nil {
response(w, 404, []byte("file not found"))
return
}
data, err := file.Read()
if err != nil {
panic(err)
}
w.Header().Set("Content-Disposition", `attachment; filename="`+filepath.Base(file.Path)+`"`)
w.Write(data)
return
}
fs := []string{}
for _, i := range cui.fileIndex {
fs = append(fs, cui.Files[i].Path)
}
if cui.ConfigPath != "" {
fs = append(fs, cui.ConfigPath)
}
w.Header().Set("Content-Disposition", `attachment; filename="export.tar.gz"`)
bundle(w, fs, cui.AppName, false)
}
func (cui *ConfigUI) PostConfig(w http.ResponseWriter, r *http.Request) {
if cui.NoReconfig {
panic("system reconfig is disabled")
}
data, err := ioutil.ReadAll(r.Body)
r.Body.Close()
if err != nil {
panic(err)
}
err = cui.LoadConfig(string(data))
if err != nil {
panic(err)
}
if cui.ConfigPath != "" {
info, err := os.Stat(cui.ConfigPath)
if err != nil {
panic(err)
}
err = os.WriteFile(cui.ConfigPath, data, info.Mode())
if err != nil {
panic(err)
}
}
w.Write([]byte("ok"))
}
func (cui *ConfigUI) GetConfig(w http.ResponseWriter, r *http.Request) {
data, err := cui.Config()
if err != nil {
panic(err)
}
w.Write(data)
}

View File

@ -2,5 +2,5 @@ package public
import "embed" import "embed"
//go:embed js css ace assets //go:embed css ace assets
var FS embed.FS var FS embed.FS

143
server.go
View File

@ -1,12 +1,8 @@
package configui package configui
import ( import (
"encoding/json"
"io/ioutil"
"log" "log"
"net/http" "net/http"
"os"
"path/filepath"
"strings" "strings"
) )
@ -80,142 +76,3 @@ func (cui *ConfigUI) mux() *http.ServeMux {
cuiR.HandleFunc("/", cui.App) cuiR.HandleFunc("/", cui.App)
return cuiR return cuiR
} }
func (cui *ConfigUI) ListFiles(w http.ResponseWriter, r *http.Request) {
data, err := json.Marshal(cui.Files)
if err != nil {
panic(err)
}
w.Write(data)
}
func (cui *ConfigUI) GetFile(w http.ResponseWriter, r *http.Request) {
name := r.URL.Query().Get("name")
file, err := cui.File(name)
if err != nil {
response(w, 404, []byte("file not found"))
return
}
data, err := file.Read()
if err != nil {
panic(err)
}
response, err := json.Marshal(map[string]string{
"path": file.Path,
"name": file.Name,
"action": file.Action,
"data": string(data),
})
if err != nil {
panic(err)
}
w.Header().Set("Content-Type", "application/json")
w.Write(response)
}
func (cui *ConfigUI) PostFile(w http.ResponseWriter, r *http.Request) {
data, err := ioutil.ReadAll(r.Body)
r.Body.Close()
if err != nil {
panic(err)
}
f := File{}
if err := json.Unmarshal(data, &f); err != nil {
panic(err)
}
file, err := cui.File(f.Name)
if err != nil {
response(w, 404, []byte("file not found"))
return
}
if err := file.Write([]byte(f.Data)); err != nil {
panic(err)
}
w.Write([]byte("ok"))
}
func (cui *ConfigUI) Apply(w http.ResponseWriter, r *http.Request) {
name := r.URL.Query().Get("name")
file, err := cui.File(name)
if err != nil {
response(w, 404, []byte("file not found"))
return
}
result, err := file.Do()
if err != nil {
panic(err)
}
w.Write([]byte(result))
}
func (cui *ConfigUI) Download(w http.ResponseWriter, r *http.Request) {
if name := r.URL.Query().Get("name"); name != "" {
if name == cui.AppName {
data, err := cui.Config()
if err != nil {
panic(err)
}
w.Header().Set(
"Content-Disposition", `
attachment; filename="`+cui.AppName+`.json"`,
)
w.Write(data)
return
}
file, err := cui.File(name)
if err != nil {
response(w, 404, []byte("file not found"))
return
}
data, err := file.Read()
if err != nil {
panic(err)
}
w.Header().Set("Content-Disposition", `attachment; filename="`+filepath.Base(file.Path)+`"`)
w.Write(data)
return
}
fs := []string{}
for _, i := range cui.fileIndex {
fs = append(fs, cui.Files[i].Path)
}
if cui.ConfigPath != "" {
fs = append(fs, cui.ConfigPath)
}
w.Header().Set("Content-Disposition", `attachment; filename="export.tar.gz"`)
bundle(w, fs, cui.AppName, false)
}
func (cui *ConfigUI) PostConfig(w http.ResponseWriter, r *http.Request) {
if cui.NoReconfig {
panic("system reconfig is disabled")
}
data, err := ioutil.ReadAll(r.Body)
r.Body.Close()
if err != nil {
panic(err)
}
err = cui.LoadConfig(string(data))
if err != nil {
panic(err)
}
if cui.ConfigPath != "" {
info, err := os.Stat(cui.ConfigPath)
if err != nil {
panic(err)
}
err = os.WriteFile(cui.ConfigPath, data, info.Mode())
if err != nil {
panic(err)
}
}
w.Write([]byte("ok"))
}
func (cui *ConfigUI) GetConfig(w http.ResponseWriter, r *http.Request) {
data, err := cui.Config()
if err != nil {
panic(err)
}
w.Write(data)
}

View File

@ -1,8 +1,8 @@
{{define "base/footer"}} {{define "base/footer"}}
<script src="/public/ace/js/ace.js" type="text/javascript" charset="utf-8"></script> <script src="/public/ace/js/ace.js" type="text/javascript" charset="utf-8"></script>
<script src="/public/ace/js/ext-beautify.js" type="text/javascript" charset="utf-8"></script> <script src="/public/ace/js/ext-beautify.js" type="text/javascript" charset="utf-8"></script>
{{template "base/script" .}}
<!-- <script src="/public/js/main.js"></script> --> <!-- <script src="/public/js/main.js"></script> -->
<script src="/public/js/back.js"></script>
</body> </body>
</html> </html>
{{end}} {{end}}

View File

@ -1,5 +1,5 @@
{{define "base/script"}}
<script>
window.ToolIsFollow = false; window.ToolIsFollow = false;
async function FileGet(follower=false){ async function FileGet(follower=false){
@ -29,7 +29,7 @@ async function FileGet(follower=false){
} }
async function FileSave(){ async function FileSave(){
if (Active == 'ConfigUI') { if (Active == '{{.AppName}}') {
const res = await fetch('/api/conf', { const res = await fetch('/api/conf', {
method: 'POST', method: 'POST',
body: editor.getValue(), body: editor.getValue(),
@ -53,13 +53,14 @@ async function FileSave(){
} }
async function FileApply(){ async function FileApply(){
if (Active == 'ConfigUI') { if (Active == '{{.AppName}}') {
return; return;
} }
else { else {
const res = await fetch('/api/apply?name='+ Active, { const res = await fetch('/api/apply?name='+ Active, {
method: 'POST', method: 'POST',
}).catch(err=>{console.log(err);return;}); }).catch(err=>{console.log(err);return;});
console.log("running")
if(!res.ok){ if(!res.ok){
const result = await Catch(res) const result = await Catch(res)
result_editor.session.setValue(result) result_editor.session.setValue(result)
@ -80,13 +81,6 @@ async function Catch(res){
// starting point // starting point
(function(){ (function(){
// block ctl-s
window.addEventListener("keypress", function(event) {
if (!(event.code == 115 && event.ctrlKey) && !(event.code == 19)) return true
alert("Ctrl-S pressed")
event.preventDefault()
return false
})
// setup ace editor // setup ace editor
setEditor() setEditor()
@ -102,3 +96,5 @@ async function Catch(res){
} }
}), 1000) }), 1000)
}()) }())
</script>
{{end}}

View File

@ -15,14 +15,14 @@
{{ end }} {{ end }}
</ul> </ul>
<p class="menu-label"> <p class="menu-label">
ConfigUI System
</p> </p>
<ul class="menu-list"> <ul class="menu-list">
<li> <li>
<a class="has-tooltip-arrow {{if eq .File.Name .AppName }}is-active{{end}}" <a class="has-tooltip-arrow {{if eq .File.Name .AppName }}is-active{{end}}"
data-tooltip="{{$.File.Path}}" data-tooltip="{{$.File.Path}}"
href="/" href="/"
>config.json</a></li> >Config</a></li>
</ul> </ul>
</aside> </aside>
</section> </section>