pull/36/head
Evan 2021-10-23 12:55:05 +08:00
parent 3931d30181
commit 829e7637ca
15 changed files with 105 additions and 30 deletions

2
.gitignore vendored
View File

@ -1,5 +1,5 @@
dist dist
node_modules node_modules
.parcel-cache .parcel-cache
public/css/main.css* public/css/main.css.map
public/js/main.js* public/js/main.js*

View File

@ -4,13 +4,20 @@
* download files #26 * download files #26
* add goto last line toolbar #21 * add goto last line toolbar #21
* use parcel to load main.js
* use icons * use icons
* bind ctrl-s (cmd-s) to fileSave
* refactor as lib #15
* Set Title to be changeable #24
* show run result below #33
* set font size #31
* Hide Config zone for other usage such as go playground #23
## Fix ## Fix
* all cmds should be pass straight back to user * all cmd output should be pass straight back to user
* timeout on none ending cmds #34 * timeout on none ending cmd #34
* add sys setting to conf #32
* Apply should save before taking action #19
# 0.1.1 # 0.1.1

View File

@ -23,10 +23,10 @@ run: build
.PHONY: web .PHONY: web
web: web:
npm run build npm run build
npm run js-dev # npm run js-dev
.PHONY: build .PHONY: build
build: web build:
go build ${LDFLAGS} -o dist/${PROJ} cmd/$(PROJ)/main.go go build ${LDFLAGS} -o dist/${PROJ} cmd/$(PROJ)/main.go

5
app.go
View File

@ -28,7 +28,10 @@ type Page struct {
Error string Error string
File ActiveFile File ActiveFile
Editor Editor Editor Editor
Static bool Static bool
HideConfig bool
ResultBellow bool
} }
func (cui *ConfigUI) App(w http.ResponseWriter, r *http.Request) { func (cui *ConfigUI) App(w http.ResponseWriter, r *http.Request) {
@ -63,6 +66,8 @@ func (cui *ConfigUI) App(w http.ResponseWriter, r *http.Request) {
Platform: plat, Platform: plat,
}, },
Static: cui.NoReconfig, Static: cui.NoReconfig,
HideConfig: cui.HideConfig,
ResultBellow: cui.ResultBellow,
} }
content := "" content := ""

View File

@ -100,7 +100,7 @@ func main() {
// setup routes // setup routes
server := &http.Server{ server := &http.Server{
Addr: flagBind, Addr: flagBind,
WriteTimeout: time.Second * 3, WriteTimeout: time.Second * 30,
ReadTimeout: time.Second * 30, ReadTimeout: time.Second * 30,
Handler: cui, Handler: cui,
} }

View File

@ -48,7 +48,15 @@ type ConfigUI struct {
} }
func New() *ConfigUI { func New() *ConfigUI {
tmpl := template.Must(template.New("").ParseFS(tmplFS, "templates/*.tmpl", "templates/**/*.tmpl")) 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{ return &ConfigUI{
fileIndex: map[string]int{}, fileIndex: map[string]int{},
AppName: "ConfigUI", AppName: "ConfigUI",

View File

@ -75,12 +75,12 @@ func (f *File) Do() (string, error) {
done <- string(out) done <- string(out)
}() }()
select { select {
case <-time.After(5 * time.Second): case <-time.After(10 * time.Second):
cmd.Process.Kill() cmd.Process.Kill()
log.Println("timeout") log.Println("timeout")
return "", errors.New("command timeout") return "", errors.New("command timeout")
case out := <-done: case out := <-done:
log.Println("\n", out) log.Printf("\n%v", out)
return out, nil return out, nil
} }
} }

View File

1
public/css/main.css Normal file

File diff suppressed because one or more lines are too long

View File

@ -1,6 +1,7 @@
{{define "base/script"}} {{define "base/script"}}
<script> <script>
window.ToolIsFollow = false; window.ToolIsFollow = false;
window.ContentChanged = false;
async function FileGet(follower=false){ async function FileGet(follower=false){
let f = '' let f = ''
@ -37,7 +38,10 @@ async function FileSave(){
'Content-Type': 'application/json' 'Content-Type': 'application/json'
}) })
}).catch(err=>{console.log(err);return;}); }).catch(err=>{console.log(err);return;});
if (res.ok) window.location.reload(); if (res.ok) {
window.location.reload();
window.ContentChanged = false
}
else Catch(res) else Catch(res)
} }
else { else {
@ -49,6 +53,7 @@ async function FileSave(){
}) })
}).catch(err=>{console.log(err);return;}); }).catch(err=>{console.log(err);return;});
if(!res.ok) Catch(res) if(!res.ok) Catch(res)
else window.ContentChanged = false
} }
} }
@ -71,13 +76,25 @@ async function FileApply(){
} }
async function Catch(res){ async function Catch(res){
console.trace() {{/* console.trace()
console.log(res) console.log(res) */}}
const msg = await res.text() const msg = await res.text()
ShowError(msg) ShowError(msg)
return msg return msg
} }
function setResult(){
var result_editor = ace.edit("result_editor");
window.result_editor = result_editor
result_editor.setTheme("ace/theme/monokai");
result_editor.session.setMode("ace/mode/sh");
result_editor.setReadOnly(true);
result_editor.setOptions({
maxLines: 1000
});
}
// starting point // starting point
(function(){ (function(){

View File

@ -15,6 +15,21 @@ function setEditor(){
editor.session.setUseWrapMode(false); editor.session.setUseWrapMode(false);
editor.session.setNewLineMode('{{.Editor.Platform}}') editor.session.setNewLineMode('{{.Editor.Platform}}')
editor.setReadOnly({{.File.RO}}); editor.setReadOnly({{.File.RO}});
editor.session.on('change', function(delta) {
// delta.start, delta.end, delta.lines, delta.action
window.ContentChanged = true
});
editor.commands.addCommand({
name: 'SaveContent',
bindKey: {win: 'Ctrl-S', mac: 'Command-S'},
exec: function(editor) {
//...
FileSave()
},
readOnly: false // false if this command should not apply in readOnly mode
});
} }
</script> </script>
{{end}} {{end}}

View File

@ -14,6 +14,7 @@
</li> </li>
{{ end }} {{ end }}
</ul> </ul>
{{if not .HideConfig}}
<p class="menu-label"> <p class="menu-label">
System System
</p> </p>
@ -24,6 +25,7 @@
href="/" href="/"
>Config</a></li> >Config</a></li>
</ul> </ul>
{{end}}
</aside> </aside>
</section> </section>
{{end}} {{end}}

View File

@ -23,17 +23,6 @@
</div> </div>
<script> <script>
function setResult(){
var result_editor = ace.edit("result_editor");
window.result_editor = result_editor
result_editor.setTheme("ace/theme/monokai");
result_editor.session.setMode("ace/mode/sh");
result_editor.setReadOnly(true);
result_editor.setOptions({
maxLines: 1000
});
}
function ResultViewTog(){ function ResultViewTog(){
let el = document.getElementById('result_view') let el = document.getElementById('result_view')
el.classList.toggle('is-active') el.classList.toggle('is-active')

View File

@ -47,6 +47,16 @@
</select> </select>
</div> </div>
</p> </p>
<p class="control">
<div class="select is-small">
<select onchange="toolSetFontSize(this)">
<option value="1rem">1rem</option>
{{range step 8 36 2}}
<option value="{{.}}px">{{.}}px</option>
{{end}}
</select>
</div>
</p>
</div> </div>
</div> </div>
@ -63,12 +73,14 @@
{{if not .File.RO}} {{if not .File.RO}}
<p class="control"> <p class="control">
{{if eq .File.Name .AppName}} {{if eq .File.Name .AppName}}
{{if not .Static}}
<button class="button is-small has-tooltip-arrow" <button class="button is-small has-tooltip-arrow"
data-tooltip="Apply" onclick="toolSave()"> data-tooltip="Apply" onclick="toolSave()">
<span class="icon is-small"><span class="material-icons" id="toolSaveIco"> <span class="icon is-small"><span class="material-icons" id="toolSaveIco">
play_arrow play_arrow
</span></span> </span></span>
</button> </button>
{{end}}
{{else}} {{else}}
<button class="button is-small has-tooltip-arrow" <button class="button is-small has-tooltip-arrow"
data-tooltip="Save" onclick="toolSave()"> data-tooltip="Save" onclick="toolSave()">
@ -91,7 +103,6 @@
</p> </p>
{{end}} {{end}}
{{/* TEST */}}
<p class="control"> <p class="control">
<a class="button is-small has-tooltip-arrow" data-tooltip="Download" <a class="button is-small has-tooltip-arrow" data-tooltip="Download"
href="/api/export?name={{.File.Name}}"> href="/api/export?name={{.File.Name}}">
@ -145,6 +156,12 @@ function toolFormat(){
beautify.beautify(editor.session); beautify.beautify(editor.session);
} }
function toolSetFontSize(obj){
let value = obj.value;
document.getElementById('editor').style.fontSize=value;
document.getElementById('result_editor').style.fontSize=value;
}
function toolFollow(){ function toolFollow(){
if (ToolIsFollow){ if (ToolIsFollow){
ToolIsFollow = false ToolIsFollow = false
@ -184,12 +201,15 @@ async function toolSave(){
async function toolApply(){ async function toolApply(){
let el = document.getElementById('toolApplyIco'); let el = document.getElementById('toolApplyIco');
let originText = el.innerText; let originText = el.innerText;
el.innerText='refreash'; el.innerText='rotate_right';
el.classList.add("icn-loading") el.classList.add("icn-loading")
FileApply() if (window.ContentChanged){
await FileSave()
}
await FileApply()
el.innerText=originText; el.innerText=originText;
el.classList.remove("icn-loading") el.classList.remove("icn-loading")
ResultViewTog() {{if not .ResultBellow}}ResultViewTog(){{end}}
} }
</script> </script>
{{end}} {{end}}

View File

@ -24,10 +24,21 @@ var Active = "{{.File.Name}}";
</div> </div>
<div class="column"> <div class="column">
<div class="box"> <div class="box">
{{if and .HideConfig (eq .File.Name .AppName)}}
Home
{{else}}
{{template "components/editor" .}} {{template "components/editor" .}}
{{end}}
</div> </div>
{{if .ResultBellow}}
<div class="box">
<div id="result_editor"></div>
</div>
{{end}}
</div> </div>
</div> </div>
{{if not .ResultBellow}}
{{template "components/result" .}} {{template "components/result" .}}
{{end}}
{{template "base/footer" .}} {{template "base/footer" .}}
{{end}} {{end}}