Compare commits
No commits in common. "1d7be51f414896d7e6334b3ed4a8d97907e5b255" and "76a3c446da405e091260f618c08784c5b9e5c60d" have entirely different histories.
1d7be51f41
...
76a3c446da
|
@ -229,7 +229,6 @@ section#results a, section#results button {
|
||||||
color: #000;
|
color: #000;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
dialog {
|
dialog {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
|
|
|
@ -1,34 +1,14 @@
|
||||||
CREATE TABLE IF NOT EXISTS "country"
|
|
||||||
(
|
|
||||||
id uuid,
|
|
||||||
iso_name char(2) UNIQUE NOT NULL,
|
|
||||||
name varchar(45) NOT NULL,
|
|
||||||
|
|
||||||
primary key (id)
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS "holiday"
|
CREATE TABLE IF NOT EXISTS "holiday"
|
||||||
(
|
(
|
||||||
id uuid,
|
id uuid,
|
||||||
country char(2) NOT NULL,
|
country char(2),
|
||||||
date date NOT NULL,
|
date date,
|
||||||
name varchar(64) NOT NULL,
|
name varchar(64),
|
||||||
description varchar(512),
|
description varchar(512),
|
||||||
is_state boolean NOT NULL,
|
is_state boolean,
|
||||||
is_religious boolean NOT NULL,
|
is_religious boolean
|
||||||
|
|
||||||
primary key (id),
|
|
||||||
constraint fk_country_id foreign key (country)
|
|
||||||
references country(iso_name) on delete cascade on update cascade
|
|
||||||
);
|
);
|
||||||
|
|
||||||
INSERT INTO "country" (id, iso_name, name)
|
|
||||||
VALUES
|
|
||||||
('096ca6c4-5c04-47a4-0063-4b4cc6f6b671', 'HR', 'Croatia'),
|
|
||||||
('096ca6c4-5c04-47a4-0063-4b4cc6f6b672', 'US', 'USA'),
|
|
||||||
('096ca6c4-5c04-47a4-0063-4b4cc6f6b673', 'FR', 'France'),
|
|
||||||
('096ca6c4-5c04-47a4-0063-4b4cc6f6b674', 'GB', 'Great Britain');
|
|
||||||
|
|
||||||
INSERT INTO "holiday" (id, country, date, name, description, is_state, is_religious)
|
INSERT INTO "holiday" (id, country, date, name, description, is_state, is_religious)
|
||||||
VALUES
|
VALUES
|
||||||
('096ca6c4-5c04-47a4-b363-4b4cc6f6b671', 'HR', '2023-01-01', 'Nova godina', '', true, false),
|
('096ca6c4-5c04-47a4-b363-4b4cc6f6b671', 'HR', '2023-01-01', 'Nova godina', '', true, false),
|
||||||
|
|
|
@ -10,7 +10,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func getHolidays(service holiday.HolidayService) gin.HandlerFunc {
|
func getHolidays(service holiday.Service) gin.HandlerFunc {
|
||||||
return func(c *gin.Context) {
|
return func(c *gin.Context) {
|
||||||
paging := holiday.Paging{PageSize: 50}
|
paging := holiday.Paging{PageSize: 50}
|
||||||
if err := c.ShouldBindQuery(&paging); err != nil {
|
if err := c.ShouldBindQuery(&paging); err != nil {
|
||||||
|
|
|
@ -1,40 +0,0 @@
|
||||||
package holiday
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/google/uuid"
|
|
||||||
"github.com/jmoiron/sqlx"
|
|
||||||
)
|
|
||||||
|
|
||||||
type CountryService struct {
|
|
||||||
DB *sqlx.DB
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *CountryService) FindById(id uuid.UUID) (Country, error) {
|
|
||||||
var country Country
|
|
||||||
return country, s.DB.Get(&country, `SELECT * FROM "country" WHERE "id" = $1;`, id)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *CountryService) Find() ([]Country, error) {
|
|
||||||
var countries []Country
|
|
||||||
return countries, s.DB.Select(&countries, `SELECT * FROM "country";`)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *CountryService) Update(country Country) (Country, error) {
|
|
||||||
_, err := s.DB.Exec(`UPDATE country SET "iso_name" = $2, "name" = $3 WHERE "id" = $1`,
|
|
||||||
&country.Id, &country.IsoName, &country.Name,
|
|
||||||
)
|
|
||||||
return country, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *CountryService) Create(country Country) (Country, error) {
|
|
||||||
country.Id = uuid.Must(uuid.NewRandom())
|
|
||||||
_, err := s.DB.Exec(`INSERT INTO country (id, iso_name, name) values ($1, $2, $3)`,
|
|
||||||
&country.Id, &country.IsoName, &country.Name,
|
|
||||||
)
|
|
||||||
return country, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *CountryService) Delete(id uuid.UUID) error {
|
|
||||||
_, err := s.DB.Exec(`DELETE FROM country WHERE "id" = $1`, &id)
|
|
||||||
return err
|
|
||||||
}
|
|
|
@ -15,12 +15,6 @@ type Holiday struct {
|
||||||
IsReligiousHoliday bool `db:"is_religious"`
|
IsReligiousHoliday bool `db:"is_religious"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Country struct {
|
|
||||||
Id uuid.UUID `db:"id"`
|
|
||||||
IsoName string `db:"iso_name"`
|
|
||||||
Name string `db:"name"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Paging struct {
|
type Paging struct {
|
||||||
PageSize int `form:"page_size" binging:"min=0"`
|
PageSize int `form:"page_size" binging:"min=0"`
|
||||||
Page int `form:"page" binging:"min=0"`
|
Page int `form:"page" binging:"min=0"`
|
||||||
|
|
|
@ -8,11 +8,11 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type HolidayService struct {
|
type Service struct {
|
||||||
DB *sqlx.DB
|
DB *sqlx.DB
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *HolidayService) Find(search Search, paging Paging) ([]Holiday, error) {
|
func (s *Service) Find(search Search, paging Paging) ([]Holiday, error) {
|
||||||
var holidays []Holiday
|
var holidays []Holiday
|
||||||
var err error
|
var err error
|
||||||
if search.Date != nil {
|
if search.Date != nil {
|
||||||
|
@ -30,32 +30,32 @@ func (s *HolidayService) Find(search Search, paging Paging) ([]Holiday, error) {
|
||||||
return s.paginate(holidays, paging), err
|
return s.paginate(holidays, paging), err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *HolidayService) FindById(id uuid.UUID) (Holiday, error) {
|
func (s *Service) FindById(id uuid.UUID) (Holiday, error) {
|
||||||
var holiday Holiday
|
var holiday Holiday
|
||||||
return holiday, s.DB.Get(&holiday, `SELECT * FROM "holiday" WHERE "id" = $1;`, id)
|
return holiday, s.DB.Get(&holiday, `SELECT * FROM "holiday" WHERE "id" = $1;`, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *HolidayService) findByDate(date time.Time, isState *bool, isReligious *bool, country string) ([]Holiday, error) {
|
func (s *Service) findByDate(date time.Time, isState *bool, isReligious *bool, country string) ([]Holiday, error) {
|
||||||
var holidays []Holiday
|
var holidays []Holiday
|
||||||
return holidays, s.DB.Select(&holidays, `SELECT * FROM "holiday" WHERE "date" = $1 AND country = $2 `+s.filter(isState, isReligious)+";", date, country)
|
return holidays, s.DB.Select(&holidays, `SELECT * FROM "holiday" WHERE "date" = $1 AND country = $2 `+s.filter(isState, isReligious)+";", date, country)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *HolidayService) findForRange(rangeStart time.Time, rangeEnd time.Time, isState *bool, isReligious *bool, country string) ([]Holiday, error) {
|
func (s *Service) findForRange(rangeStart time.Time, rangeEnd time.Time, isState *bool, isReligious *bool, country string) ([]Holiday, error) {
|
||||||
var holidays []Holiday
|
var holidays []Holiday
|
||||||
return holidays, s.DB.Select(&holidays, `SELECT * FROM "holiday" WHERE "date" BETWEEN $1 AND $2 AND country = $3`+s.filter(isState, isReligious)+";", rangeStart, rangeEnd, country)
|
return holidays, s.DB.Select(&holidays, `SELECT * FROM "holiday" WHERE "date" BETWEEN $1 AND $2 AND country = $3`+s.filter(isState, isReligious)+";", rangeStart, rangeEnd, country)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *HolidayService) findByYear(year int, isState *bool, isReligious *bool, country string) ([]Holiday, error) {
|
func (s *Service) findByYear(year int, isState *bool, isReligious *bool, country string) ([]Holiday, error) {
|
||||||
var holidays []Holiday
|
var holidays []Holiday
|
||||||
return holidays, s.DB.Select(&holidays, `SELECT * FROM "holiday" WHERE extract(year from "date") = $1 AND country = $2 `+s.filter(isState, isReligious)+";", year, country)
|
return holidays, s.DB.Select(&holidays, `SELECT * FROM "holiday" WHERE extract(year from "date") = $1 AND country = $2 `+s.filter(isState, isReligious)+";", year, country)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *HolidayService) find(isState *bool, isReligious *bool, country string) ([]Holiday, error) {
|
func (s *Service) find(isState *bool, isReligious *bool, country string) ([]Holiday, error) {
|
||||||
var holidays []Holiday
|
var holidays []Holiday
|
||||||
return holidays, s.DB.Select(&holidays, `SELECT * FROM "holiday" WHERE country = $1 `+s.filter(isState, isReligious)+";", country)
|
return holidays, s.DB.Select(&holidays, `SELECT * FROM "holiday" WHERE country = $1 `+s.filter(isState, isReligious)+";", country)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *HolidayService) paginate(holidays []Holiday, paging Paging) []Holiday {
|
func (s *Service) paginate(holidays []Holiday, paging Paging) []Holiday {
|
||||||
start := paging.Page * paging.PageSize
|
start := paging.Page * paging.PageSize
|
||||||
end := (paging.Page + 1) * paging.PageSize
|
end := (paging.Page + 1) * paging.PageSize
|
||||||
if end < len(holidays) {
|
if end < len(holidays) {
|
||||||
|
@ -67,7 +67,7 @@ func (s *HolidayService) paginate(holidays []Holiday, paging Paging) []Holiday {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *HolidayService) filter(isState *bool, isReligious *bool) string {
|
func (s *Service) filter(isState *bool, isReligious *bool) string {
|
||||||
var filters []string
|
var filters []string
|
||||||
if isState != nil {
|
if isState != nil {
|
||||||
filters = append(filters, "is_state = "+strconv.FormatBool(*isState))
|
filters = append(filters, "is_state = "+strconv.FormatBool(*isState))
|
||||||
|
@ -82,14 +82,14 @@ func (s *HolidayService) filter(isState *bool, isReligious *bool) string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *HolidayService) Update(holiday Holiday) (Holiday, error) {
|
func (s *Service) Update(holiday Holiday) (Holiday, error) {
|
||||||
_, err := s.DB.Exec(`UPDATE holiday SET "country" = $1, "name" = $2, "description" = $3, "date" = $4, "is_state"=$5, "is_religious"=$6 WHERE "id" = $7`,
|
_, err := s.DB.Exec(`UPDATE holiday SET "country" = $1, "name" = $2, "description" = $3, "date" = $4, "is_state"=$5, "is_religious"=$6 WHERE "id" = $7`,
|
||||||
&holiday.Country, &holiday.Name, &holiday.Description, &holiday.Date, &holiday.IsStateHoliday, &holiday.IsReligiousHoliday, &holiday.Id,
|
&holiday.Country, &holiday.Name, &holiday.Description, &holiday.Date, &holiday.IsStateHoliday, &holiday.IsReligiousHoliday, &holiday.Id,
|
||||||
)
|
)
|
||||||
return holiday, err
|
return holiday, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *HolidayService) Create(holiday Holiday) (Holiday, error) {
|
func (s *Service) Create(holiday Holiday) (Holiday, error) {
|
||||||
holiday.Id = uuid.Must(uuid.NewRandom())
|
holiday.Id = uuid.Must(uuid.NewRandom())
|
||||||
_, err := s.DB.Exec(`INSERT INTO holiday (id, country, name, description, date, is_state, is_religious) values ($1, $2, $3, $4, $5, $6, $7)`,
|
_, err := s.DB.Exec(`INSERT INTO holiday (id, country, name, description, date, is_state, is_religious) values ($1, $2, $3, $4, $5, $6, $7)`,
|
||||||
&holiday.Id, &holiday.Country, &holiday.Name, &holiday.Description, &holiday.Date, &holiday.IsStateHoliday, &holiday.IsReligiousHoliday,
|
&holiday.Id, &holiday.Country, &holiday.Name, &holiday.Description, &holiday.Date, &holiday.IsStateHoliday, &holiday.IsReligiousHoliday,
|
||||||
|
@ -97,7 +97,7 @@ func (s *HolidayService) Create(holiday Holiday) (Holiday, error) {
|
||||||
return holiday, err
|
return holiday, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *HolidayService) Delete(id uuid.UUID) error {
|
func (s *Service) Delete(id uuid.UUID) error {
|
||||||
_, err := s.DB.Exec(`DELETE FROM holiday WHERE "id" = $1`, &id)
|
_, err := s.DB.Exec(`DELETE FROM holiday WHERE "id" = $1`, &id)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
|
@ -1,14 +0,0 @@
|
||||||
package holiday
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/jmoiron/sqlx"
|
|
||||||
)
|
|
||||||
|
|
||||||
type YearService struct {
|
|
||||||
DB *sqlx.DB
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *YearService) Find() ([]int, error) {
|
|
||||||
var years []int
|
|
||||||
return years, s.DB.Select(&years, "SELECT distinct extract(year from date) as date FROM holiday order by date asc")
|
|
||||||
}
|
|
106
main.go
106
main.go
|
@ -53,13 +53,11 @@ func main() {
|
||||||
|
|
||||||
loadTemplates(g)
|
loadTemplates(g)
|
||||||
|
|
||||||
holidayService := holiday.HolidayService{DB: client}
|
holidayService := holiday.Service{DB: client}
|
||||||
countryService := holiday.CountryService{DB: client}
|
|
||||||
yearService := holiday.YearService{DB: client}
|
|
||||||
|
|
||||||
g.GET("/api/v1/holidays", getHolidays(holidayService))
|
g.GET("/api/v1/holidays", getHolidays(holidayService))
|
||||||
|
|
||||||
setupAdminDashboard(g.Group("/admin"), holidayService, countryService, yearService)
|
setupAdminDashboard(g.Group("/admin"), holidayService)
|
||||||
|
|
||||||
g.GET("/", func(c *gin.Context) {
|
g.GET("/", func(c *gin.Context) {
|
||||||
year := time.Now().Year()
|
year := time.Now().Year()
|
||||||
|
@ -69,14 +67,10 @@ func main() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
holidays, _ := holidayService.Find(search, holiday.Paging{PageSize: 100})
|
holidays, _ := holidayService.Find(search, holiday.Paging{PageSize: 100})
|
||||||
countries, _ := countryService.Find()
|
c.HTML(http.StatusOK, "index.gohtml", gin.H{"Search": search, "Holidays": mapHolidays(holidays).Holidays})
|
||||||
years, _ := yearService.Find()
|
|
||||||
c.HTML(http.StatusOK, "index.gohtml", gin.H{"Years": years, "Countries": countries, "Search": search, "Holidays": mapHolidays(holidays).Holidays})
|
|
||||||
})
|
})
|
||||||
g.GET("/documentation", func(c *gin.Context) {
|
g.GET("/documentation", func(c *gin.Context) {
|
||||||
countries, _ := countryService.Find()
|
c.HTML(http.StatusOK, "documentation.gohtml", nil)
|
||||||
years, _ := yearService.Find()
|
|
||||||
c.HTML(http.StatusOK, "documentation.gohtml", gin.H{"Years": years, "Countries": countries})
|
|
||||||
})
|
})
|
||||||
g.GET("/search", func(c *gin.Context) {
|
g.GET("/search", func(c *gin.Context) {
|
||||||
request := holiday.Search{}
|
request := holiday.Search{}
|
||||||
|
@ -86,12 +80,10 @@ func main() {
|
||||||
}
|
}
|
||||||
search := holiday.Search{Country: request.Country, Date: request.Date}
|
search := holiday.Search{Country: request.Country, Date: request.Date}
|
||||||
holidays, _ := holidayService.Find(search, holiday.Paging{PageSize: 100})
|
holidays, _ := holidayService.Find(search, holiday.Paging{PageSize: 100})
|
||||||
countries, _ := countryService.Find()
|
c.HTML(http.StatusOK, "search.gohtml", gin.H{"Search": search, "Holidays": mapHolidays(holidays).Holidays})
|
||||||
c.HTML(http.StatusOK, "search.gohtml", gin.H{"Countries": countries, "Search": search, "Holidays": mapHolidays(holidays).Holidays})
|
|
||||||
})
|
})
|
||||||
g.GET("/dialogs/check-is-a-holiday", func(c *gin.Context) {
|
g.GET("/dialogs/check-is-a-holiday", func(c *gin.Context) {
|
||||||
countries, _ := countryService.Find()
|
c.HTML(http.StatusOK, "check-is-a-holiday.gohtml", gin.H{})
|
||||||
c.HTML(http.StatusOK, "check-is-a-holiday.gohtml", gin.H{"Countries": countries})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
log.Fatal(http.ListenAndServe(":5281", g))
|
log.Fatal(http.ListenAndServe(":5281", g))
|
||||||
|
@ -120,19 +112,15 @@ func loadTemplates(g *gin.Engine) {
|
||||||
"templates/documentation.gohtml",
|
"templates/documentation.gohtml",
|
||||||
|
|
||||||
"templates/admin_dashboard.gohtml",
|
"templates/admin_dashboard.gohtml",
|
||||||
"templates/countries.gohtml",
|
|
||||||
|
|
||||||
"templates/dialogs/add-holiday.gohtml",
|
"templates/dialogs/add-holiday.gohtml",
|
||||||
"templates/dialogs/edit-holiday.gohtml",
|
"templates/dialogs/edit-holiday.gohtml",
|
||||||
"templates/dialogs/delete-holiday.gohtml",
|
"templates/dialogs/delete-holiday.gohtml",
|
||||||
"templates/dialogs/check-is-a-holiday.gohtml",
|
"templates/dialogs/check-is-a-holiday.gohtml",
|
||||||
|
|
||||||
"templates/dialogs/edit-country.gohtml",
|
|
||||||
"templates/dialogs/delete-country.gohtml",
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupAdminDashboard(adminDashboard *gin.RouterGroup, service holiday.HolidayService, countryService holiday.CountryService, yearService holiday.YearService) {
|
func setupAdminDashboard(adminDashboard *gin.RouterGroup, service holiday.Service) {
|
||||||
adminDashboard.Use(gin.BasicAuth(loadAuth()))
|
adminDashboard.Use(gin.BasicAuth(loadAuth()))
|
||||||
|
|
||||||
adminDashboard.GET("/", func(c *gin.Context) {
|
adminDashboard.GET("/", func(c *gin.Context) {
|
||||||
|
@ -144,17 +132,14 @@ func setupAdminDashboard(adminDashboard *gin.RouterGroup, service holiday.Holida
|
||||||
}
|
}
|
||||||
holidays, _ := service.Find(search, holiday.Paging{PageSize: 100})
|
holidays, _ := service.Find(search, holiday.Paging{PageSize: 100})
|
||||||
holidayResponse := mapHolidays(holidays)
|
holidayResponse := mapHolidays(holidays)
|
||||||
countries, _ := countryService.Find()
|
|
||||||
years, _ := yearService.Find()
|
|
||||||
|
|
||||||
response := map[string]any{}
|
response := map[string]any{}
|
||||||
response["Holidays"] = holidayResponse
|
response["holidays"] = holidayResponse
|
||||||
response["Search"] = search
|
response["search"] = search
|
||||||
response["Countries"] = countries
|
|
||||||
response["Years"] = years
|
|
||||||
|
|
||||||
c.HTML(http.StatusOK, "admin_dashboard.gohtml", response)
|
c.HTML(http.StatusOK, "admin_dashboard.gohtml", response)
|
||||||
})
|
})
|
||||||
|
|
||||||
adminDashboard.POST("/holidays", func(c *gin.Context) {
|
adminDashboard.POST("/holidays", func(c *gin.Context) {
|
||||||
request := struct {
|
request := struct {
|
||||||
Id *string `form:"id"`
|
Id *string `form:"id"`
|
||||||
|
@ -205,56 +190,8 @@ func setupAdminDashboard(adminDashboard *gin.RouterGroup, service holiday.Holida
|
||||||
}
|
}
|
||||||
c.Redirect(http.StatusSeeOther, "/admin?country="+hol.Country+"&year="+strconv.FormatInt(int64(hol.Date.Year()), 10))
|
c.Redirect(http.StatusSeeOther, "/admin?country="+hol.Country+"&year="+strconv.FormatInt(int64(hol.Date.Year()), 10))
|
||||||
})
|
})
|
||||||
adminDashboard.GET("/countries", func(c *gin.Context) {
|
|
||||||
countries, _ := countryService.Find()
|
|
||||||
c.HTML(http.StatusOK, "countries.gohtml", gin.H{"Countries": countries})
|
|
||||||
})
|
|
||||||
adminDashboard.POST("/countries", func(c *gin.Context) {
|
|
||||||
request := struct {
|
|
||||||
Id *string `form:"id"`
|
|
||||||
IsoName string `form:"iso_name" binding:"required,min=2,max=2"`
|
|
||||||
Name string `form:"name" binding:"required,min=1,max=45"`
|
|
||||||
}{}
|
|
||||||
if err := c.ShouldBind(&request); err != nil {
|
|
||||||
c.AbortWithError(http.StatusBadRequest, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
country := holiday.Country{
|
|
||||||
IsoName: request.IsoName,
|
|
||||||
Name: request.Name,
|
|
||||||
}
|
|
||||||
|
|
||||||
var err error
|
|
||||||
if request.Id != nil {
|
|
||||||
country.Id = uuid.MustParse(*request.Id)
|
|
||||||
country, err = countryService.Update(country)
|
|
||||||
} else {
|
|
||||||
country, err = countryService.Create(country)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
c.AbortWithError(http.StatusInternalServerError, err)
|
|
||||||
} else {
|
|
||||||
c.Redirect(http.StatusSeeOther, "/admin/countries")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
adminDashboard.POST("/countries/:id/delete", func(c *gin.Context) {
|
|
||||||
id := uuid.MustParse(c.Param("id"))
|
|
||||||
_, err := countryService.FindById(id)
|
|
||||||
if err != nil {
|
|
||||||
c.AbortWithError(http.StatusNotFound, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if err := countryService.Delete(id); err != nil {
|
|
||||||
c.AbortWithError(http.StatusInternalServerError, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.Redirect(http.StatusSeeOther, "/admin/countries")
|
|
||||||
})
|
|
||||||
|
|
||||||
adminDashboard.GET("/dialogs/add-holiday", func(c *gin.Context) {
|
adminDashboard.GET("/dialogs/add-holiday", func(c *gin.Context) {
|
||||||
countries, _ := countryService.Find()
|
c.HTML(http.StatusOK, "add-holiday.gohtml", gin.H{})
|
||||||
c.HTML(http.StatusOK, "add-holiday.gohtml", gin.H{"Countries": countries})
|
|
||||||
})
|
})
|
||||||
adminDashboard.GET("/dialogs/edit-holiday", func(c *gin.Context) {
|
adminDashboard.GET("/dialogs/edit-holiday", func(c *gin.Context) {
|
||||||
id := uuid.MustParse(c.Query("id"))
|
id := uuid.MustParse(c.Query("id"))
|
||||||
|
@ -263,17 +200,7 @@ func setupAdminDashboard(adminDashboard *gin.RouterGroup, service holiday.Holida
|
||||||
c.AbortWithError(http.StatusNotFound, err)
|
c.AbortWithError(http.StatusNotFound, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
countries, _ := countryService.Find()
|
c.HTML(http.StatusOK, "edit-holiday.gohtml", gin.H{"Holiday": hol})
|
||||||
c.HTML(http.StatusOK, "edit-holiday.gohtml", gin.H{"Countries": countries, "Holiday": hol})
|
|
||||||
})
|
|
||||||
adminDashboard.GET("/dialogs/edit-country", func(c *gin.Context) {
|
|
||||||
id := uuid.MustParse(c.Query("id"))
|
|
||||||
country, err := countryService.FindById(id)
|
|
||||||
if err != nil {
|
|
||||||
c.AbortWithError(http.StatusNotFound, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.HTML(http.StatusOK, "edit-country.gohtml", gin.H{"Country": country})
|
|
||||||
})
|
})
|
||||||
adminDashboard.GET("/dialogs/delete-holiday", func(c *gin.Context) {
|
adminDashboard.GET("/dialogs/delete-holiday", func(c *gin.Context) {
|
||||||
id := uuid.MustParse(c.Query("id"))
|
id := uuid.MustParse(c.Query("id"))
|
||||||
|
@ -284,15 +211,6 @@ func setupAdminDashboard(adminDashboard *gin.RouterGroup, service holiday.Holida
|
||||||
}
|
}
|
||||||
c.HTML(http.StatusOK, "delete-holiday.gohtml", gin.H{"Holiday": hol})
|
c.HTML(http.StatusOK, "delete-holiday.gohtml", gin.H{"Holiday": hol})
|
||||||
})
|
})
|
||||||
adminDashboard.GET("/dialogs/delete-country", func(c *gin.Context) {
|
|
||||||
id := uuid.MustParse(c.Query("id"))
|
|
||||||
country, err := countryService.FindById(id)
|
|
||||||
if err != nil {
|
|
||||||
c.AbortWithError(http.StatusNotFound, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.HTML(http.StatusOK, "delete-country.gohtml", gin.H{"Country": country})
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadAuth() map[string]string {
|
func loadAuth() map[string]string {
|
||||||
|
|
2
makefile
2
makefile
|
@ -1,7 +1,7 @@
|
||||||
# scripts for building app
|
# scripts for building app
|
||||||
# requires go 1.19+ and git installed
|
# requires go 1.19+ and git installed
|
||||||
|
|
||||||
VERSION := 0.2.1
|
VERSION := 0.1.0
|
||||||
|
|
||||||
serve:
|
serve:
|
||||||
go run ./...
|
go run ./...
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
<nav>
|
<nav>
|
||||||
<section class="container">
|
<section class="container">
|
||||||
<a class="selected" href="#">Search</a>
|
<a class="selected" href="#">Search</a>
|
||||||
<a href="/admin/countries">Countries</a>
|
|
||||||
<button data-type="dialog" data-trigger="#create-card" data-url="/admin/dialogs/add-holiday">Add new holiday</button>
|
<button data-type="dialog" data-trigger="#create-card" data-url="/admin/dialogs/add-holiday">Add new holiday</button>
|
||||||
</section>
|
</section>
|
||||||
</nav>
|
</nav>
|
||||||
|
@ -28,17 +27,23 @@
|
||||||
<section>
|
<section>
|
||||||
<label for="country">Country:</label>
|
<label for="country">Country:</label>
|
||||||
<select id="country" name="country">
|
<select id="country" name="country">
|
||||||
{{range $entry := .Countries}}
|
<option value="HR" {{if eq .search.Country "HR"}}selected{{end}}>Croatia</option>
|
||||||
<option {{if eq $.Search.Country $entry.IsoName}}selected{{end}} value="{{$entry.IsoName}}">{{$entry.Name}}</option>
|
<option value="GB" {{if eq .search.Country "GB"}}selected{{end}}>Great Britain</option>
|
||||||
{{end}}
|
<option value="US" {{if eq .search.Country "US"}}selected{{end}}>USA</option>
|
||||||
|
<option value="FR" {{if eq .search.Country "FR"}}selected{{end}}>France</option>
|
||||||
</select>
|
</select>
|
||||||
</section>
|
</section>
|
||||||
<section>
|
<section>
|
||||||
<label for="year">Year:</label>
|
<label for="year">Year:</label>
|
||||||
<select id="year" name="year">
|
<select id="year" name="year">
|
||||||
{{range $entry := .Years}}
|
<option value="2020" {{if eq (deferint .search.Year) 2020}}selected{{end}}>2020</option>
|
||||||
<option {{if intpeq $.Search.Year $entry}}selected{{end}} value="{{$entry}}">{{$entry}}</option>
|
<option value="2021" {{if eq (deferint .search.Year) 2021}}selected{{end}}>2021</option>
|
||||||
{{end}}
|
<option value="2022" {{if eq (deferint .search.Year) 2022}}selected{{end}}>2022</option>
|
||||||
|
<option value="2023" {{if eq (deferint .search.Year) 2023}}selected{{end}}>2023</option>
|
||||||
|
<option value="2024" {{if eq (deferint .search.Year) 2024}}selected{{end}}>2024</option>
|
||||||
|
<option value="2025" {{if eq (deferint .search.Year) 2025}}selected{{end}}>2025</option>
|
||||||
|
<option value="2026" {{if eq (deferint .search.Year) 2026}}selected{{end}}>2026</option>
|
||||||
|
<option value="2027" {{if eq (deferint .search.Year) 2027}}selected{{end}}>2027</option>
|
||||||
</select>
|
</select>
|
||||||
</section>
|
</section>
|
||||||
<section class="radio-group">
|
<section class="radio-group">
|
||||||
|
@ -48,7 +53,7 @@
|
||||||
</label><input type="radio" value="false" name="sh" id="sh_false"><label for="sh_false">False
|
</label><input type="radio" value="false" name="sh" id="sh_false"><label for="sh_false">False
|
||||||
</label><input type="radio" value="" name="sh" id="sh_any"><label for="sh_any">All</label>
|
</label><input type="radio" value="" name="sh" id="sh_any"><label for="sh_any">All</label>
|
||||||
</div>
|
</div>
|
||||||
<input type="hidden" value="{{.Search.StateHoliday}}" name="state_holiday">
|
<input type="hidden" value="{{.search.StateHoliday}}" name="state_holiday">
|
||||||
</section>
|
</section>
|
||||||
<section class="radio-group">
|
<section class="radio-group">
|
||||||
<label>Is religious holiday:</label>
|
<label>Is religious holiday:</label>
|
||||||
|
@ -57,7 +62,7 @@
|
||||||
</label><input type="radio" value="false" name="rh" id="rh_false"><label for="rh_false">False
|
</label><input type="radio" value="false" name="rh" id="rh_false"><label for="rh_false">False
|
||||||
</label><input type="radio" value="" name="rh" id="rh_any"><label for="rh_any">All</label>
|
</label><input type="radio" value="" name="rh" id="rh_any"><label for="rh_any">All</label>
|
||||||
</div>
|
</div>
|
||||||
<input type="hidden" value="{{.Search.ReligiousHoliday}}" name="religious_holiday">
|
<input type="hidden" value="{{.search.ReligiousHoliday}}" name="religious_holiday">
|
||||||
</section>
|
</section>
|
||||||
<section class="actions">
|
<section class="actions">
|
||||||
<button class="icon primary" type="submit">
|
<button class="icon primary" type="submit">
|
||||||
|
@ -81,7 +86,7 @@
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
|
||||||
{{range $entry := .Holidays.Holidays}}
|
{{range $entry := .holidays.Holidays}}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{$entry.Name}}</td>
|
<td>{{$entry.Name}}</td>
|
||||||
<td>{{$entry.Date.Format "2006-01-02"}}</td>
|
<td>{{$entry.Date.Format "2006-01-02"}}</td>
|
||||||
|
|
|
@ -1,60 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title>Holiday-api | Admin dashboard</title>
|
|
||||||
<link rel="stylesheet" href="/assets/style.css">
|
|
||||||
<script src="/assets/global.js"></script>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="dialog-container"></div>
|
|
||||||
<header>
|
|
||||||
<section class="container">
|
|
||||||
<h1><a href="/">Holiday-api | Countries</a></h1>
|
|
||||||
</section>
|
|
||||||
</header>
|
|
||||||
<nav>
|
|
||||||
<section class="container">
|
|
||||||
<a href="/admin">Search</a>
|
|
||||||
<a class="selected" href="#">Countries</a>
|
|
||||||
<button data-type="dialog" data-trigger="#create-card" data-url="/admin/dialogs/add-holiday">Add new holiday</button>
|
|
||||||
</section>
|
|
||||||
</nav>
|
|
||||||
<main>
|
|
||||||
|
|
||||||
<section style="margin: 1em; flex-grow: 1">
|
|
||||||
<form action="/admin/countries" method="post">
|
|
||||||
<table style="width: 100%">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Iso name</th>
|
|
||||||
<th>Name</th>
|
|
||||||
<th></th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><section><input minlength="2" maxlength="2" required id="iso_name" type="text" name="iso_name"></section></td>
|
|
||||||
<td><section><input minlength="1" maxlength="45" required id="name" type="text" name="name"></section></td>
|
|
||||||
<td><button>Create country</button></td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
{{range $entry := .Countries}}
|
|
||||||
<tr>
|
|
||||||
<td>{{$entry.IsoName}}</td>
|
|
||||||
<td>{{$entry.Name}}</td>
|
|
||||||
<td>
|
|
||||||
<button type="button" data-type="dialog" data-trigger="#update-card" data-url="/admin/dialogs/edit-country?id={{$entry.Id}}" class="clean icon"><img class="icon" src="/assets/images/edit.svg"></button>
|
|
||||||
<button type="button" data-type="dialog" data-trigger="#delete-card" data-url="/admin/dialogs/delete-country?id={{$entry.Id}}" class="clean icon"><img class="icon" src="/assets/images/trash-delete.svg"></button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{{end}}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</form>
|
|
||||||
</section>
|
|
||||||
</main>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -4,9 +4,10 @@
|
||||||
<section>
|
<section>
|
||||||
<label for="country">Country:</label>
|
<label for="country">Country:</label>
|
||||||
<select id="country" required name="country">
|
<select id="country" required name="country">
|
||||||
{{range $entry := .Countries}}
|
<option value="HR">Croatia</option>
|
||||||
<option value="{{$entry.IsoName}}">{{$entry.Name}}</option>
|
<option value="US">United states</option>
|
||||||
{{end}}
|
<option value="FR">France</option>
|
||||||
|
<option value="GB">Great Britain</option>
|
||||||
</select>
|
</select>
|
||||||
</section>
|
</section>
|
||||||
<section>
|
<section>
|
||||||
|
|
|
@ -7,9 +7,10 @@
|
||||||
<section>
|
<section>
|
||||||
<label for="country">Country:</label>
|
<label for="country">Country:</label>
|
||||||
<select id="country" name="country">
|
<select id="country" name="country">
|
||||||
{{range $entry := .Countries}}
|
<option value="HR">Croatia</option>
|
||||||
<option value="{{$entry.IsoName}}">{{$entry.Name}}</option>
|
<option value="US">United states</option>
|
||||||
{{end}}
|
<option value="FR">France</option>
|
||||||
|
<option value="GB">Great Britain</option>
|
||||||
</select>
|
</select>
|
||||||
</section>
|
</section>
|
||||||
<section>
|
<section>
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
|
|
||||||
<dialog class="card" id="delete-card">
|
|
||||||
<h3 class="card-title">Delete country</h3>
|
|
||||||
<p>Are you sure you want to delete "{{.Country.Name}}"?<br>All holidays for given country will be deleted!</p>
|
|
||||||
<form method="post" action="/admin/countries/{{.Country.Id}}/delete">
|
|
||||||
<section class="actions">
|
|
||||||
<button type="submit">Delete</button>
|
|
||||||
<button type="button" onclick="closeDialog('#delete-card')">Cancel</button>
|
|
||||||
</section>
|
|
||||||
</form>
|
|
||||||
</dialog>
|
|
|
@ -1,18 +0,0 @@
|
||||||
<dialog class="card" id="update-card">
|
|
||||||
<h3 class="card-title">Edit country</h3>
|
|
||||||
<form method="post" action="/admin/countries">
|
|
||||||
<input type="hidden" name="id" value="{{.Country.Id}}">
|
|
||||||
<section>
|
|
||||||
<label for="name">Iso name:</label>
|
|
||||||
<input required minlength="2" maxlength="2" id="iso_name" value="{{.Country.IsoName}}" name="iso_name" type="text">
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<label for="name">Name:</label>
|
|
||||||
<input required minlength="1" maxlength="45" id="name" value="{{.Country.Name}}" name="name" type="text">
|
|
||||||
</section>
|
|
||||||
<section class="actions">
|
|
||||||
<button type="submit">Update</button>
|
|
||||||
<button type="button" onclick="closeDialog('#update-card')">Cancel</button>
|
|
||||||
</section>
|
|
||||||
</form>
|
|
||||||
</dialog>
|
|
|
@ -5,9 +5,10 @@
|
||||||
<section>
|
<section>
|
||||||
<label for="country">Country:</label>
|
<label for="country">Country:</label>
|
||||||
<select id="country" required name="country">
|
<select id="country" required name="country">
|
||||||
{{range $entry := .Countries}}
|
<option {{if eq .Holiday.Country "HR"}}selected{{end}} value="HR">Croatia</option>
|
||||||
<option {{if eq $.Holiday.Country $entry.IsoName}}selected{{end}} value="{{$entry.IsoName}}">{{$entry.Name}}</option>
|
<option {{if eq .Holiday.Country "US"}}selected{{end}} value="US">United states</option>
|
||||||
{{end}}
|
<option {{if eq .Holiday.Country "FR"}}selected{{end}} value="FR">France</option>
|
||||||
|
<option {{if eq .Holiday.Country "GB"}}selected{{end}} value="GB">Great Britain</option>
|
||||||
</select>
|
</select>
|
||||||
</section>
|
</section>
|
||||||
<section>
|
<section>
|
||||||
|
|
|
@ -29,9 +29,10 @@
|
||||||
<section>
|
<section>
|
||||||
<label for="country">Country</label>
|
<label for="country">Country</label>
|
||||||
<select id="country" name="country">
|
<select id="country" name="country">
|
||||||
{{range $entry := .Countries}}
|
<option value="HR">Croatia</option>
|
||||||
<option value="{{$entry.IsoName}}">{{$entry.Name}}</option>
|
<option value="GB">Great Britain</option>
|
||||||
{{end}}
|
<option value="US">USA</option>
|
||||||
|
<option value="FR">France</option>
|
||||||
</select>
|
</select>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
@ -61,9 +62,14 @@
|
||||||
<section>
|
<section>
|
||||||
<label for="dsy-year">Year</label>
|
<label for="dsy-year">Year</label>
|
||||||
<select id="dsy-year" name="year">
|
<select id="dsy-year" name="year">
|
||||||
{{range $entry := .Years}}
|
<option value="2020">2020</option>
|
||||||
<option value="{{$entry}}">{{$entry}}</option>
|
<option value="2021">2021</option>
|
||||||
{{end}}
|
<option value="2022">2022</option>
|
||||||
|
<option value="2023">2023</option>
|
||||||
|
<option value="2024">2024</option>
|
||||||
|
<option value="2025">2025</option>
|
||||||
|
<option value="2026">2026</option>
|
||||||
|
<option value="2027">2027</option>
|
||||||
</select>
|
</select>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -28,17 +28,19 @@
|
||||||
<section>
|
<section>
|
||||||
<label for="country">Country:</label>
|
<label for="country">Country:</label>
|
||||||
<select id="country" name="country">
|
<select id="country" name="country">
|
||||||
{{range $entry := .Countries}}
|
<option {{if eq .Search.Country "HR"}}selected{{end}} value="HR">Croatia</option>
|
||||||
<option {{if eq $.Search.Country $entry.IsoName}}selected{{end}} value="{{$entry.IsoName}}">{{$entry.Name}}</option>
|
<option {{if eq .Search.Country "US"}}selected{{end}} value="US">United states</option>
|
||||||
{{end}}
|
<option {{if eq .Search.Country "FR"}}selected{{end}} value="FR">France</option>
|
||||||
|
<option {{if eq .Search.Country "GB"}}selected{{end}} value="GB">Great Britain</option>
|
||||||
</select>
|
</select>
|
||||||
</section>
|
</section>
|
||||||
<section>
|
<section>
|
||||||
<label for="year">Year:</label>
|
<label for="year">Year:</label>
|
||||||
<select id="year" name="year">
|
<select id="year" name="year">
|
||||||
{{range $entry := .Years}}
|
<option {{if intpeq .Search.Year 2020}}selected{{end}} value="2020">2020</option>
|
||||||
<option {{if intpeq $.Search.Year $entry}}selected{{end}} value="{{$entry}}">{{$entry}}</option>
|
<option {{if intpeq .Search.Year 2021}}selected{{end}} value="2021">2021</option>
|
||||||
{{end}}
|
<option {{if intpeq .Search.Year 2022}}selected{{end}} value="2022">2022</option>
|
||||||
|
<option {{if intpeq .Search.Year 2023}}selected{{end}} value="2023">2023</option>
|
||||||
</select>
|
</select>
|
||||||
</section>
|
</section>
|
||||||
<section class="radio-group">
|
<section class="radio-group">
|
||||||
|
|
|
@ -29,9 +29,10 @@
|
||||||
<section>
|
<section>
|
||||||
<label for="country">Country:</label>
|
<label for="country">Country:</label>
|
||||||
<select id="country" name="country">
|
<select id="country" name="country">
|
||||||
{{range $entry := .Countries}}
|
<option {{if eq .Search.Country "HR"}}selected{{end}} value="HR">Croatia</option>
|
||||||
<option {{if eq $.Search.Country $entry.IsoName}}selected{{end}} value="{{$entry.IsoName}}">{{$entry.Name}}</option>
|
<option {{if eq .Search.Country "US"}}selected{{end}} value="US">United states</option>
|
||||||
{{end}}
|
<option {{if eq .Search.Country "FR"}}selected{{end}} value="FR">France</option>
|
||||||
|
<option {{if eq .Search.Country "GB"}}selected{{end}} value="GB">Great Britain</option>
|
||||||
</select>
|
</select>
|
||||||
</section>
|
</section>
|
||||||
<section>
|
<section>
|
||||||
|
|
Loading…
Reference in New Issue