pull/36/head
Evan Chen 2021-10-21 16:04:57 +08:00
parent e90f1e8e87
commit 442aad83ec
11 changed files with 113 additions and 25 deletions

View File

@ -2,9 +2,13 @@
## Feature
* download files #26
* add goto last line toolbar #21
## Fix
* all cmds should be pass straight back to user
* timeout on none ending cmds #34
# 0.1.1

29
api.go
View File

@ -3,8 +3,10 @@ package main
import (
"encoding/json"
"io/ioutil"
"log"
"net/http"
"os"
"path/filepath"
"kumoly.io/tools/configui/configui"
)
@ -70,6 +72,7 @@ func Apply(w http.ResponseWriter, r *http.Request) {
return
}
result, err := file.Do()
log.Println(err)
if err != nil {
panic(err)
}
@ -77,10 +80,36 @@ func Apply(w http.ResponseWriter, r *http.Request) {
}
func Download(w http.ResponseWriter, r *http.Request) {
if name := r.URL.Query().Get("name"); name != "" {
if name == "ConfigUI" {
data, err := GetConfig()
if err != nil {
panic(err)
}
w.Header().Set("Content-Disposition", `attachment; filename="ConfigUI.json"`)
w.Write(data)
return
}
file, ok := files[name]
if !ok {
MakeResponse(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 _, v := range files {
fs = append(fs, v.Path)
}
if flagConfigPath != "" {
fs = append(fs, flagConfigPath)
}
w.Header().Set("Content-Disposition", `attachment; filename="export.tar.gz"`)
bundle(w, fs, false)
}

View File

@ -8,6 +8,7 @@ import (
"os/exec"
"runtime"
"sync"
"time"
)
var UNIX_SHELL = "sh"
@ -54,15 +55,30 @@ func (f *File) Do() (string, error) {
if f.Action == "" {
return "", nil
}
cmd := exec.Command(UNIX_SHELL, "-c", f.Action)
timeout := time.After(2 * time.Second)
cmd := &exec.Cmd{}
if runtime.GOOS == "windows" {
cmd = exec.Command(WIN_SHELL, "/c", f.Action)
} else {
exec.Command(UNIX_SHELL, "-c", f.Action)
}
var out []byte
done := make(chan struct{}, 1)
go func() {
out, _ = cmd.CombinedOutput()
// real cmd err is only pass down
// if err != nil {
// return string(out), err
// }
done <- struct{}{}
}()
select {
case <-timeout:
cmd.Process.Kill()
return "", errors.New("command timeout")
case <-done:
return string(out), nil
}
out, _ := cmd.CombinedOutput()
// if err != nil {
// return "", err
// }
return string(out), nil
}
func ReadConfig(confstr string) ([]File, error) {

View File

@ -58,7 +58,8 @@ async function FileApply(){
method: 'POST',
})
if(!res.ok){
handleError(res)
const result = await handleError(res)
result_editor.session.setValue(result)
return
}
const result = await res.text()
@ -69,6 +70,7 @@ async function FileApply(){
async function handleError(res){
const msg = await res.text()
ShowError(msg)
return msg
}
// starting point

View File

@ -0,0 +1,19 @@
VERSION=$(git describe --tags --abbrev=0)
BUILD=$(git rev-parse --short HEAD)
PROJ=$(basename "$(PWD)")
HUB=hub.kumoly.io
HUB_PROJECT=tools
LDFLAGS='-ldflags "-X main.Version=${VERSION} -X main.Build=${BUILD} -w"'
PLATFORMS='darwin linux'
ARCHITECTURES=amd64
APPS=configui
echo $LDFLAGS
build(){
foreach GOOS $1
echo $GOOS
}
build $PLATFORMS

View File

@ -3,8 +3,15 @@
// }
#editor,#result_editor {
height: 75vh;
font-size: 1rem;
position: relative;
width: inherit !important;
}
#editor {
height: 70vh;
}
#result_editor {
min-height: 50vh;
}

View File

@ -12,6 +12,10 @@ $modal-content-width: 90vw;
position: fixed; /* Sit on top of the page content */
top: 1;
left: 50%;
z-index: 2;
z-index: 50;
transform: translateX(-50%)
}
#title {
padding: 0.5rem;
}

View File

@ -1,9 +1,9 @@
{{define "components/editor"}}
{{template "components/toolbar" .}}
<container class="container is-max-desktop">
<!-- <container class="container is-max-desktop"> -->
<div id="editor">{{.File.Content}}</div>
</container>
<!-- </container> -->
<script>
function setEditor(){
var beautify = ace.require("ace/ext/beautify");

View File

@ -29,6 +29,9 @@ function setResult(){
result_editor.setTheme("ace/theme/monokai");
result_editor.session.setMode("ace/mode/sh");
result_editor.setReadOnly(true);
result_editor.setOptions({
maxLines: 1000
});
}
function ResultViewTog(){

View File

@ -3,7 +3,10 @@
<div class="level-left">
<div class="field has-addons">
<p class="control">
<div class="select">
<button class="button is-small" onclick="editor.gotoLine(editor.session.getLength())">Bottom</button>
</p>
<p class="control">
<div class="select is-small">
<select onchange="SetTabstop(this)">
<option value="0">Tabstop</option>
<option value="4">Tabstop 4</option>
@ -13,13 +16,13 @@
</div>
</p>
<p class="control">
<button class="button" id="toolFollow" onclick="toolFollow()">Follow</button>
<button class="button is-small" id="toolFollow" onclick="toolFollow()">Follow</button>
</p>
<p class="control">
<button class="button" onclick="toolFormat()">Format</button>
<button class="button is-small" onclick="toolFormat()">Format</button>
</p>
<p class="control">
<button class="button is-light is-danger" id="toolWrap" onclick="toggleWrap()">NoWrap</button>
<button class="button is-small is-light is-danger" id="toolWrap" onclick="toggleWrap()">NoWrap</button>
</p>
</div>
</div>
@ -27,29 +30,30 @@
<div class="level-right">
<div class="field has-addons">
<p class="control">
<button class="button" id="toolRefresh" onclick="toolRefresh()">Refresh</button>
<button class="button is-small" id="toolRefresh" onclick="toolRefresh()">Refresh</button>
</p>
{{if not .File.RO}}
<p class="control">
{{if eq .File.Alias "ConfigUI"}}
<button class="button" id="toolSave" onclick="toolSave()">Apply</button>
<button class="button is-small" id="toolSave" onclick="toolSave()">Apply</button>
{{else}}
<button class="button" id="toolSave" onclick="toolSave()">Save</button>
<button class="button is-small" id="toolSave" onclick="toolSave()">Save</button>
{{end}}
</p>
{{end}}
{{if .File.Action}}
<p class="control">
<button class="button has-tooltip-arrow"
<button class="button is-small has-tooltip-arrow"
data-tooltip="{{.File.Action}}"
id="toolApply" onclick="toolApply()"
>Apply</button>
</p>
{{/* <p class="control">
<a class="button" href="/api/dl?name">Download</a>
</p> */}}
{{end}}
{{/* TEST */}}
<p class="control">
<a class="button is-small" href="/api/export?name={{.File.Alias}}">Download</a>
</p>
</div>
</div>
</div>

View File

@ -6,7 +6,7 @@ var Active = "{{.File.Alias}}";
</script>
<section class="hero is-small is-primary">
<div class="hero-body">
<div class="hero-body" id="title">
<p class="title">
ConfigUI
</p>
@ -19,7 +19,7 @@ var Active = "{{.File.Alias}}";
{{template "components/menu" .}}
</div>
<div class="box has-text-centered">
<a href="/api/export" class="button">Export Files</a>
<a href="/api/export" class="button is-small">Export Files</a>
</div>
</div>
<div class="column">