diff --git a/cmds/server.go b/cmds/server.go index 2445b8a..40c2690 100644 --- a/cmds/server.go +++ b/cmds/server.go @@ -111,6 +111,7 @@ Starting weiro without any arguments will start the server. lh := handlers.LoginHandler{Config: cfg, AuthService: svcs.Auth} ph := handlers.PostsHandler{PostService: svcs.Posts} uh := handlers.UploadsHandler{UploadsService: svcs.Uploads} + ssh := handlers.SiteSettingsHandler{SiteService: svcs.Sites} app.Get("/login", lh.Login) app.Post("/login", lh.DoLogin) @@ -137,6 +138,9 @@ Starting weiro without any arguments will start the server. siteGroup.Post("/uploads/pending/:guid/finalize", uh.UploadComplete) siteGroup.Delete("/uploads/:uploadID", uh.Delete) + siteGroup.Get("/settings", ssh.General) + siteGroup.Post("/settings", ssh.UpdateGeneral) + app.Get("/", middleware.OptionalUser(svcs.Auth), ih.Index) app.Get("/first-run", ih.FirstRun) app.Post("/first-run", ih.FirstRunSubmit) diff --git a/handlers/posts.go b/handlers/posts.go index 283ffd9..3f282e0 100644 --- a/handlers/posts.go +++ b/handlers/posts.go @@ -152,15 +152,3 @@ func (ph PostsHandler) Delete(c fiber.Ctx) error { return c.Redirect().To("/") })) } - -func (ph PostsHandler) Rebuild(c fiber.Ctx) error { - if err := ph.PostService.RebuildSite(c.Context()); err != nil { - return err - } - - return accepts(c, json(func() any { - return fiber.Map{} - }), html(func(c fiber.Ctx) error { - return c.Redirect().To("/") - })) -} diff --git a/handlers/sitesettings.go b/handlers/sitesettings.go new file mode 100644 index 0000000..0fe2100 --- /dev/null +++ b/handlers/sitesettings.go @@ -0,0 +1,52 @@ +package handlers + +import ( + "fmt" + + "github.com/gofiber/fiber/v3" + "lmika.dev/lmika/weiro/models" + "lmika.dev/lmika/weiro/services/sites" +) + +type SiteSettingsHandler struct { + SiteService *sites.Service +} + +func (s *SiteSettingsHandler) General(ctx fiber.Ctx) error { + site := ctx.Locals("site").(models.Site) + + return ctx.Render("sitesettings/general", fiber.Map{ + "site": site, + "tzones": sites.ListZones(), + }) +} + +func (s *SiteSettingsHandler) UpdateGeneral(c fiber.Ctx) error { + site := c.Locals("site").(models.Site) + + var params sites.UpdateSiteSettingsParams + if err := c.Bind().Body(¶ms); err != nil { + return err + } + params.SiteID = site.ID + + if _, err := s.SiteService.UpdateSiteSettings(c.Context(), params); err != nil { + return err + } + + return c.Redirect().To(fmt.Sprintf("/sites/%v/settings", +site.ID)) +} + +func (ph PostsHandler) Rebuild(c fiber.Ctx) error { + site := c.Locals("site").(models.Site) + + if err := ph.PostService.RebuildSite(c.Context()); err != nil { + return err + } + + return accepts(c, json(func() any { + return fiber.Map{} + }), html(func(c fiber.Ctx) error { + return c.Redirect().To(fmt.Sprintf("/sites/%v/settings", +site.ID)) + })) +} diff --git a/models/sites.go b/models/sites.go index 42b8a3c..16cbef4 100644 --- a/models/sites.go +++ b/models/sites.go @@ -27,8 +27,9 @@ type Site struct { GUID string Created time.Time - Title string - Tagline string + Title string + Tagline string + Timezone string } type SitePublishTarget struct { diff --git a/providers/db/gen/sqlgen/models.go b/providers/db/gen/sqlgen/models.go index 1de5ce3..4f69bd0 100644 --- a/providers/db/gen/sqlgen/models.go +++ b/providers/db/gen/sqlgen/models.go @@ -47,6 +47,7 @@ type Site struct { Title string Tagline string CreatedAt int64 + Timezone string } type Upload struct { diff --git a/providers/db/gen/sqlgen/sites.sql.go b/providers/db/gen/sqlgen/sites.sql.go index fd3d3c6..1a1b965 100644 --- a/providers/db/gen/sqlgen/sites.sql.go +++ b/providers/db/gen/sqlgen/sites.sql.go @@ -27,8 +27,9 @@ INSERT INTO sites ( guid, title, tagline, + timezone, created_at -) VALUES (?, ?, ?, ?, ?) +) VALUES (?, ?, ?, ?, ?, ?) RETURNING id ` @@ -37,6 +38,7 @@ type InsertSiteParams struct { Guid string Title string Tagline string + Timezone string CreatedAt int64 } @@ -46,6 +48,7 @@ func (q *Queries) InsertSite(ctx context.Context, arg InsertSiteParams) (int64, arg.Guid, arg.Title, arg.Tagline, + arg.Timezone, arg.CreatedAt, ) var id int64 @@ -98,7 +101,7 @@ func (q *Queries) SelectAllSitesWithOwners(ctx context.Context) ([]SelectAllSite } const selectSiteByGUID = `-- name: SelectSiteByGUID :one -SELECT id, owner_id, guid, title, tagline, created_at FROM sites WHERE guid = ? +SELECT id, owner_id, guid, title, tagline, created_at, timezone FROM sites WHERE guid = ? ` func (q *Queries) SelectSiteByGUID(ctx context.Context, guid string) (Site, error) { @@ -111,12 +114,13 @@ func (q *Queries) SelectSiteByGUID(ctx context.Context, guid string) (Site, erro &i.Title, &i.Tagline, &i.CreatedAt, + &i.Timezone, ) return i, err } const selectSiteByID = `-- name: SelectSiteByID :one -SELECT id, owner_id, guid, title, tagline, created_at FROM sites WHERE id = ? +SELECT id, owner_id, guid, title, tagline, created_at, timezone FROM sites WHERE id = ? ` func (q *Queries) SelectSiteByID(ctx context.Context, id int64) (Site, error) { @@ -129,12 +133,13 @@ func (q *Queries) SelectSiteByID(ctx context.Context, id int64) (Site, error) { &i.Title, &i.Tagline, &i.CreatedAt, + &i.Timezone, ) return i, err } const selectSitesOwnedByUser = `-- name: SelectSitesOwnedByUser :many -SELECT id, owner_id, guid, title, tagline, created_at FROM sites WHERE owner_id = ? ORDER BY title ASC +SELECT id, owner_id, guid, title, tagline, created_at, timezone FROM sites WHERE owner_id = ? ORDER BY title ASC ` func (q *Queries) SelectSitesOwnedByUser(ctx context.Context, ownerID int64) ([]Site, error) { @@ -153,6 +158,7 @@ func (q *Queries) SelectSitesOwnedByUser(ctx context.Context, ownerID int64) ([] &i.Title, &i.Tagline, &i.CreatedAt, + &i.Timezone, ); err != nil { return nil, err } @@ -166,3 +172,24 @@ func (q *Queries) SelectSitesOwnedByUser(ctx context.Context, ownerID int64) ([] } return items, nil } + +const updateSite = `-- name: UpdateSite :exec +UPDATE sites SET title = ?, tagline = ?, timezone = ? WHERE id = ? +` + +type UpdateSiteParams struct { + Title string + Tagline string + Timezone string + ID int64 +} + +func (q *Queries) UpdateSite(ctx context.Context, arg UpdateSiteParams) error { + _, err := q.db.ExecContext(ctx, updateSite, + arg.Title, + arg.Tagline, + arg.Timezone, + arg.ID, + ) + return err +} diff --git a/providers/db/sites.go b/providers/db/sites.go index f878e45..28d83f6 100644 --- a/providers/db/sites.go +++ b/providers/db/sites.go @@ -46,6 +46,7 @@ func (db *Provider) SaveSite(ctx context.Context, site *models.Site) error { Guid: site.GUID, Title: site.Title, Tagline: site.Tagline, + Timezone: site.Timezone, CreatedAt: timeToInt(site.Created), }) if err != nil { @@ -55,8 +56,12 @@ func (db *Provider) SaveSite(ctx context.Context, site *models.Site) error { return nil } - // No update query defined in sqlgen yet - return nil + return db.queries.UpdateSite(ctx, sqlgen.UpdateSiteParams{ + Title: site.Title, + Tagline: site.Tagline, + Timezone: site.Timezone, + ID: site.ID, + }) } func (db *Provider) HasUsersAndSites(ctx context.Context) (bool, error) { @@ -96,11 +101,12 @@ func (db *Provider) SelectAllSitesWithOwners(ctx context.Context) ([]SiteWithOwn func dbSiteToSite(row sqlgen.Site) models.Site { return models.Site{ - ID: row.ID, - OwnerID: row.OwnerID, - GUID: row.Guid, - Title: row.Title, - Tagline: row.Tagline, - Created: time.Unix(row.CreatedAt, 0).UTC(), + ID: row.ID, + OwnerID: row.OwnerID, + GUID: row.Guid, + Title: row.Title, + Timezone: row.Timezone, + Tagline: row.Tagline, + Created: time.Unix(row.CreatedAt, 0).UTC(), } } diff --git a/services/posts/create.go b/services/posts/create.go index 52b9400..f73d49c 100644 --- a/services/posts/create.go +++ b/services/posts/create.go @@ -32,13 +32,20 @@ func (s *Service) UpdatePost(ctx context.Context, params CreatePostParams) (*mod post.Title = params.Title post.Body = params.Body post.UpdatedAt = now - post.Slug = post.BestSlug() oldState := post.State switch strings.ToLower(params.Action) { case "publish": post.State = models.StatePublished - post.PublishedAt = now + + // Set the published at with the site timezone, and reset the slug, so that the date + // is in the site timezone. + renderTZ, err := time.LoadLocation(site.Timezone) + if err != nil { + renderTZ = time.UTC + } + post.PublishedAt = now.In(renderTZ) + post.Slug = post.BestSlug() case "save draft": post.State = models.StateDraft post.PublishedAt = time.Time{} diff --git a/services/publisher/service.go b/services/publisher/service.go index ec9834e..f0b39f0 100644 --- a/services/publisher/service.go +++ b/services/publisher/service.go @@ -6,6 +6,7 @@ import ( "iter" "log" "os" + "time" "emperror.dev/errors" "github.com/go-openapi/runtime" @@ -71,10 +72,16 @@ func (p *Publisher) Publish(ctx context.Context, site models.Site) error { } func (p *Publisher) publishSite(ctx context.Context, pubSite pubmodel.Site, target models.SitePublishTarget) error { + renderTZ, err := time.LoadLocation(pubSite.Timezone) + if err != nil { + renderTZ = time.UTC + } + sb, err := sitebuilder.New(pubSite, sitebuilder.Options{ BasePosts: "/posts", TemplatesFS: simplecss.FS, FeedItems: 30, + RenderTZ: renderTZ, }) if err != nil { return err diff --git a/services/sites/services.go b/services/sites/services.go index 22e3916..06afe15 100644 --- a/services/sites/services.go +++ b/services/sites/services.go @@ -77,10 +77,11 @@ func (s *Service) FirstRun(ctx context.Context, req FirstRunRequest) (newUser mo } newSite = models.Site{ - Title: defaultIfEmpty(req.SiteName, "New Site"), - GUID: models.NewNanoID(), - OwnerID: newUser.ID, - Created: time.Now(), + Title: defaultIfEmpty(req.SiteName, "New Site"), + GUID: models.NewNanoID(), + OwnerID: newUser.ID, + Timezone: "UTC", + Created: time.Now(), } if err := s.db.SaveSite(ctx, &newSite); err != nil { return newUser, newSite, err @@ -126,3 +127,32 @@ func (s *Service) GetSiteByID(ctx context.Context, siteID int64) (models.Site, e func (s *Service) ListAllSitesWithOwners(ctx context.Context) ([]db.SiteWithOwner, error) { return s.db.SelectAllSitesWithOwners(ctx) } + +type UpdateSiteSettingsParams struct { + SiteID int64 `form:"siteID"` + Name string `form:"name"` + Tagline string `form:"tagline"` + Timezone string `form:"timezone"` +} + +func (s *Service) UpdateSiteSettings(ctx context.Context, params UpdateSiteSettingsParams) (models.Site, error) { + site, err := s.GetSiteByID(ctx, params.SiteID) + if err != nil { + return models.Site{}, err + } + + _, err = time.LoadLocation(params.Timezone) + if err != nil { + return models.Site{}, errors.Wrap(err, "invalid timezone") + } + + site.Title = params.Name + site.Tagline = params.Tagline + site.Timezone = params.Timezone + + if err := s.db.SaveSite(ctx, &site); err != nil { + return models.Site{}, err + } + + return site, nil +} diff --git a/services/sites/tzones.go b/services/sites/tzones.go new file mode 100644 index 0000000..a61f208 --- /dev/null +++ b/services/sites/tzones.go @@ -0,0 +1,23 @@ +package sites + +import ( + "embed" + "strings" + "sync" +) + +//go:embed tzones.txt +var tzonesFS embed.FS + +var loadZones = sync.OnceValue(func() []string { + zones, err := tzonesFS.ReadFile("tzones.txt") + if err != nil { + return nil + } + + return strings.Split(string(zones), "\n") +}) + +func ListZones() []string { + return loadZones() +} diff --git a/services/sites/tzones.txt b/services/sites/tzones.txt new file mode 100644 index 0000000..1e65bff --- /dev/null +++ b/services/sites/tzones.txt @@ -0,0 +1,606 @@ +Africa/Abidjan +Africa/Accra +Africa/Addis_Ababa +Africa/Algiers +Africa/Asmara +Africa/Asmera +Africa/Bamako +Africa/Bangui +Africa/Banjul +Africa/Bissau +Africa/Blantyre +Africa/Brazzaville +Africa/Bujumbura +Africa/Cairo +Africa/Casablanca +Africa/Ceuta +Africa/Conakry +Africa/Dakar +Africa/Dar_es_Salaam +Africa/Djibouti +Africa/Douala +Africa/El_Aaiun +Africa/Freetown +Africa/Gaborone +Africa/Harare +Africa/Johannesburg +Africa/Juba +Africa/Kampala +Africa/Khartoum +Africa/Kigali +Africa/Kinshasa +Africa/Lagos +Africa/Libreville +Africa/Lome +Africa/Luanda +Africa/Lubumbashi +Africa/Lusaka +Africa/Malabo +Africa/Maputo +Africa/Maseru +Africa/Mbabane +Africa/Mogadishu +Africa/Monrovia +Africa/Nairobi +Africa/Ndjamena +Africa/Niamey +Africa/Nouakchott +Africa/Ouagadougou +Africa/Porto-Novo +Africa/Sao_Tome +Africa/Timbuktu +Africa/Tripoli +Africa/Tunis +Africa/Windhoek +America/Adak +America/Anchorage +America/Anguilla +America/Antigua +America/Araguaina +America/Argentina/Buenos_Aires +America/Argentina/Catamarca +America/Argentina/ComodRivadavia +America/Argentina/Cordoba +America/Argentina/Jujuy +America/Argentina/La_Rioja +America/Argentina/Mendoza +America/Argentina/Rio_Gallegos +America/Argentina/Salta +America/Argentina/San_Juan +America/Argentina/San_Luis +America/Argentina/Tucuman +America/Argentina/Ushuaia +America/Aruba +America/Asuncion +America/Atikokan +America/Atka +America/Bahia +America/Bahia_Banderas +America/Barbados +America/Belem +America/Belize +America/Blanc-Sablon +America/Boa_Vista +America/Bogota +America/Boise +America/Buenos_Aires +America/Cambridge_Bay +America/Campo_Grande +America/Cancun +America/Caracas +America/Catamarca +America/Cayenne +America/Cayman +America/Chicago +America/Chihuahua +America/Coral_Harbour +America/Cordoba +America/Costa_Rica +America/Creston +America/Cuiaba +America/Curacao +America/Danmarkshavn +America/Dawson +America/Dawson_Creek +America/Denver +America/Detroit +America/Dominica +America/Edmonton +America/Eirunepe +America/El_Salvador +America/Ensenada +America/Fort_Nelson +America/Fort_Wayne +America/Fortaleza +America/Glace_Bay +America/Godthab +America/Goose_Bay +America/Grand_Turk +America/Grenada +America/Guadeloupe +America/Guatemala +America/Guayaquil +America/Guyana +America/Halifax +America/Havana +America/Hermosillo +America/Indiana/Indianapolis +America/Indiana/Knox +America/Indiana/Marengo +America/Indiana/Petersburg +America/Indiana/Tell_City +America/Indiana/Vevay +America/Indiana/Vincennes +America/Indiana/Winamac +America/Indianapolis +America/Inuvik +America/Iqaluit +America/Jamaica +America/Jujuy +America/Juneau +America/Kentucky/Louisville +America/Kentucky/Monticello +America/Knox_IN +America/Kralendijk +America/La_Paz +America/Lima +America/Los_Angeles +America/Louisville +America/Lower_Princes +America/Maceio +America/Managua +America/Manaus +America/Marigot +America/Martinique +America/Matamoros +America/Mazatlan +America/Mendoza +America/Menominee +America/Merida +America/Metlakatla +America/Mexico_City +America/Miquelon +America/Moncton +America/Monterrey +America/Montevideo +America/Montreal +America/Montserrat +America/Nassau +America/New_York +America/Nipigon +America/Nome +America/Noronha +America/North_Dakota/Beulah +America/North_Dakota/Center +America/North_Dakota/New_Salem +America/Ojinaga +America/Panama +America/Pangnirtung +America/Paramaribo +America/Phoenix +America/Port-au-Prince +America/Port_of_Spain +America/Porto_Acre +America/Porto_Velho +America/Puerto_Rico +America/Punta_Arenas +America/Rainy_River +America/Rankin_Inlet +America/Recife +America/Regina +America/Resolute +America/Rio_Branco +America/Rosario +America/Santa_Isabel +America/Santarem +America/Santiago +America/Santo_Domingo +America/Sao_Paulo +America/Scoresbysund +America/Shiprock +America/Sitka +America/St_Barthelemy +America/St_Johns +America/St_Kitts +America/St_Lucia +America/St_Thomas +America/St_Vincent +America/Swift_Current +America/Tegucigalpa +America/Thule +America/Thunder_Bay +America/Tijuana +America/Toronto +America/Tortola +America/Vancouver +America/Virgin +America/Whitehorse +America/Winnipeg +America/Yakutat +America/Yellowknife +Antarctica/Casey +Antarctica/Davis +Antarctica/DumontDUrville +Antarctica/Macquarie +Antarctica/Mawson +Antarctica/McMurdo +Antarctica/Palmer +Antarctica/Rothera +Antarctica/South_Pole +Antarctica/Syowa +Antarctica/Troll +Antarctica/Vostok +Arctic/Longyearbyen +Asia/Aden +Asia/Almaty +Asia/Amman +Asia/Anadyr +Asia/Aqtau +Asia/Aqtobe +Asia/Ashgabat +Asia/Ashkhabad +Asia/Atyrau +Asia/Baghdad +Asia/Bahrain +Asia/Baku +Asia/Bangkok +Asia/Barnaul +Asia/Beirut +Asia/Bishkek +Asia/Brunei +Asia/Calcutta +Asia/Chita +Asia/Choibalsan +Asia/Chongqing +Asia/Chungking +Asia/Colombo +Asia/Dacca +Asia/Damascus +Asia/Dhaka +Asia/Dili +Asia/Dubai +Asia/Dushanbe +Asia/Famagusta +Asia/Gaza +Asia/Harbin +Asia/Hebron +Asia/Ho_Chi_Minh +Asia/Hong_Kong +Asia/Hovd +Asia/Irkutsk +Asia/Istanbul +Asia/Jakarta +Asia/Jayapura +Asia/Jerusalem +Asia/Kabul +Asia/Kamchatka +Asia/Karachi +Asia/Kashgar +Asia/Kathmandu +Asia/Katmandu +Asia/Khandyga +Asia/Kolkata +Asia/Krasnoyarsk +Asia/Kuala_Lumpur +Asia/Kuching +Asia/Kuwait +Asia/Macao +Asia/Macau +Asia/Magadan +Asia/Makassar +Asia/Manila +Asia/Muscat +Asia/Nicosia +Asia/Novokuznetsk +Asia/Novosibirsk +Asia/Omsk +Asia/Oral +Asia/Phnom_Penh +Asia/Pontianak +Asia/Pyongyang +Asia/Qatar +Asia/Qyzylorda +Asia/Rangoon +Asia/Riyadh +Asia/Saigon +Asia/Sakhalin +Asia/Samarkand +Asia/Seoul +Asia/Shanghai +Asia/Singapore +Asia/Srednekolymsk +Asia/Taipei +Asia/Tashkent +Asia/Tbilisi +Asia/Tehran +Asia/Tel_Aviv +Asia/Thimbu +Asia/Thimphu +Asia/Tokyo +Asia/Tomsk +Asia/Ujung_Pandang +Asia/Ulaanbaatar +Asia/Ulan_Bator +Asia/Urumqi +Asia/Ust-Nera +Asia/Vientiane +Asia/Vladivostok +Asia/Yakutsk +Asia/Yangon +Asia/Yekaterinburg +Asia/Yerevan +Atlantic/Azores +Atlantic/Bermuda +Atlantic/Canary +Atlantic/Cape_Verde +Atlantic/Faeroe +Atlantic/Faroe +Atlantic/Jan_Mayen +Atlantic/Madeira +Atlantic/Reykjavik +Atlantic/South_Georgia +Atlantic/St_Helena +Atlantic/Stanley +Australia/ACT +Australia/Adelaide +Australia/Brisbane +Australia/Broken_Hill +Australia/Canberra +Australia/Currie +Australia/Darwin +Australia/Eucla +Australia/Hobart +Australia/LHI +Australia/Lindeman +Australia/Lord_Howe +Australia/Melbourne +Australia/NSW +Australia/North +Australia/Perth +Australia/Queensland +Australia/South +Australia/Sydney +Australia/Tasmania +Australia/Victoria +Australia/West +Australia/Yancowinna +Brazil/Acre +Brazil/DeNoronha +Brazil/East +Brazil/West +CET +CST6CDT +Canada/Atlantic +Canada/Central +Canada/Eastern +Canada/Mountain +Canada/Newfoundland +Canada/Pacific +Canada/Saskatchewan +Canada/Yukon +Chile/Continental +Chile/EasterIsland +Cuba +EET +EST +EST5EDT +Egypt +Eire +Etc/GMT +Etc/GMT+0 +Etc/GMT+1 +Etc/GMT+10 +Etc/GMT+11 +Etc/GMT+12 +Etc/GMT+2 +Etc/GMT+3 +Etc/GMT+4 +Etc/GMT+5 +Etc/GMT+6 +Etc/GMT+7 +Etc/GMT+8 +Etc/GMT+9 +Etc/GMT-0 +Etc/GMT-1 +Etc/GMT-10 +Etc/GMT-11 +Etc/GMT-12 +Etc/GMT-13 +Etc/GMT-14 +Etc/GMT-2 +Etc/GMT-3 +Etc/GMT-4 +Etc/GMT-5 +Etc/GMT-6 +Etc/GMT-7 +Etc/GMT-8 +Etc/GMT-9 +Etc/GMT0 +Etc/Greenwich +Etc/UCT +Etc/UTC +Etc/Universal +Etc/Zulu +Europe/Amsterdam +Europe/Andorra +Europe/Astrakhan +Europe/Athens +Europe/Belfast +Europe/Belgrade +Europe/Berlin +Europe/Bratislava +Europe/Brussels +Europe/Bucharest +Europe/Budapest +Europe/Busingen +Europe/Chisinau +Europe/Copenhagen +Europe/Dublin +Europe/Gibraltar +Europe/Guernsey +Europe/Helsinki +Europe/Isle_of_Man +Europe/Istanbul +Europe/Jersey +Europe/Kaliningrad +Europe/Kiev +Europe/Kirov +Europe/Lisbon +Europe/Ljubljana +Europe/London +Europe/Luxembourg +Europe/Madrid +Europe/Malta +Europe/Mariehamn +Europe/Minsk +Europe/Monaco +Europe/Moscow +Europe/Nicosia +Europe/Oslo +Europe/Paris +Europe/Podgorica +Europe/Prague +Europe/Riga +Europe/Rome +Europe/Samara +Europe/San_Marino +Europe/Sarajevo +Europe/Saratov +Europe/Simferopol +Europe/Skopje +Europe/Sofia +Europe/Stockholm +Europe/Tallinn +Europe/Tirane +Europe/Tiraspol +Europe/Ulyanovsk +Europe/Uzhgorod +Europe/Vaduz +Europe/Vatican +Europe/Vienna +Europe/Vilnius +Europe/Volgograd +Europe/Warsaw +Europe/Zagreb +Europe/Zaporozhye +Europe/Zurich +Factory +GB +GB-Eire +GMT +GMT+0 +GMT-0 +GMT0 +Greenwich +HST +Hongkong +Iceland +Indian/Antananarivo +Indian/Chagos +Indian/Christmas +Indian/Cocos +Indian/Comoro +Indian/Kerguelen +Indian/Mahe +Indian/Maldives +Indian/Mauritius +Indian/Mayotte +Indian/Reunion +Iran +Israel +Jamaica +Japan +Kwajalein +Libya +MET +MST +MST7MDT +Mexico/BajaNorte +Mexico/BajaSur +Mexico/General +NZ +NZ-CHAT +Navajo +PRC +PST8PDT +Pacific/Apia +Pacific/Auckland +Pacific/Bougainville +Pacific/Chatham +Pacific/Chuuk +Pacific/Easter +Pacific/Efate +Pacific/Enderbury +Pacific/Fakaofo +Pacific/Fiji +Pacific/Funafuti +Pacific/Galapagos +Pacific/Gambier +Pacific/Guadalcanal +Pacific/Guam +Pacific/Honolulu +Pacific/Johnston +Pacific/Kiritimati +Pacific/Kosrae +Pacific/Kwajalein +Pacific/Majuro +Pacific/Marquesas +Pacific/Midway +Pacific/Nauru +Pacific/Niue +Pacific/Norfolk +Pacific/Noumea +Pacific/Pago_Pago +Pacific/Palau +Pacific/Pitcairn +Pacific/Pohnpei +Pacific/Ponape +Pacific/Port_Moresby +Pacific/Rarotonga +Pacific/Saipan +Pacific/Samoa +Pacific/Tahiti +Pacific/Tarawa +Pacific/Tongatapu +Pacific/Truk +Pacific/Wake +Pacific/Wallis +Pacific/Yap +Poland +Portugal +ROC +ROK +Singapore +SystemV/AST4 +SystemV/AST4ADT +SystemV/CST6 +SystemV/CST6CDT +SystemV/EST5 +SystemV/EST5EDT +SystemV/HST10 +SystemV/MST7 +SystemV/MST7MDT +SystemV/PST8 +SystemV/PST8PDT +SystemV/YST9 +SystemV/YST9YDT +Turkey +UCT +US/Alaska +US/Aleutian +US/Arizona +US/Central +US/East-Indiana +US/Eastern +US/Hawaii +US/Indiana-Starke +US/Michigan +US/Mountain +US/Pacific +US/Pacific-New +US/Samoa +UTC +Universal +W-SU +WET +Zulu diff --git a/sql/queries/sites.sql b/sql/queries/sites.sql index 92e7ccb..8fe2469 100644 --- a/sql/queries/sites.sql +++ b/sql/queries/sites.sql @@ -13,13 +13,17 @@ INSERT INTO sites ( guid, title, tagline, + timezone, created_at -) VALUES (?, ?, ?, ?, ?) +) VALUES (?, ?, ?, ?, ?, ?) RETURNING id; -- name: HasUsersAndSites :one SELECT (SELECT COUNT(*) FROM users) > 0 AND (SELECT COUNT(*) FROM sites) > 0 AS has_users_and_sites; +-- name: UpdateSite :exec +UPDATE sites SET title = ?, tagline = ?, timezone = ? WHERE id = ?; + -- name: SelectAllSitesWithOwners :many SELECT s.id, s.guid, s.title, s.owner_id, u.username FROM sites s diff --git a/sql/schema/03_add_loc_to_site.up.sql b/sql/schema/03_add_loc_to_site.up.sql new file mode 100644 index 0000000..2798610 --- /dev/null +++ b/sql/schema/03_add_loc_to_site.up.sql @@ -0,0 +1 @@ +ALTER TABLE sites ADD COLUMN timezone TEXT NOT NULL DEFAULT 'UTC'; \ No newline at end of file diff --git a/views/_common/nav.html b/views/_common/nav.html index 7b8bd16..87801d2 100644 --- a/views/_common/nav.html +++ b/views/_common/nav.html @@ -13,6 +13,9 @@