aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/dbx/db.go11
-rw-r--r--src/dbx/mintages.go182
-rw-r--r--src/dbx/sql/last.sql28
-rw-r--r--src/dbx/users.go7
-rw-r--r--src/http.go51
-rw-r--r--src/tables.go108
-rw-r--r--src/templates.go10
-rw-r--r--src/templates/-base.html.tmpl38
-rw-r--r--src/templates/coins-mintages.html.tmpl91
9 files changed, 294 insertions, 232 deletions
diff --git a/src/dbx/db.go b/src/dbx/db.go
index b839531..5ee3782 100644
--- a/src/dbx/db.go
+++ b/src/dbx/db.go
@@ -1,6 +1,7 @@
package dbx
import (
+ "context"
"fmt"
"io/fs"
"log"
@@ -20,6 +21,16 @@ var (
func Init(sqlDir fs.FS) {
db = sqlx.MustConnect("sqlite3", DBName)
atexit.Register(Close)
+
+ conn := Try2(db.Conn(context.Background()))
+ Try(conn.Raw(func(driverConn any) error {
+ return driverConn.(*sqlite3.SQLiteConn).RegisterFunc("C_",
+ func(s, _ string) string {
+ return s
+ }, true)
+ }))
+ conn.Close()
+
Try(applyMigrations(sqlDir))
/* TODO: Remove debug code */
diff --git a/src/dbx/mintages.go b/src/dbx/mintages.go
index 9b98bd6..2223eff 100644
--- a/src/dbx/mintages.go
+++ b/src/dbx/mintages.go
@@ -1,21 +1,22 @@
package dbx
import (
+ "context"
"database/sql"
"slices"
)
type CountryMintageData struct {
Standard []MSCountryRow
- Commemorative []MCCountryRow
+ Commemorative []MCommemorative
}
type YearMintageData struct {
Standard []MSYearRow
- Commemorative []MCYearRow
+ Commemorative []MCommemorative
}
-type msRowInternal struct {
+type msRow struct {
Country string
Type MintageType
Year int
@@ -25,47 +26,29 @@ type msRowInternal struct {
Reference sql.Null[string]
}
-type mcRowInternal struct {
- Country string
- Type MintageType
- Year int
- Name string
- Number int
- Mintmark sql.Null[string]
- Mintage sql.Null[int]
- Reference sql.Null[string]
-}
-
type MSCountryRow struct {
Year int
- Mintmark string
- Mintages [ndenoms]int
- References []string
-}
-
-type MCCountryRow struct {
- Year int
- Name string
- Number int
- Mintmark string
- Mintage int
- Reference string
+ Mintmark sql.Null[string]
+ Mintages [ndenoms]sql.Null[int]
+ References [ndenoms]sql.Null[string]
}
type MSYearRow struct {
Country string
- Mintmark string
- Mintages [ndenoms]int
- References []string
+ Mintmark sql.Null[string]
+ Mintages [ndenoms]sql.Null[int]
+ References [ndenoms]sql.Null[string]
}
-type MCYearRow struct {
- Country string
- Name string
+type MCommemorative struct {
+ Country string
+ Type MintageType
+ Year int
+ Name string
Number int
- Mintmark string
- Mintage int
- Reference string
+ Mintmark sql.Null[string]
+ Mintage sql.Null[int]
+ Reference sql.Null[string]
}
type MintageType int
@@ -77,12 +60,6 @@ const (
TypeProof
)
-/* DO NOT REORDER! */
-const (
- MintageUnknown = -iota - 1
- MintageInvalid
-)
-
const ndenoms = 8
func NewMintageType(s string) MintageType {
@@ -103,10 +80,10 @@ func GetMintagesByYear(year int, typ MintageType) (YearMintageData, error) {
var (
zero YearMintageData
xs []MSYearRow
- ys []MCYearRow
+ ys []MCommemorative
)
- rs, err := db.Queryx(`
+ rs, err := db.QueryxContext(context.TODO(), `
SELECT * FROM mintages_s
WHERE year = ? AND type = ?
ORDER BY country, mintmark, denomination
@@ -116,28 +93,22 @@ func GetMintagesByYear(year int, typ MintageType) (YearMintageData, error) {
}
for rs.Next() {
- var x msRowInternal
+ var x msRow
if err = rs.StructScan(&x); err != nil {
return zero, err
}
loop:
msr := MSYearRow{
- Country: x.Country,
- Mintmark: sqlOr(x.Mintmark, ""),
- References: make([]string, 0, ndenoms),
- }
- for i := range msr.Mintages {
- msr.Mintages[i] = MintageUnknown
- }
- msr.Mintages[denomToIdx(x.Denomination)] =
- sqlOr(x.Mintage, MintageUnknown)
- if x.Reference.Valid {
- msr.References = append(msr.References, x.Reference.V)
+ Country: x.Country,
+ Mintmark: x.Mintmark,
}
+ i := denomToIdx(x.Denomination)
+ msr.Mintages[i] = x.Mintage
+ msr.References[i] = x.Reference
for rs.Next() {
- var y msRowInternal
+ var y msRow
if err = rs.StructScan(&y); err != nil {
return zero, err
}
@@ -148,11 +119,9 @@ func GetMintagesByYear(year int, typ MintageType) (YearMintageData, error) {
goto loop
}
- msr.Mintages[denomToIdx(y.Denomination)] =
- sqlOr(y.Mintage, MintageUnknown)
- if y.Reference.Valid {
- msr.References = append(msr.References, y.Reference.V)
- }
+ i = denomToIdx(y.Denomination)
+ msr.Mintages[i] = y.Mintage
+ msr.References[i] = y.Reference
}
xs = append(xs, msr)
@@ -162,29 +131,11 @@ func GetMintagesByYear(year int, typ MintageType) (YearMintageData, error) {
return zero, err
}
- rs, err = db.Queryx(`
- SELECT * FROM mintages_c
- WHERE year = ? AND type = ?
- ORDER BY country, mintmark, number
+ db.SelectContext(context.TODO(), &ys, `
+ SELECT * FROM mintages_c
+ WHERE year = ? and type = ?
+ ORDER BY country, mintmark, number
`, year, typ)
- if err != nil {
- return zero, err
- }
-
- for rs.Next() {
- var y mcRowInternal
- if err = rs.StructScan(&y); err != nil {
- return zero, err
- }
- ys = append(ys, MCYearRow{
- Country: y.Country,
- Name: y.Name,
- Number: y.Number,
- Mintmark: sqlOr(y.Mintmark, ""),
- Mintage: sqlOr(y.Mintage, MintageUnknown),
- Reference: sqlOr(y.Reference, ""),
- })
- }
return YearMintageData{xs, ys}, nil
}
@@ -193,10 +144,10 @@ func GetMintagesByCountry(country string, typ MintageType) (CountryMintageData,
var (
zero CountryMintageData
xs []MSCountryRow
- ys []MCCountryRow
+ ys []MCommemorative
)
- rs, err := db.Queryx(`
+ rs, err := db.QueryxContext(context.TODO(), `
SELECT * FROM mintages_s
WHERE country = ? AND type = ?
ORDER BY year, mintmark, denomination
@@ -206,28 +157,22 @@ func GetMintagesByCountry(country string, typ MintageType) (CountryMintageData,
}
for rs.Next() {
- var x msRowInternal
+ var x msRow
if err = rs.StructScan(&x); err != nil {
return zero, err
}
loop:
msr := MSCountryRow{
- Year: x.Year,
- Mintmark: sqlOr(x.Mintmark, ""),
- References: make([]string, 0, ndenoms),
- }
- for i := range msr.Mintages {
- msr.Mintages[i] = MintageUnknown
- }
- msr.Mintages[denomToIdx(x.Denomination)] =
- sqlOr(x.Mintage, MintageUnknown)
- if x.Reference.Valid {
- msr.References = append(msr.References, x.Reference.V)
+ Year: x.Year,
+ Mintmark: x.Mintmark,
}
+ i := denomToIdx(x.Denomination)
+ msr.Mintages[i] = x.Mintage
+ msr.References[i] = x.Reference
for rs.Next() {
- var y msRowInternal
+ var y msRow
if err = rs.StructScan(&y); err != nil {
return zero, err
}
@@ -238,11 +183,9 @@ func GetMintagesByCountry(country string, typ MintageType) (CountryMintageData,
goto loop
}
- msr.Mintages[denomToIdx(y.Denomination)] =
- sqlOr(y.Mintage, MintageUnknown)
- if y.Reference.Valid {
- msr.References = append(msr.References, y.Reference.V)
- }
+ i = denomToIdx(y.Denomination)
+ msr.Mintages[i] = y.Mintage
+ msr.References[i] = y.Reference
}
xs = append(xs, msr)
@@ -252,40 +195,15 @@ func GetMintagesByCountry(country string, typ MintageType) (CountryMintageData,
return zero, err
}
- rs, err = db.Queryx(`
- SELECT * FROM mintages_c
- WHERE country = ? AND type = ?
- ORDER BY year, mintmark, number
+ db.SelectContext(context.TODO(), &ys, `
+ SELECT * FROM mintages_c
+ WHERE country = ? and type = ?
+ ORDER BY year, mintmark, number
`, country, typ)
- if err != nil {
- return zero, err
- }
-
- for rs.Next() {
- var y mcRowInternal
- if err = rs.StructScan(&y); err != nil {
- return zero, err
- }
- ys = append(ys, MCCountryRow{
- Year: y.Year,
- Name: y.Name,
- Number: y.Number,
- Mintmark: sqlOr(y.Mintmark, ""),
- Mintage: sqlOr(y.Mintage, MintageUnknown),
- Reference: sqlOr(y.Reference, ""),
- })
- }
return CountryMintageData{xs, ys}, rs.Err()
}
-func sqlOr[T any](v sql.Null[T], dflt T) T {
- if v.Valid {
- return v.V
- }
- return dflt
-}
-
func denomToIdx(d float64) int {
return slices.Index([]float64{
0.01, 0.02, 0.05, 0.10,
diff --git a/src/dbx/sql/last.sql b/src/dbx/sql/last.sql
index fa2adbb..22ebab8 100644
--- a/src/dbx/sql/last.sql
+++ b/src/dbx/sql/last.sql
@@ -133,9 +133,25 @@ INSERT INTO mintages_c (
mintage,
reference
) VALUES
- ('sk', 0, 2014, 'Slovak Republic to the EU', 1, NULL, 1000000, NULL),
- ('sk', 0, 2015, 'Ľudovít Štúr', 1, NULL, 1000000, NULL),
- ('sk', 0, 2015, 'EU Flag', 2, NULL, 1000000, NULL),
- ('fr', 0, 2015, 'Peace and security', 1, NULL, 4000000, NULL),
- ('fr', 0, 2015, 'Fête de la Fédération', 2, NULL, 4000000, NULL),
- ('fr', 0, 2015, 'EU Flag', 3, NULL, 4000000, NULL); \ No newline at end of file
+ ('de', 0, 2015, C_('Hessen', 'CC Name'), 1, 'A', 6000000, NULL),
+ ('de', 0, 2015, C_('German Reunification', 'CC Name'), 2, 'A', 6000000, NULL),
+ ('de', 0, 2015, C_('EU Flag', 'CC Name'), 3, 'A', 6000000, NULL),
+ ('de', 0, 2015, C_('Hessen', 'CC Name'), 1, 'D', 6300000, NULL),
+ ('de', 0, 2015, C_('German Reunification', 'CC Name'), 2, 'D', 6300000, NULL),
+ ('de', 0, 2015, C_('EU Flag', 'CC Name'), 3, 'D', 6300000, NULL),
+ ('de', 0, 2015, C_('Hessen', 'CC Name'), 1, 'F', 7200000, NULL),
+ ('de', 0, 2015, C_('German Reunification', 'CC Name'), 2, 'F', 7200000, NULL),
+ ('de', 0, 2015, C_('EU Flag', 'CC Name'), 3, 'F', 7200000, NULL),
+ ('de', 0, 2015, C_('Hessen', 'CC Name'), 1, 'G', 4200000, NULL),
+ ('de', 0, 2015, C_('German Reunification', 'CC Name'), 2, 'G', 4200000, NULL),
+ ('de', 0, 2015, C_('EU Flag', 'CC Name'), 3, 'G', 4200000, NULL),
+ ('de', 0, 2015, C_('Hessen', 'CC Name'), 1, 'J', 6300000, NULL),
+ ('de', 0, 2015, C_('German Reunification', 'CC Name'), 2, 'J', 6300000, NULL),
+ ('de', 0, 2015, C_('EU Flag', 'CC Name'), 3, 'J', 6300000, NULL),
+ ('sk', 0, 2014, C_('Slovak Republic to the EU', 'CC Name'), 1, NULL, 1000000, NULL),
+ ('sk', 0, 2015, C_('Ľudovít Štúr', 'CC Name'), 1, NULL, 1000000, NULL),
+ ('sk', 0, 2015, C_('EU Flag', 'CC Name'), 2, NULL, 1000000, NULL),
+ ('nl', 0, 2015, C_('EU Flag', 'CC Name'), 2, NULL, NULL, NULL),
+ ('fr', 0, 2015, C_('Peace and security', 'CC Name'), 1, NULL, 4000000, NULL),
+ ('fr', 0, 2015, C_('Fête de la Fédération', 'CC Name'), 2, NULL, 4000000, NULL),
+ ('fr', 0, 2015, C_('EU Flag', 'CC Name'), 3, NULL, 4000000, NULL); \ No newline at end of file
diff --git a/src/dbx/users.go b/src/dbx/users.go
index 4235b28..bf78dcd 100644
--- a/src/dbx/users.go
+++ b/src/dbx/users.go
@@ -1,6 +1,7 @@
package dbx
import (
+ "context"
"database/sql"
"errors"
@@ -27,7 +28,7 @@ func CreateUser(user User) error {
return err
}
- _, err = db.Exec(`
+ _, err = db.ExecContext(context.TODO(), `
INSERT INTO users (
email,
username,
@@ -43,8 +44,8 @@ func Login(username, password string) (User, error) {
username = norm.NFC.String(username)
password = norm.NFC.String(password)
- /* TODO: Pass a context here? */
- rs, err := db.Queryx(`SELECT * FROM users WHERE username = ?`, username)
+ rs, err := db.QueryxContext(context.TODO(),
+ `SELECT * FROM users WHERE username = ?`, username)
if err != nil {
return User{}, err
}
diff --git a/src/http.go b/src/http.go
index 071b25c..fce82ba 100644
--- a/src/http.go
+++ b/src/http.go
@@ -13,8 +13,6 @@ import (
"strings"
"time"
- "golang.org/x/text/collate"
- "golang.org/x/text/language"
. "git.thomasvoss.com/euro-cash.eu/pkg/try"
"git.thomasvoss.com/euro-cash.eu/src/dbx"
@@ -155,7 +153,6 @@ func mintageHandler(next http.Handler) http.Handler {
td.FilterBy = "country"
}
- var err error
mt := dbx.NewMintageType(td.Type)
switch td.FilterBy {
@@ -166,45 +163,25 @@ func mintageHandler(next http.Handler) http.Handler {
}) {
td.Code = td.Countries[0].Code
}
- td.CountryMintages, err = dbx.GetMintagesByCountry(td.Code, mt)
+
+ m, err := dbx.GetMintagesByCountry(td.Code, mt)
+ if err != nil {
+ throwError(http.StatusInternalServerError, err, w, r)
+ return
+ }
+ td.CountryMintages = makeCountryMintageTable(m, td.Printer)
case "year":
+ var err error
td.Year, err = strconv.Atoi(r.FormValue("year"))
- if err != nil {
+ if err != nil || td.Year < 1999 {
td.Year = 1999
}
- td.YearMintages, err = dbx.GetMintagesByYear(td.Year, mt)
-
- /* NOTE: It’s safe to use MustParse() here, because by this
- point we know that all BCPs are valid. */
- c := collate.New(language.MustParse(td.Printer.Bcp))
- for i, r := range td.YearMintages.Standard {
- name := td.Printer.GetC(
- countryCodeToName[r.Country], "Place Name")
- td.YearMintages.Standard[i].Country = name
- }
- for i, r := range td.YearMintages.Commemorative {
- name := td.Printer.GetC(
- countryCodeToName[r.Country], "Place Name")
- td.YearMintages.Commemorative[i].Country = name
+ m, err := dbx.GetMintagesByYear(td.Year, mt)
+ if err != nil {
+ throwError(http.StatusInternalServerError, err, w, r)
+ return
}
- slices.SortFunc(td.YearMintages.Standard, func(x, y dbx.MSYearRow) int {
- Δ := c.CompareString(x.Country, y.Country)
- if Δ == 0 {
- Δ = c.CompareString(x.Mintmark, y.Mintmark)
- }
- return Δ
- })
- slices.SortFunc(td.YearMintages.Commemorative, func(x, y dbx.MCYearRow) int {
- Δ := c.CompareString(x.Country, y.Country)
- if Δ == 0 {
- Δ = c.CompareString(x.Mintmark, y.Mintmark)
- }
- return Δ
- })
- }
- if err != nil {
- throwError(http.StatusInternalServerError, err, w, r)
- return
+ td.YearMintages = makeYearMintageTable(m, td.Printer)
}
next.ServeHTTP(w, r)
diff --git a/src/tables.go b/src/tables.go
new file mode 100644
index 0000000..f99630b
--- /dev/null
+++ b/src/tables.go
@@ -0,0 +1,108 @@
+package app
+
+import (
+ "database/sql"
+ "slices"
+
+ "golang.org/x/text/collate"
+ "golang.org/x/text/language"
+
+ "git.thomasvoss.com/euro-cash.eu/src/dbx"
+ "git.thomasvoss.com/euro-cash.eu/src/i18n"
+)
+
+type YearCCsPair struct {
+ Year int
+ Mintmark sql.Null[string]
+ CCs []dbx.MCommemorative
+}
+
+type CountryMintageTable struct {
+ Standard []dbx.MSCountryRow
+ Commemorative []YearCCsPair
+}
+
+type CountryCCsPair struct {
+ Country string
+ Mintmark sql.Null[string]
+ CCs []dbx.MCommemorative
+}
+
+type YearMintageTable struct {
+ Standard []dbx.MSYearRow
+ Commemorative []CountryCCsPair
+}
+
+func makeCountryMintageTable(data dbx.CountryMintageData, p i18n.Printer) CountryMintageTable {
+ ccdata := data.Commemorative
+ ccs := make([]YearCCsPair, 0, len(ccdata))
+
+ for len(ccdata) > 0 {
+ x := ccdata[0]
+ i := len(ccdata)
+ for j, y := range ccdata[1:] {
+ if x.Year != y.Year || x.Mintmark != y.Mintmark {
+ i = j + 1
+ break
+ }
+ }
+ ccs = append(ccs, YearCCsPair{
+ Year: x.Year,
+ Mintmark: x.Mintmark,
+ CCs: ccdata[:i],
+ })
+ ccdata = ccdata[i:]
+ }
+
+ return CountryMintageTable{data.Standard, ccs}
+}
+
+func makeYearMintageTable(data dbx.YearMintageData, p i18n.Printer) YearMintageTable {
+ ccdata := data.Commemorative
+ ccs := make([]CountryCCsPair, 0, len(ccdata))
+
+ for len(ccdata) > 0 {
+ x := ccdata[0]
+ i := len(ccdata)
+ for j, y := range ccdata[1:] {
+ if x.Country != y.Country || x.Mintmark != y.Mintmark {
+ i = j + 1
+ break
+ }
+ }
+ ccs = append(ccs, CountryCCsPair{
+ Country: x.Country,
+ Mintmark: x.Mintmark,
+ CCs: ccdata[:i],
+ })
+ ccdata = ccdata[i:]
+ }
+
+ /* NOTE: It’s safe to use MustParse() here, because by this
+ point we know that all BCPs are valid. */
+ c := collate.New(language.MustParse(p.Bcp))
+ for i, r := range data.Standard {
+ name := countryCodeToName[r.Country]
+ data.Standard[i].Country = p.GetC(name, "Place Name")
+ }
+ for i, r := range ccs {
+ name := countryCodeToName[r.Country]
+ ccs[i].Country = p.GetC(name, "Place Name")
+ }
+ slices.SortFunc(data.Standard, func(x, y dbx.MSYearRow) int {
+ Δ := c.CompareString(x.Country, y.Country)
+ if Δ == 0 {
+ Δ = c.CompareString(x.Mintmark.V, y.Mintmark.V)
+ }
+ return Δ
+ })
+ slices.SortFunc(ccs, func(x, y CountryCCsPair) int {
+ Δ := c.CompareString(x.Country, y.Country)
+ if Δ == 0 {
+ Δ = c.CompareString(x.Mintmark.V, y.Mintmark.V)
+ }
+ return Δ
+ })
+
+ return YearMintageTable{data.Standard, ccs}
+}
diff --git a/src/templates.go b/src/templates.go
index 076f8dc..6a43fcb 100644
--- a/src/templates.go
+++ b/src/templates.go
@@ -10,7 +10,6 @@ import (
. "git.thomasvoss.com/euro-cash.eu/pkg/try"
"git.thomasvoss.com/euro-cash.eu/pkg/watch"
- "git.thomasvoss.com/euro-cash.eu/src/dbx"
"git.thomasvoss.com/euro-cash.eu/src/i18n"
)
@@ -20,8 +19,8 @@ type templateData struct {
Printers map[string]i18n.Printer
Code, Type, FilterBy string
Year int
- CountryMintages dbx.CountryMintageData
- YearMintages dbx.YearMintageData
+ CountryMintages CountryMintageTable
+ YearMintages YearMintageTable
Countries []country
}
@@ -30,6 +29,7 @@ var (
errorTmpl *template.Template
templates map[string]*template.Template
funcmap = map[string]any{
+ "evenp": evenp,
"ifElse": ifElse,
"locales": i18n.Locales,
"map": templateMakeMap,
@@ -132,6 +132,10 @@ func templateMakeMap(args ...any) map[string]any {
return m
}
+func evenp(n int) bool {
+ return n&1 == 0
+}
+
func ifElse(b bool, x, y any) any {
if b {
return x
diff --git a/src/templates/-base.html.tmpl b/src/templates/-base.html.tmpl
index f455a14..2e78a7c 100644
--- a/src/templates/-base.html.tmpl
+++ b/src/templates/-base.html.tmpl
@@ -14,22 +14,32 @@
const $$ = q => document.querySelectorAll(q);
(() => {
- const validate = theme =>
- ["light", "dark"].includes(theme) ? theme : "light";
- const toggle = theme =>
- theme == "light" ? "dark" : "light";
+ document.addEventListener("DOMContentLoaded", _ => {
+ const root = $("html");
+ const icons = {
+ light: $("#nav-icon-theme-light"),
+ dark: $("#nav-icon-theme-dark"),
+ };
- const setTheme = theme => {
- localStorage.setItem("theme", theme);
- $("html").setAttribute("data-theme", theme);
- $(`#nav-icon-theme-${theme}`).style.display = "";
- $(`#nav-icon-theme-${toggle(theme)}`).style.display = "none";
- };
+ const toggle = theme =>
+ theme === "light" ? "dark" : "light"
- document.addEventListener("DOMContentLoaded", _ => {
- $("#theme-button").onclick = () =>
- setTheme(toggle(validate(localStorage.getItem("theme"))));
- setTheme(validate(localStorage.getItem("theme")));
+ const setTheme = theme => {
+ localStorage.setItem("theme", theme);
+ root.setAttribute("data-theme", theme);
+ icons[theme].style.display = "";
+ icons[toggle(theme)].style.display = "none";
+ };
+
+ /* Double toggle to handle invalid theme */
+ setTheme(toggle(toggle(localStorage.getItem("theme"))));
+ $("#theme-button").onclick = () => {
+ const theme = toggle(localStorage.getItem("theme"));
+ if (document.startViewTransition)
+ document.startViewTransition(() => setTheme(theme));
+ else
+ setTheme(theme);
+ };
});
})();
</script>
diff --git a/src/templates/coins-mintages.html.tmpl b/src/templates/coins-mintages.html.tmpl
index 7c041f3..e5fa5f1 100644
--- a/src/templates/coins-mintages.html.tmpl
+++ b/src/templates/coins-mintages.html.tmpl
@@ -9,6 +9,10 @@
position: sticky;
left: 0;
}
+
+ .striped :is(th, td) {
+ background-color: var(--pico-table-row-stripped-background-color);
+ }
}
label[for="country-dd"] { display: none; }
@@ -99,11 +103,12 @@
</div>
<button type="submit">{{ .GetC "Filter" "Header/Label" }}</button>
</form>
+
+ {{ if and (eq .FilterBy "country")
+ (gt (len .CountryMintages.Standard) 0) }}
<figure>
<figcaption>{{ .Get "Standard Issue Coins" }}</figcaption>
<div class="overflow-auto">
- {{ if eq .FilterBy "country" }}
-
<table class="mintage-table striped" role="grid">
<thead>
<th>{{ .GetC "Year" "Header/Label" }}</th>
@@ -122,8 +127,8 @@
<tr>
<th scope="row">
{{- .Year -}}
- {{- if ne .Mintmark "" -}}
- &nbsp;<sub><small>{{ .Mintmark }}</small></sub>
+ {{- if .Mintmark.Valid -}}
+ &nbsp;<sub><small>{{ .Mintmark.V }}</small></sub>
{{- end -}}
</th>
{{ range .Mintages }}
@@ -133,9 +138,15 @@
{{ end }}
</tbody>
</table>
+ </div>
+ </figure>
- {{ else if eq .FilterBy "year" }}
+ {{ else if and (eq .FilterBy "year")
+ (gt (len .YearMintages.Standard) 0) }}
+ <figure>
+ <figcaption>{{ .Get "Standard Issue Coins" }}</figcaption>
+ <div class="overflow-auto">
<table class="mintage-table striped" role="grid">
<thead>
<th>{{ .GetC "Country" "Header/Label" }}</th>
@@ -154,8 +165,8 @@
<tr>
<th scope="row">
{{- .Country -}}
- {{- if ne .Mintmark "" -}}
- &nbsp;<sub><small>{{ .Mintmark }}</small></sub>
+ {{- if .Mintmark.Valid -}}
+ &nbsp;<sub><small>{{ .Mintmark.V }}</small></sub>
{{- end -}}
</th>
{{ range .Mintages }}
@@ -165,15 +176,15 @@
{{ end }}
</tbody>
</table>
- {{ end }}
</div>
</figure>
+ {{ end }}
{{ if eq .FilterBy "country" }}
{{ if ne (len .CountryMintages.Commemorative) 0 }}
<figure>
<figcaption>{{ .Get "Commemorative Coins" }}</figcaption>
- <table class="mintage-table striped" role="grid">
+ <table class="mintage-table" role="grid">
<thead>
<th>{{ .GetC "Year" "Header/Label" }}</th>
<th>{{ .GetC "Commemorated Topic" "Header/Label" }}</th>
@@ -181,21 +192,25 @@
</thead>
<tbody>
{{ $p := .Printer }}
- {{ range .CountryMintages.Commemorative }}
- <tr>
- <th scope="row">
- {{- .Year -}}
- {{- if ne .Mintmark "" -}}
- &nbsp;<sub><small>{{ .Mintmark }}</small></sub>
+ {{ range $i, $ := .CountryMintages.Commemorative }}
+ {{ $y := .Year }}
+ {{ $mm := .Mintmark }}
+ {{ $ccs := .CCs }}
+ {{ range $j, $cc := .CCs }}
+ <tr {{ if evenp $i }}class="striped"{{ end }}>
+ {{ if eq $j 0 }}
+ <th scope="row" rowspan="{{ len $ccs }}">
+ {{- $y -}}
+ {{- if $mm.Valid -}}
+ &nbsp;<sub><small>{{ $mm.V }}</small></sub>
{{- end -}}
</th>
- <!-- TODO: Translate commemorative names -->
- <td>{{ .Name }}</td>
- {{ with .Mintage }}
- {{ template "mintages/mintage-cell" (tuple . $p) }}
{{ end }}
+ <td>{{ $p.GetC .Name "CC Name" }}</td>
+ {{ template "mintages/mintage-cell" (tuple .Mintage $p) }}
</tr>
{{ end }}
+ {{ end }}
</tbody>
</table>
</figure>
@@ -206,7 +221,7 @@
{{ if ne (len .YearMintages.Commemorative) 0 }}
<figure>
<figcaption>{{ .Get "Commemorative Coins" }}</figcaption>
- <table class="mintage-table striped" role="grid">
+ <table class="mintage-table" role="grid">
<thead>
<th>{{ .GetC "Country" "Header/Label" }}</th>
<th>{{ .GetC "Commemorated Topic" "Header/Label" }}</th>
@@ -214,21 +229,25 @@
</thead>
<tbody>
{{ $p := .Printer }}
- {{ range .YearMintages.Commemorative }}
- <tr>
- <th scope="row">
- {{- .Country -}}
- {{- if ne .Mintmark "" -}}
- &nbsp;<sub><small>{{ .Mintmark }}</small></sub>
+ {{ range $i, $ := .YearMintages.Commemorative }}
+ {{ $c := .Country }}
+ {{ $mm := .Mintmark }}
+ {{ $ccs := .CCs }}
+ {{ range $j, $cc := .CCs }}
+ <tr {{ if evenp $i }}class="striped"{{ end }}>
+ {{ if eq $j 0 }}
+ <th scope="row" rowspan="{{ len $ccs }}">
+ {{- $c -}}
+ {{- if $mm.Valid -}}
+ &nbsp;<sub><small>{{ $mm.V }}</small></sub>
{{- end -}}
</th>
- <!-- TODO: Translate commemorative names -->
- <td>{{ .Name }}</td>
- {{ with .Mintage }}
- {{ template "mintages/mintage-cell" (tuple . $p) }}
{{ end }}
+ <td>{{ $p.GetC .Name "CC Name" }}</td>
+ {{ template "mintages/mintage-cell" (tuple .Mintage $p) }}
</tr>
{{ end }}
+ {{ end }}
</tbody>
</table>
</figure>
@@ -271,13 +290,11 @@
{{ define "mintages/mintage-cell" }}
{{ $v := index . 0 }}
{{ $p := index . 1 }}
-{{ if eq $v -1 }}
- <td data-numeric>{{ $p.Get "Unknown" }}</td>
-{{ else if eq $v -2 }}
- <td data-numeric class="error">{{ $p.Get "Error" }}</td>
-{{ else if eq $v 0 }}
+{{ if not $v.Valid }}
+ <td data-numeric>{{ $p.GetC "Unknown" "Header/Label" }}</td>
+{{ else if eq $v.V 0 }}
<td data-numeric>—</td>
{{ else }}
- <td data-numeric>{{ $p.Itoa $v }}</td>
-{{ end }}
+ <td data-numeric>{{ $p.Itoa $v.V }}</td>
{{ end }}
+{{ end }} \ No newline at end of file