parent
38afcf64cf
commit
3a64217a10
54
handler.go
54
handler.go
|
@ -2,10 +2,12 @@ package configui
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func (cui *ConfigUI) ListFiles(w http.ResponseWriter, r *http.Request) {
|
||||
|
@ -27,11 +29,63 @@ func (cui *ConfigUI) GetFile(w http.ResponseWriter, r *http.Request) {
|
|||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
stat, err := os.Stat(file.Path)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
response, err := json.Marshal(map[string]string{
|
||||
"path": file.Path,
|
||||
"name": file.Name,
|
||||
"action": file.Action,
|
||||
"data": string(data),
|
||||
"delta": strconv.Itoa(int(stat.Size())),
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.Write(response)
|
||||
}
|
||||
|
||||
func (cui *ConfigUI) GetDelta(w http.ResponseWriter, r *http.Request) {
|
||||
name := r.URL.Query().Get("name")
|
||||
delta, err := strconv.ParseInt(r.URL.Query().Get("delta"), 10, 64)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
file, err := cui.File(name)
|
||||
if err != nil {
|
||||
response(w, 404, []byte("file not found"))
|
||||
return
|
||||
}
|
||||
f, err := os.Open(file.Path)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
stat, err := os.Stat(file.Path)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if delta > stat.Size() {
|
||||
panic(fmt.Errorf("delta(%d) is larger than file size(%d)", delta, stat.Size()))
|
||||
}
|
||||
if stat.Size() < delta {
|
||||
panic(fmt.Errorf("delta(%d) is smaller than file size(%d)", delta, stat.Size()))
|
||||
}
|
||||
buf := make([]byte, stat.Size()-delta)
|
||||
_, err = f.ReadAt(buf, delta)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
response, err := json.Marshal(map[string]string{
|
||||
"path": file.Path,
|
||||
"name": file.Name,
|
||||
"action": file.Action,
|
||||
"data": string(buf),
|
||||
"delta": strconv.Itoa(int(stat.Size())),
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
|
|
@ -33,6 +33,7 @@ func response(w http.ResponseWriter, status int, body []byte) (int, error) {
|
|||
}
|
||||
|
||||
func abort(w http.ResponseWriter, err interface{}) (int, error) {
|
||||
log.Println(err)
|
||||
switch v := err.(type) {
|
||||
case int:
|
||||
w.WriteHeader(v)
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -59,6 +59,13 @@ func (cui *ConfigUI) mux() *http.ServeMux {
|
|||
w.WriteHeader(404)
|
||||
}
|
||||
})
|
||||
cuiR.HandleFunc("/api/delta", func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method == "GET" {
|
||||
cui.GetDelta(w, r)
|
||||
} else {
|
||||
w.WriteHeader(404)
|
||||
}
|
||||
})
|
||||
cuiR.HandleFunc("/api/apply", func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method == "POST" {
|
||||
cui.Apply(w, r)
|
||||
|
|
|
@ -2,12 +2,13 @@
|
|||
<footer class="footer">
|
||||
<div class="content has-text-right">
|
||||
<p>
|
||||
<strong>Configui</strong> {{.Version}} by <a href="https://kumoly.io/evanchen">Evan Chen</a>.
|
||||
<strong>Configui</strong> {{.Version}} by <a href="mailto:evanchen@kumoly.io">Evan Chen</a>.
|
||||
</p>
|
||||
</div>
|
||||
</footer>
|
||||
<script src="{{.BaseUrl}}public/ace/js/ace.js" type="text/javascript" charset="utf-8"></script>
|
||||
<script src="{{.BaseUrl}}public/ace/js/ext-beautify.js" type="text/javascript" charset="utf-8"></script>
|
||||
<script src="{{.BaseUrl}}public/ace/js/ext-searchbox.js" type="text/javascript" charset="utf-8"></script>
|
||||
{{template "base/script" .}}
|
||||
<!-- <script src="/public/js/main.js"></script> -->
|
||||
</body>
|
||||
|
|
|
@ -1,30 +1,30 @@
|
|||
{{define "base/script"}}
|
||||
<script>
|
||||
window.ToolIsFollow = false;
|
||||
window.LastDelta = 0;
|
||||
window.ContentChanged = false;
|
||||
|
||||
async function FileGet(follower=false){
|
||||
let f = ''
|
||||
if (Active == 'ConfigUI') {
|
||||
if (follower) f = '?f=true'
|
||||
const res = await fetch('{{.BaseUrl}}api/conf'+f)
|
||||
async function FileGet(){
|
||||
if (Active == '{{.AppName}}') {
|
||||
const res = await fetch('{{.BaseUrl}}api/conf')
|
||||
.catch(err=>{console.log(err);return;});
|
||||
const body = await res.text();
|
||||
if(!res.ok){
|
||||
Catch(res)
|
||||
return
|
||||
}
|
||||
LastDelta = 0;
|
||||
editor.session.setValue(body);
|
||||
}
|
||||
else {
|
||||
if (follower) f = '&f=true'
|
||||
const res = await fetch('{{.BaseUrl}}api/file?name=' + Active + f)
|
||||
const res = await fetch('{{.BaseUrl}}api/file?name=' + Active)
|
||||
.catch(err=>{console.log(err);return;});
|
||||
const body = await res.json();
|
||||
if(!res.ok){
|
||||
Catch(res)
|
||||
return
|
||||
}
|
||||
LastDelta = body.delta;
|
||||
editor.session.setValue(body.data);
|
||||
}
|
||||
}
|
||||
|
@ -75,6 +75,24 @@ async function FileApply(){
|
|||
}
|
||||
}
|
||||
|
||||
async function FileDelta(){
|
||||
if (Active == '{{.AppName}}') {
|
||||
await FileGet()
|
||||
return
|
||||
}
|
||||
else {
|
||||
const res = await fetch('{{.BaseUrl}}api/delta?f=true&name=' + Active+'&delta='+LastDelta)
|
||||
.catch(err=>{console.log(err);return;});
|
||||
const body = await res.json();
|
||||
if(!res.ok){
|
||||
Catch(res)
|
||||
return
|
||||
}
|
||||
LastDelta = body.delta;
|
||||
editor.session.setValue(editor.getValue()+body.data);
|
||||
}
|
||||
}
|
||||
|
||||
async function Catch(res){
|
||||
{{/* console.trace()
|
||||
console.log(res) */}}
|
||||
|
@ -107,7 +125,7 @@ function setResult(){
|
|||
// for follow mode
|
||||
setInterval((async ()=>{
|
||||
if (ToolIsFollow){
|
||||
await FileGet(true)
|
||||
await FileDelta()
|
||||
editor.gotoLine(editor.session.getLength());
|
||||
}
|
||||
}), 1000)
|
||||
|
|
|
@ -164,20 +164,24 @@ function toolSetFontSize(obj){
|
|||
|
||||
function toolFollow(){
|
||||
if (ToolIsFollow){
|
||||
ToolIsFollow = false
|
||||
ToolIsFollow = false;
|
||||
editor.setReadOnly({{.File.RO}});
|
||||
let el = document.getElementById('toolFollow');
|
||||
let icon = document.getElementById('toolFollowIcon');
|
||||
el.classList.remove('is-primary');
|
||||
icon.classList.remove('icn-spinner');
|
||||
icon.innerText='sync_disabled';
|
||||
} else {
|
||||
ToolIsFollow = true
|
||||
editor.setReadOnly(true);
|
||||
let el = document.getElementById('toolFollow');
|
||||
let icon = document.getElementById('toolFollowIcon');
|
||||
el.classList.add('is-primary');
|
||||
icon.innerText='sync';
|
||||
icon.classList.add('icn-spinner');
|
||||
editor.gotoLine(editor.session.getLength());
|
||||
FileGet().then(()=>{
|
||||
ToolIsFollow = true
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue