Refactor web #26

Merged
tardisx merged 8 commits from refactor-web into main 2023-11-20 07:38:17 +10:30
2 changed files with 88 additions and 31 deletions
Showing only changes of commit 24251a87c8 - Show all commits

View File

@ -1,12 +1,16 @@
{{ define "content" }} {{ define "content" }}
<div id="layout" class="pure-g pure-u-1" x-data="popup_create()" x-init=""> <div id="layout" class="pure-g pure-u-1" x-data="popup_create()" >
<h2>Download create</h2> <h2>Download create</h2>
<p>URL: <tt>{{ .url }}</tt></p> <p>URL: <tt>{{ .url }}</tt></p>
<p class="error" x-show="error_message" x-transition.duration.500ms x-text="error_message"></p>
<table class="pure-table" > <table class="pure-table" >
<tr> <tr>
<th>profile</th> <th>profile</th>
<td> <td>
<select x-bind:disabled="profile_chosen" x-on:change="update_profile()" class="pure-input-1-2" x-model="profile_chosen"> <select class="pure-input-1-2" x-model="profile_chosen">
<option value="">choose a profile</option> <option value="">choose a profile</option>
{{ range $i := .config.DownloadProfiles }} {{ range $i := .config.DownloadProfiles }}
<option>{{ $i.Name }}</option> <option>{{ $i.Name }}</option>
@ -17,8 +21,8 @@
<tr> <tr>
<th>destination</th> <th>destination</th>
<td> <td>
<select x-on:change="update_destination()" class="pure-input-1-2" x-model="destination_chosen"> <select class="pure-input-1-2" x-model="destination_chosen">
<option value="-">leave in {{ .config.Server.DownloadPath }}</option> <option value="">leave in {{ .config.Server.DownloadPath }}</option>
{{ range $i := .config.Destinations }} {{ range $i := .config.Destinations }}
<option>{{ $i.Name }}</option> <option>{{ $i.Name }}</option>
{{ end }} {{ end }}
@ -39,18 +43,28 @@
<script> <script>
function popup_create() { function popup_create() {
return { return {
profile_chosen: null, profile_chosen: "",
destination_chosen: null, destination_chosen: "",
error_message: "",
start() { start() {
let op = { let op = {
method: 'POST', method: 'POST',
body: JSON.stringify({action: 'start'}), body: JSON.stringify({action: 'start', url: '{{ .url }}', profile: this.profile_chosen, destination: this.destination_chosen}),
headers: { 'Content-Type': 'application/json' } headers: { 'Content-Type': 'application/json' }
}; };
fetch('/rest/fetch', op) fetch('/fetch', op)
.then(response => response.json()) .then(response => response.json())
.then(info => { .then(response => {
console.log(info) console.log(response)
if (response.error) {
this.error_message = response.error;
this.success_message = '';
document.body.scrollTop = document.documentElement.scrollTop = 0;
} else {
this.error_message = '';
console.log(response.location)
window.location = response.location
}
}) })
} }
} }

View File

@ -22,6 +22,11 @@ type successResponse struct {
Message string `json:"message"` Message string `json:"message"`
} }
type queuedResponse struct {
Success bool `json:"success"`
Location string `json:"location"`
}
type errorResponse struct { type errorResponse struct {
Success bool `json:"success"` Success bool `json:"success"`
Error string `json:"error"` Error string `json:"error"`
@ -314,8 +319,11 @@ func fetchInfoRESTHandler(dm *download.Manager) func(w http.ResponseWriter, r *h
} }
} }
// fetchHandler shows the popup, either the initial form (for create) or the form when in
// progress (to be updated by REST) - this is determined by GET vs POST
func fetchHandler(cs *config.ConfigService, vm *version.Manager, dm *download.Manager) func(w http.ResponseWriter, r *http.Request) { func fetchHandler(cs *config.ConfigService, vm *version.Manager, dm *download.Manager) func(w http.ResponseWriter, r *http.Request) {
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
log.Printf("fetchHandler ")
method := r.Method method := r.Method
@ -328,7 +336,7 @@ func fetchHandler(cs *config.ConfigService, vm *version.Manager, dm *download.Ma
if method == "GET" && idOK == nil && idInt > 0 { if method == "GET" && idOK == nil && idInt > 0 {
// existing, load it up // existing, load it up
log.Printf("loading popup for id %d", idInt)
dl, err := dm.GetDlById(int(idInt)) dl, err := dm.GetDlById(int(idInt))
if err != nil { if err != nil {
log.Printf("not found") log.Printf("not found")
@ -350,40 +358,75 @@ func fetchHandler(cs *config.ConfigService, vm *version.Manager, dm *download.Ma
return return
} else if method == "POST" { } else if method == "POST" {
// creating a new one // creating a new one
panic("should not get here") type reqType struct {
URL string `json:"url"`
ProfileChosen string `json:"profile"`
DestinationChosen string `json:"destination"`
}
query := r.URL.Query() req := reqType{}
url, present := query["url"] json.NewDecoder(r.Body).Decode(&req)
if !present { log.Printf("popup POST request: %#v", req)
if req.URL == "" {
w.WriteHeader(400) w.WriteHeader(400)
fmt.Fprint(w, "No url supplied") json.NewEncoder(w).Encode(errorResponse{
Success: false,
Error: "No URL supplied",
})
return return
} else { } else {
log.Printf("popup for %s (POST)", url)
if req.ProfileChosen == "" {
w.WriteHeader(400)
json.NewEncoder(w).Encode(errorResponse{
Success: false,
Error: "you must choose a profile",
})
return
}
profile := cs.Config.ProfileCalled(req.ProfileChosen)
if profile == nil {
w.WriteHeader(400)
json.NewEncoder(w).Encode(errorResponse{
Success: false,
Error: fmt.Sprintf("no such profile: '%s'", req.ProfileChosen),
})
return
}
destination := cs.Config.DestinationCalled(req.DestinationChosen)
if req.DestinationChosen != "" && destination == nil {
w.WriteHeader(400)
json.NewEncoder(w).Encode(errorResponse{
Success: false,
Error: fmt.Sprintf("no such destination: '%s'", req.DestinationChosen),
})
return
}
// create the new download // create the new download
newDL := download.NewDownload(url[0], cs.Config) newDL := download.NewDownload(req.URL, cs.Config)
id := newDL.Id
newDL.Destination = destination
newDL.DownloadProfile = *profile
dm.AddDownload(newDL) dm.AddDownload(newDL)
dm.Queue(newDL)
t, err := template.ParseFS(webFS, "web/layout.tmpl", "web/popup.html") w.WriteHeader(200)
if err != nil { json.NewEncoder(w).Encode(queuedResponse{
panic(err) Success: true,
} Location: fmt.Sprintf("/fetch/%d", id),
})
newDL.Lock.Lock()
defer newDL.Lock.Unlock()
templateData := map[string]interface{}{"Version": vm.GetInfo(), "dl": newDL, "config": cs.Config, "canStop": download.CanStopDownload}
err = t.ExecuteTemplate(w, "layout", templateData)
if err != nil {
panic(err)
}
} }
} else { } else {
// a GET, show the popup so they can start the download (or just close // a GET, show the popup so they can start the download (or just close
// the popup if they didn't mean it) // the popup if they didn't mean it)
log.Print("loading popup for a new download")
query := r.URL.Query() query := r.URL.Query()
url, present := query["url"] url, present := query["url"]