update
parent
a956221c4e
commit
38cc74dd6f
15
app.go
15
app.go
|
@ -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 {
|
||||||
|
@ -39,11 +40,17 @@ func (cui *ConfigUI) App(w http.ResponseWriter, r *http.Request) {
|
||||||
Files := []ActiveFile{}
|
Files := []ActiveFile{}
|
||||||
for _, i := range cui.fileIndex {
|
for _, i := range cui.fileIndex {
|
||||||
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 != "" {
|
||||||
|
|
|
@ -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{
|
||||||
|
|
|
@ -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)
|
||||||
|
|
9
file.go
9
file.go
|
@ -15,8 +15,12 @@ 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 bool `json:"ro"`
|
// RO is readonly
|
||||||
Lang string `json:"lang"`
|
RO bool `json:"ro"`
|
||||||
|
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)
|
||||||
|
|
147
handler.go
147
handler.go
|
@ -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)
|
||||||
|
}
|
||||||
|
|
|
@ -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
143
server.go
|
@ -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)
|
|
||||||
}
|
|
||||||
|
|
|
@ -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}}
|
|
@ -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}}
|
|
@ -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>
|
||||||
|
|
Loading…
Reference in New Issue