2023-12-27 03:06:11 +01:00
|
|
|
package main
|
|
|
|
|
2023-12-27 03:46:20 +01:00
|
|
|
/*
|
|
|
|
This file is part of taler-dashboard
|
|
|
|
Copyright (C) 2023 Özgür Kesim
|
|
|
|
|
|
|
|
taler-dashboard is free software; you can redistribute it and/or modify it
|
|
|
|
under the terms of the GNU Affero General Public License as published by the
|
|
|
|
Free Software Foundation; either version 3, or (at your option) any later
|
|
|
|
version.
|
|
|
|
|
|
|
|
taler-dashboard is distributed in the hope that it will be useful, but
|
|
|
|
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
|
|
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
|
|
|
License for more details.
|
|
|
|
|
|
|
|
You can receive a copy of the GNU Affero General Public License from
|
|
|
|
<http://www.gnu.org/licenses/>
|
|
|
|
|
|
|
|
@author Özgür Kesim <oec-taler@kesim.org>
|
|
|
|
*/
|
|
|
|
|
2023-12-27 03:06:11 +01:00
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
|
|
|
"html/template"
|
|
|
|
"io"
|
|
|
|
"log"
|
|
|
|
"net/http"
|
|
|
|
"strings"
|
|
|
|
"sync"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
type Data struct {
|
|
|
|
mux sync.RWMutex
|
|
|
|
url string
|
|
|
|
token string
|
|
|
|
num int
|
|
|
|
projectId int
|
|
|
|
filterId int
|
|
|
|
minimumVersion string
|
|
|
|
tmpl *template.Template
|
|
|
|
ctx context.Context
|
|
|
|
|
|
|
|
Issues Issues
|
|
|
|
Timestamp time.Time
|
2023-12-27 04:18:58 +01:00
|
|
|
Freq time.Duration
|
2023-12-27 03:06:11 +01:00
|
|
|
Lasterror error
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewData(ctx context.Context, url, token string, num int) *Data {
|
|
|
|
data := &Data{
|
|
|
|
url: url,
|
|
|
|
token: token,
|
|
|
|
ctx: ctx,
|
|
|
|
num: num,
|
|
|
|
}
|
|
|
|
fm := map[string]any{
|
|
|
|
"shorten": func(max int, s string) string {
|
|
|
|
if len(s) <= max {
|
|
|
|
return s
|
|
|
|
}
|
|
|
|
return s[:max] + "⋯"
|
|
|
|
},
|
|
|
|
}
|
|
|
|
data.tmpl = template.Must(template.New("index").Funcs(fm).ParseFS(content, "*.tmpl"))
|
|
|
|
|
|
|
|
return data
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *Data) update() {
|
|
|
|
url := fmt.Sprintf("%s?project_id=%dfilter_id=%d&page_size=%d",
|
|
|
|
d.url, d.projectId, d.filterId, d.num)
|
|
|
|
req, e := http.NewRequestWithContext(d.ctx, "GET", url, nil)
|
|
|
|
if nil != e {
|
|
|
|
d.mux.Lock()
|
|
|
|
defer d.mux.Unlock()
|
|
|
|
d.Lasterror = e
|
|
|
|
return
|
|
|
|
}
|
|
|
|
req.Header.Add("Authorization", d.token)
|
|
|
|
|
|
|
|
r, e := http.DefaultClient.Do(req)
|
|
|
|
if nil != e {
|
|
|
|
d.mux.Lock()
|
|
|
|
defer d.mux.Unlock()
|
|
|
|
d.Lasterror = e
|
|
|
|
return
|
|
|
|
} else if 200 != r.StatusCode {
|
|
|
|
d.mux.Lock()
|
|
|
|
defer d.mux.Unlock()
|
|
|
|
d.Lasterror = fmt.Errorf("Got unexpected status %s\n", r.Status)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
iss := struct{ Issues Issues }{}
|
|
|
|
e = json.NewDecoder(r.Body).Decode(&iss)
|
|
|
|
|
|
|
|
d.mux.Lock()
|
|
|
|
defer d.mux.Unlock()
|
|
|
|
d.Lasterror = e
|
|
|
|
if nil != e {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
d.Timestamp = time.Now()
|
|
|
|
|
|
|
|
// Filter issues with old target versions out
|
|
|
|
var issues = Issues{}
|
|
|
|
for _, issue := range iss.Issues {
|
|
|
|
if strings.Compare(d.minimumVersion, issue.TargetVersion.Name) < 0 {
|
|
|
|
issues = append(issues, issue)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
d.Issues = issues
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *Data) printJSON(w io.Writer) {
|
|
|
|
d.mux.RLock()
|
|
|
|
defer d.mux.RUnlock()
|
|
|
|
|
|
|
|
if nil == d.Issues {
|
|
|
|
fmt.Fprintln(w, "{}")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
enc := json.NewEncoder(w)
|
|
|
|
enc.SetIndent("", " ")
|
|
|
|
enc.Encode(d.Issues)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *Data) printTemplate(w io.Writer, name string) {
|
|
|
|
d.mux.RLock()
|
|
|
|
defer d.mux.RUnlock()
|
|
|
|
e := d.tmpl.ExecuteTemplate(w, name, d)
|
|
|
|
if nil != e {
|
|
|
|
log.Println(e)
|
|
|
|
}
|
|
|
|
}
|