diff options
| -rw-r--r-- | src/dbx/mintages.go | 8 | ||||
| -rw-r--r-- | src/dbx/sql/last.sql | 15 | ||||
| -rw-r--r-- | src/http.go | 49 | ||||
| -rw-r--r-- | src/tables.go | 108 | ||||
| -rw-r--r-- | src/templates.go | 10 | ||||
| -rw-r--r-- | src/templates/coins-mintages.html.tmpl | 49 | 
6 files changed, 180 insertions, 59 deletions
| diff --git a/src/dbx/mintages.go b/src/dbx/mintages.go index c612a92..2223eff 100644 --- a/src/dbx/mintages.go +++ b/src/dbx/mintages.go @@ -100,8 +100,8 @@ func GetMintagesByYear(year int, typ MintageType) (YearMintageData, error) {  	loop:  		msr := MSYearRow{ -			Country:    x.Country, -			Mintmark:   x.Mintmark, +			Country:  x.Country, +			Mintmark: x.Mintmark,  		}  		i := denomToIdx(x.Denomination)  		msr.Mintages[i] = x.Mintage @@ -164,8 +164,8 @@ func GetMintagesByCountry(country string, typ MintageType) (CountryMintageData,  	loop:  		msr := MSCountryRow{ -			Year:       x.Year, -			Mintmark:   x.Mintmark, +			Year:     x.Year, +			Mintmark: x.Mintmark,  		}  		i := denomToIdx(x.Denomination)  		msr.Mintages[i] = x.Mintage diff --git a/src/dbx/sql/last.sql b/src/dbx/sql/last.sql index 0f70bcc..22ebab8 100644 --- a/src/dbx/sql/last.sql +++ b/src/dbx/sql/last.sql @@ -133,6 +133,21 @@ INSERT INTO mintages_c (  	mintage,  	reference  ) VALUES +	('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), diff --git a/src/http.go b/src/http.go index 241ddcc..fce82ba 100644 --- a/src/http.go +++ b/src/http.go @@ -14,8 +14,6 @@ import (  	"time"  	. "git.thomasvoss.com/euro-cash.eu/pkg/try" -	"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/email" @@ -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 || 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.V, y.Mintmark.V) -				} -				return Δ -			}) -			slices.SortFunc(td.YearMintages.Commemorative, func(x, y dbx.MCommemorative) int { -				Δ := c.CompareString(x.Country, y.Country) -				if Δ == 0 { -					Δ = c.CompareString(x.Mintmark.V, y.Mintmark.V) -				} -				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/coins-mintages.html.tmpl b/src/templates/coins-mintages.html.tmpl index a70a8ea..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; } @@ -180,7 +184,7 @@  		{{ 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> @@ -188,18 +192,25 @@  				</thead>  				<tbody>  					{{ $p := .Printer }} -					{{ range .CountryMintages.Commemorative }} -					<tr> -						<th scope="row"> -							{{- .Year -}} -							{{- if .Mintmark.Valid -}} -							 <sub><small>{{ .Mintmark.V }}</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 -}} +							 <sub><small>{{ $mm.V }}</small></sub>  							{{- end -}}  						</th> +						{{ end }}  						<td>{{ $p.GetC .Name "CC Name" }}</td>  						{{ template "mintages/mintage-cell" (tuple .Mintage $p) }}  					</tr>  					{{ end }} +					{{ end }}  				</tbody>  			</table>  		</figure> @@ -210,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> @@ -218,19 +229,25 @@  				</thead>  				<tbody>  					{{ $p := .Printer }} -					{{ range .YearMintages.Commemorative }} -					<tr> -						<th scope="row"> -							{{- .Country -}} -							{{- if .Mintmark.Valid -}} -							 <sub><small>{{ .Mintmark.V }}</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 -}} +							 <sub><small>{{ $mm.V }}</small></sub>  							{{- end -}}  						</th> -						<!-- TODO: Translate commemorative names --> -						<td>{{ .Name }}</td> +						{{ end }} +						<td>{{ $p.GetC .Name "CC Name" }}</td>  						{{ template "mintages/mintage-cell" (tuple .Mintage $p) }}  					</tr>  					{{ end }} +					{{ end }}  				</tbody>  			</table>  		</figure> |