-
Notifications
You must be signed in to change notification settings - Fork 0
/
recent.go
162 lines (142 loc) · 4.05 KB
/
recent.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
package main
import (
"fmt"
"html/template"
"log"
"net/http"
"os"
"sort"
"strconv"
"strings"
"time"
"cloud.google.com/go/storage"
"github.com/jehiah/legislator/db"
)
type RecentLegislation struct {
File string
Name string
Date time.Time // recent change
Action string
StatusName string
BodyName string
PrimarySponsor db.PersonReference
NumberSponsors int
}
func (r RecentLegislation) Number() int {
c := strings.Split(strings.TrimPrefix(r.File, "Int "), "-")
if len(c) == 2 {
n, _ := strconv.Atoi(c[0])
return n
}
return 0
}
func (l RecentLegislation) IntroLink() template.URL {
return template.URL("/" + strings.TrimPrefix(l.File, "Int "))
}
func (l RecentLegislation) IntroLinkText() string {
return "intro.nyc/" + strings.TrimPrefix(l.File, "Int ")
}
func NewRecentLegislation(l Legislation) RecentLegislation {
r := RecentLegislation{
File: l.File,
Name: l.Name,
BodyName: l.BodyName,
StatusName: l.StatusName,
Date: l.IntroDate,
PrimarySponsor: l.PrimarySponsor(),
NumberSponsors: len(l.Sponsors),
}
r.Action, r.Date = l.RecentAction()
return r
}
func isSameDate(a, b time.Time) bool {
y1, m1, d1 := a.In(americaNewYork).Date()
y2, m2, d2 := b.In(americaNewYork).Date()
return y1 == y2 && m1 == m2 && d1 == d2
}
type DateGroup struct {
Date time.Time
Legislation []RecentLegislation
}
func (d DateGroup) IsFuture() bool {
return d.Date.After(time.Now())
}
func NewDateGroups(r []RecentLegislation) []DateGroup {
var o []DateGroup
if len(r) == 0 {
return o
}
o = append(o, DateGroup{Date: r[0].Date})
for _, rr := range r {
if !isSameDate(rr.Date, o[len(o)-1].Date) {
o = append(o, DateGroup{Date: rr.Date})
}
o[len(o)-1].Legislation = append(o[len(o)-1].Legislation, rr)
}
sort.Slice(o, func(i, j int) bool { return o[i].Date.After(o[j].Date) })
for _, g := range o {
sort.Slice(g.Legislation, func(i, j int) bool { return g.Legislation[i].Number() < g.Legislation[j].Number() })
}
return o
}
// RecentLegislation returns the list of legislation changes /recent
func (a *App) RecentLegislation(w http.ResponseWriter, r *http.Request) {
t := newTemplate(a.templateFS, "recent_legislation.html")
type Page struct {
Page string
LastSync LastSync
Dates []DateGroup
ResubmitLookup map[string]*Legislation
}
body := Page{
Page: "recent",
ResubmitLookup: make(map[string]*Legislation),
}
var legislation LegislationList
// get all the years for the legislative session
for year := CurrentSession.StartYear; year <= CurrentSession.EndYear && year <= time.Now().Year(); year++ {
var l []Legislation
err := a.getJSONFile(r.Context(), fmt.Sprintf("build/%d.json", year), &l)
if err != nil {
if err == storage.ErrObjectNotExist || os.IsNotExist(err) {
continue
}
log.Print(err)
http.Error(w, "Internal Server Error", 500)
return
}
legislation = append(legislation, l...)
}
body.Dates = NewDateGroups(legislation.Recent(time.Hour * 24 * 30))
// build a lookup of re-submit bills
for year := CurrentSession.StartYear; year <= CurrentSession.EndYear && year <= time.Now().Year(); year++ {
var resubmitFile ResubmitFile
err := a.getJSONFile(r.Context(), fmt.Sprintf("build/resubmit_%d.json", year), &resubmitFile)
if err != nil {
if err == storage.ErrObjectNotExist || os.IsNotExist(err) {
continue
}
log.Print(err)
http.Error(w, "Internal Server Error", 500)
return
}
for _, r := range resubmitFile.Resubmitted {
body.ResubmitLookup[r.ToFile] = &Legislation{Legislation: db.Legislation{File: r.FromFile}}
}
}
cacheTTL := time.Minute * 30
err := a.getJSONFile(r.Context(), "build/last_sync.json", &body.LastSync)
if err != nil {
log.Print(err)
http.Error(w, "Internal Server Error", 500)
return
}
w.Header().Set("content-type", "text/html")
a.addExpireHeaders(w, cacheTTL)
err = t.ExecuteTemplate(w, "recent_legislation.html", body)
if err != nil {
log.Print(err)
http.Error(w, "Internal Server Error", 500)
return
}
}