added version details
This commit is contained in:
parent
3fb0453a86
commit
9afc0ce0ff
75
data.go
75
data.go
@ -47,7 +47,7 @@ type Data struct {
|
||||
|
||||
Issues Issues
|
||||
Features Issues
|
||||
Projects Projects
|
||||
Project Project
|
||||
Timestamp time.Time
|
||||
Freq time.Duration
|
||||
Lasterror error
|
||||
@ -73,6 +73,63 @@ func NewData(ctx context.Context, url, token string, num int) *Data {
|
||||
return data
|
||||
}
|
||||
|
||||
func (d *Data) getProject() {
|
||||
url := fmt.Sprintf("%s/projects/%d", d.url, d.projectId)
|
||||
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
|
||||
}
|
||||
|
||||
var project Project
|
||||
p := struct{ Projects []Project }{}
|
||||
e = json.NewDecoder(r.Body).Decode(&p)
|
||||
|
||||
if len(p.Projects) < 1 {
|
||||
e = fmt.Errorf("no project found with id", d.projectId)
|
||||
} else {
|
||||
// filter out obsolete versions
|
||||
project = p.Projects[0]
|
||||
var versions Versions
|
||||
log.Println("found", len(project.Versions), "versions")
|
||||
for _, v := range project.Versions {
|
||||
v := v
|
||||
if !v.Obsolete && !v.Released {
|
||||
versions = append(versions, v)
|
||||
}
|
||||
}
|
||||
project.Versions = versions
|
||||
}
|
||||
|
||||
d.mux.Lock()
|
||||
defer d.mux.Unlock()
|
||||
d.Lasterror = e
|
||||
if nil != e {
|
||||
return
|
||||
}
|
||||
|
||||
d.Timestamp = time.Now()
|
||||
d.Project = project
|
||||
|
||||
fmt.Println("Got project details for", d.projectId, "with", len(d.Project.Versions), "version entries")
|
||||
}
|
||||
|
||||
const statusFilter = `status%5B%5D=10&status%5B%5D=20&status%5B%5D=30&status%5B%5D=40&status%5B%5D=50&severity%5B%5D=20`
|
||||
|
||||
var fields = []string{"id",
|
||||
@ -92,7 +149,7 @@ var fields = []string{"id",
|
||||
"tags",
|
||||
}
|
||||
|
||||
func (d *Data) update() {
|
||||
func (d *Data) getIssues() {
|
||||
url := fmt.Sprintf("%s/issues?project_id=%d&page_size=%d&%s&select=%s",
|
||||
d.url, d.projectId, d.num, statusFilter,
|
||||
strings.Join(fields, ","))
|
||||
@ -132,9 +189,11 @@ func (d *Data) update() {
|
||||
// Filter issues with old target versions out
|
||||
var issues = Issues{}
|
||||
var features = Issues{}
|
||||
var open = 0
|
||||
for _, issue := range iss.Issues {
|
||||
if issue.Resolution.Name == "open" &&
|
||||
strings.Compare(d.minimumVersion, issue.TargetVersion.Name) < 0 {
|
||||
open++
|
||||
if issue.Severity.Name == "feature" {
|
||||
features = append(features, issue)
|
||||
} else {
|
||||
@ -144,11 +203,12 @@ func (d *Data) update() {
|
||||
}
|
||||
d.Issues = issues
|
||||
d.Features = features
|
||||
fmt.Println("got", len(iss.Issues), "entries: ", len(features), "features and ", len(issues), "issues")
|
||||
fmt.Println("Got", len(iss.Issues), "entries, of which", open, "are open and relevant:", len(features), "features and", len(issues), "issues")
|
||||
}
|
||||
|
||||
func (d *Data) Loop() {
|
||||
d.update()
|
||||
d.getProject()
|
||||
d.getIssues()
|
||||
go func() {
|
||||
var ticker = time.NewTicker(d.Freq)
|
||||
for range ticker.C {
|
||||
@ -157,7 +217,8 @@ func (d *Data) Loop() {
|
||||
return
|
||||
default:
|
||||
fmt.Println("updating data")
|
||||
d.update()
|
||||
d.getProject()
|
||||
d.getIssues()
|
||||
}
|
||||
}
|
||||
}()
|
||||
@ -203,6 +264,10 @@ func (d *Data) TargetVersions() (tv []string) {
|
||||
return
|
||||
}
|
||||
|
||||
func (d *Data) VersionsByDate() VersionsByDate {
|
||||
return VersionsByDate(d.Project.Versions)
|
||||
}
|
||||
|
||||
func (d *Data) Categories() (cs []string) {
|
||||
d.mux.RLock()
|
||||
defer d.mux.RUnlock()
|
||||
|
@ -31,6 +31,7 @@ pre {
|
||||
{{ $top := . }}
|
||||
{{ $features := .Features }}
|
||||
{{ $issues := .Issues }}
|
||||
{{ $versions := .VersionsByDate }}
|
||||
<!-- p>
|
||||
{{ range $top.Tags }}
|
||||
<button>{{ . }}</button>
|
||||
|
@ -22,8 +22,6 @@ import "time"
|
||||
@author Özgür Kesim <oec-taler@kesim.org>
|
||||
*/
|
||||
|
||||
type Projects []Project
|
||||
|
||||
type Project struct {
|
||||
Id int
|
||||
Name string
|
||||
@ -33,19 +31,37 @@ type Project struct {
|
||||
Enabled bool
|
||||
InheritGlobal bool `json:"inherit_global"`
|
||||
AccessLevel KeyVal `json:"AccessLevel"`
|
||||
Versions []Version
|
||||
Categories []Category
|
||||
Versions Versions
|
||||
Categories Categories
|
||||
// CustomFields []any `json:"custom_fields"`
|
||||
}
|
||||
|
||||
type Versions []Version
|
||||
type Version struct {
|
||||
KeyVal
|
||||
Description string
|
||||
Released bool
|
||||
Obsolete bool
|
||||
Timestamp time.Time
|
||||
}
|
||||
|
||||
type VersionsByDate []Version
|
||||
|
||||
func (v VersionsByDate) Len() int { return len(v) }
|
||||
func (v VersionsByDate) Less(i, j int) bool { return v[i].Timestamp.Before(v[j].Timestamp) }
|
||||
func (v VersionsByDate) Swap(i, j int) { v[i], v[j] = v[j], v[i] }
|
||||
|
||||
type Categories []Category
|
||||
type Category struct {
|
||||
KeyVal
|
||||
Project KeyVal
|
||||
}
|
||||
|
||||
func (vs VersionsByDate) Get(version string) *Version {
|
||||
for i, v := range vs {
|
||||
if v.Name == version {
|
||||
return &vs[i]
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
20
table.tmpl
20
table.tmpl
@ -12,8 +12,7 @@ table {
|
||||
}
|
||||
th, td {
|
||||
padding: 8px;
|
||||
border-bottom: 1px solid #ddd;
|
||||
border-right: 1px solid #ddd;
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
td {
|
||||
min-width: 10em;
|
||||
@ -25,8 +24,11 @@ th.side {
|
||||
tr:hover {
|
||||
background: #efe;
|
||||
}
|
||||
.normal {
|
||||
details.version {
|
||||
margin: 5px;
|
||||
font-weight: normal;
|
||||
max-width: 40em;
|
||||
text-align: justify;
|
||||
}
|
||||
.feature {
|
||||
background: #cde;
|
||||
@ -38,7 +40,7 @@ tr:hover {
|
||||
border-radius: 5px;
|
||||
padding: 8px;
|
||||
}
|
||||
details {
|
||||
details.entry, details.feature {
|
||||
max-width: 30em;
|
||||
overflow-x: auto;
|
||||
white-space: nowrap;
|
||||
@ -58,6 +60,7 @@ details {
|
||||
{{ $top := . }}
|
||||
{{ $features := .Features }}
|
||||
{{ $issues := .Issues }}
|
||||
{{ $versions := .VersionsByDate }}
|
||||
<!--p>
|
||||
{{ range $top.Tags }}
|
||||
<button>{{ . }}</button>
|
||||
@ -69,10 +72,11 @@ details {
|
||||
<th class="side"></th>
|
||||
{{ range $top.TargetVersions }}
|
||||
<th>
|
||||
<details>
|
||||
<summary>{{ . }}</summary>
|
||||
<div class="normal">
|
||||
TODO: more
|
||||
<details class="version">
|
||||
{{ $version := $versions.Get . }}
|
||||
<summary><b>{{ . }}</b> ({{ $version.Timestamp.Format "02 Jan 06"}})</summary>
|
||||
<div>
|
||||
{{ $version.Description }}
|
||||
</div>
|
||||
</details>
|
||||
</th>
|
||||
|
Loading…
Reference in New Issue
Block a user