parent
38afcf64cf
commit
3a64217a10
54
handler.go
54
handler.go
|
@ -2,10 +2,12 @@ package configui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (cui *ConfigUI) ListFiles(w http.ResponseWriter, r *http.Request) {
|
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 {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
stat, err := os.Stat(file.Path)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
response, err := json.Marshal(map[string]string{
|
response, err := json.Marshal(map[string]string{
|
||||||
"path": file.Path,
|
"path": file.Path,
|
||||||
"name": file.Name,
|
"name": file.Name,
|
||||||
"action": file.Action,
|
"action": file.Action,
|
||||||
"data": string(data),
|
"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 {
|
if err != nil {
|
||||||
panic(err)
|
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) {
|
func abort(w http.ResponseWriter, err interface{}) (int, error) {
|
||||||
|
log.Println(err)
|
||||||
switch v := err.(type) {
|
switch v := err.(type) {
|
||||||
case int:
|
case int:
|
||||||
w.WriteHeader(v)
|
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)
|
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) {
|
cuiR.HandleFunc("/api/apply", func(w http.ResponseWriter, r *http.Request) {
|
||||||
if r.Method == "POST" {
|
if r.Method == "POST" {
|
||||||
cui.Apply(w, r)
|
cui.Apply(w, r)
|
||||||
|
|
|
@ -2,12 +2,13 @@
|
||||||
<footer class="footer">
|
<footer class="footer">
|
||||||
<div class="content has-text-right">
|
<div class="content has-text-right">
|
||||||
<p>
|
<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>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
<script src="{{.BaseUrl}}public/ace/js/ace.js" type="text/javascript" charset="utf-8"></script>
|
<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-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" .}}
|
{{template "base/script" .}}
|
||||||
<!-- <script src="/public/js/main.js"></script> -->
|
<!-- <script src="/public/js/main.js"></script> -->
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -1,30 +1,30 @@
|
||||||
{{define "base/script"}}
|
{{define "base/script"}}
|
||||||
<script>
|
<script>
|
||||||
window.ToolIsFollow = false;
|
window.ToolIsFollow = false;
|
||||||
|
window.LastDelta = 0;
|
||||||
window.ContentChanged = false;
|
window.ContentChanged = false;
|
||||||
|
|
||||||
async function FileGet(follower=false){
|
async function FileGet(){
|
||||||
let f = ''
|
if (Active == '{{.AppName}}') {
|
||||||
if (Active == 'ConfigUI') {
|
const res = await fetch('{{.BaseUrl}}api/conf')
|
||||||
if (follower) f = '?f=true'
|
|
||||||
const res = await fetch('{{.BaseUrl}}api/conf'+f)
|
|
||||||
.catch(err=>{console.log(err);return;});
|
.catch(err=>{console.log(err);return;});
|
||||||
const body = await res.text();
|
const body = await res.text();
|
||||||
if(!res.ok){
|
if(!res.ok){
|
||||||
Catch(res)
|
Catch(res)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
LastDelta = 0;
|
||||||
editor.session.setValue(body);
|
editor.session.setValue(body);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (follower) f = '&f=true'
|
const res = await fetch('{{.BaseUrl}}api/file?name=' + Active)
|
||||||
const res = await fetch('{{.BaseUrl}}api/file?name=' + Active + f)
|
|
||||||
.catch(err=>{console.log(err);return;});
|
.catch(err=>{console.log(err);return;});
|
||||||
const body = await res.json();
|
const body = await res.json();
|
||||||
if(!res.ok){
|
if(!res.ok){
|
||||||
Catch(res)
|
Catch(res)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
LastDelta = body.delta;
|
||||||
editor.session.setValue(body.data);
|
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){
|
async function Catch(res){
|
||||||
{{/* console.trace()
|
{{/* console.trace()
|
||||||
console.log(res) */}}
|
console.log(res) */}}
|
||||||
|
@ -107,7 +125,7 @@ function setResult(){
|
||||||
// for follow mode
|
// for follow mode
|
||||||
setInterval((async ()=>{
|
setInterval((async ()=>{
|
||||||
if (ToolIsFollow){
|
if (ToolIsFollow){
|
||||||
await FileGet(true)
|
await FileDelta()
|
||||||
editor.gotoLine(editor.session.getLength());
|
editor.gotoLine(editor.session.getLength());
|
||||||
}
|
}
|
||||||
}), 1000)
|
}), 1000)
|
||||||
|
|
|
@ -164,20 +164,24 @@ function toolSetFontSize(obj){
|
||||||
|
|
||||||
function toolFollow(){
|
function toolFollow(){
|
||||||
if (ToolIsFollow){
|
if (ToolIsFollow){
|
||||||
ToolIsFollow = false
|
ToolIsFollow = false;
|
||||||
|
editor.setReadOnly({{.File.RO}});
|
||||||
let el = document.getElementById('toolFollow');
|
let el = document.getElementById('toolFollow');
|
||||||
let icon = document.getElementById('toolFollowIcon');
|
let icon = document.getElementById('toolFollowIcon');
|
||||||
el.classList.remove('is-primary');
|
el.classList.remove('is-primary');
|
||||||
icon.classList.remove('icn-spinner');
|
icon.classList.remove('icn-spinner');
|
||||||
icon.innerText='sync_disabled';
|
icon.innerText='sync_disabled';
|
||||||
} else {
|
} else {
|
||||||
ToolIsFollow = true
|
editor.setReadOnly(true);
|
||||||
let el = document.getElementById('toolFollow');
|
let el = document.getElementById('toolFollow');
|
||||||
let icon = document.getElementById('toolFollowIcon');
|
let icon = document.getElementById('toolFollowIcon');
|
||||||
el.classList.add('is-primary');
|
el.classList.add('is-primary');
|
||||||
icon.innerText='sync';
|
icon.innerText='sync';
|
||||||
icon.classList.add('icn-spinner');
|
icon.classList.add('icn-spinner');
|
||||||
editor.gotoLine(editor.session.getLength());
|
editor.gotoLine(editor.session.getLength());
|
||||||
|
FileGet().then(()=>{
|
||||||
|
ToolIsFollow = true
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue