diff --git a/demo/ad.avif b/demo/ad.avif new file mode 100644 index 0000000..8334116 Binary files /dev/null and b/demo/ad.avif differ diff --git a/demo/demo.sql b/demo/demo.sql index d36ad28..651bad8 100644 --- a/demo/demo.sql +++ b/demo/demo.sql @@ -73,6 +73,7 @@ select add_media(52, 'wooden_lodges_carousel9.avif', 'image/avif', decode('m4_es select add_media(52, 'wooden_lodges_carouselA.avif', 'image/avif', decode('m4_esyscmd([[base64 -w0 demo/wooden_lodges_carouselA.avif]])', 'base64')); select add_media(52, 'wooden_lodges_carouselB.avif', 'image/avif', decode('m4_esyscmd([[base64 -w0 demo/wooden_lodges_carouselB.avif]])', 'base64')); select add_media(52, 'wooden_lodges_carouselC.avif', 'image/avif', decode('m4_esyscmd([[base64 -w0 demo/wooden_lodges_carouselC.avif]])', 'base64')); +select add_media(52, 'ad.avif', 'image/avif', decode('m4_esyscmd([[base64 -w0 demo/ad.avif]])', 'base64')); select setup_home(52, 'Vine a gaudir!'); @@ -659,6 +660,11 @@ select translate_surroundings_highlight(120, 'fr', 'Pyrénées', '

Pyrénées select translate_surroundings_highlight(121, 'fr', 'Gérone', '

Visite incontournable, principalement: le quartier juifs, les Rambles, la cathédrale et les jardins qui l’entourent … Sans oublier ses nombreuses boutiques !

Turisme Girona

'); select translate_surroundings_highlight(122, 'fr', 'Barcelone', '

Barcelone c’est plus que des boutiques et le Barça … Découvrez la richesse de ces quartiers: Gràcia, Barceloneta, …

Turisme Barcelona

'); +select setup_surroundings_ad(52, 104, 'Vine a fer barranquisme per Sadernes!', 'Reserva el teu dia', 'https://www.guiesarania.com/ca/activitats/barrancs-de-perfeccionament/barranc-de-sant-aniol/'); +select translate_surroundings_ad(52, 'en', 'Canyoneering in Sadernes!', 'Book your day'); +select translate_surroundings_ad(52, 'es', '¡Ven a hacer barranquismo en Sadernes!', 'Reserva tu día'); +select translate_surroundings_ad(52, 'fr', 'Venez faire du canyoning à Sadernes !', 'Réservez votre journée'); + alter table booking alter column booking_id restart with 122; insert into booking (company_id, campsite_type_id, holder_name, arrival_date, departure_date, number_dogs, acsi_card, booking_status) diff --git a/deploy/remove_surroundings_ad.sql b/deploy/remove_surroundings_ad.sql new file mode 100644 index 0000000..13f4343 --- /dev/null +++ b/deploy/remove_surroundings_ad.sql @@ -0,0 +1,22 @@ +-- Deploy camper:remove_surroundings_ad to pg +-- requires: roles +-- requires: schema_camper +-- requires: surroundings_ad +-- requires: surroundings_ad_i18n + +begin; + +set search_path to camper, public; + +create or replace function remove_surroundings_ad(company_id integer) returns void as +$$ + delete from surroundings_ad_i18n where company_id = remove_surroundings_ad.company_id; + delete from surroundings_ad where company_id = remove_surroundings_ad.company_id; +$$ + language sql +; + +revoke execute on function remove_surroundings_ad(integer) from public; +grant execute on function remove_surroundings_ad(integer) to admin; + +commit; diff --git a/deploy/setup_surroundings_ad.sql b/deploy/setup_surroundings_ad.sql new file mode 100644 index 0000000..b246dc0 --- /dev/null +++ b/deploy/setup_surroundings_ad.sql @@ -0,0 +1,28 @@ +-- Deploy camper:setup_surroundings_ad to pg +-- requires: roles +-- requires: schema_camper +-- requires: surroundings_ad + +begin; + +set search_path to camper, public; + +create or replace function setup_surroundings_ad(company integer, media_id integer, title text, anchor text, href uri) returns void as +$$ + insert into surroundings_ad (company_id, media_id, title, anchor, href) + values (company, media_id, title, anchor, href) + on conflict (company_id) + do update + set media_id = excluded.media_id + , title = excluded.title + , anchor = excluded.anchor + , href = excluded.href + ; +$$ + language sql +; + +revoke execute on function setup_surroundings_ad(integer, integer, text, text, uri) from public; +grant execute on function setup_surroundings_ad(integer, integer, text, text, uri) to admin; + +commit; diff --git a/deploy/surroundings_ad.sql b/deploy/surroundings_ad.sql new file mode 100644 index 0000000..1d06084 --- /dev/null +++ b/deploy/surroundings_ad.sql @@ -0,0 +1,55 @@ +-- Deploy camper:surroundings_ad to pg +-- requires: roles +-- requires: schema_camper +-- requires: company +-- requires: user_profile + +begin; + +set search_path to camper, public; + +create table surroundings_ad ( + company_id integer not null primary key references company, + media_id integer not null references media, + title text not null, + anchor text not null, + href uri not null +); + +grant select on table surroundings_ad to guest; +grant select on table surroundings_ad to employee; +grant select, insert, update, delete on table surroundings_ad to admin; + +alter table surroundings_ad enable row level security; + +create policy guest_ok +on surroundings_ad +for select +using (true) +; + +create policy insert_to_company +on surroundings_ad +for insert +with check ( + company_id in (select company_id from user_profile) +) +; + +create policy update_company +on surroundings_ad +for update +using ( + company_id in (select company_id from user_profile) +) +; + +create policy delete_from_company +on surroundings_ad +for delete +using ( + company_id in (select company_id from user_profile) +) +; + +commit; diff --git a/deploy/surroundings_ad_i18n.sql b/deploy/surroundings_ad_i18n.sql new file mode 100644 index 0000000..6c8cb88 --- /dev/null +++ b/deploy/surroundings_ad_i18n.sql @@ -0,0 +1,23 @@ +-- Deploy camper:surroundings_ad_i18n to pg +-- requires: roles +-- requires: schema_camper +-- requires: surroundings_ad +-- requires: language + +begin; + +set search_path to camper, public; + +create table surroundings_ad_i18n ( + company_id integer not null references surroundings_ad, + lang_tag text not null references language, + title text not null, + anchor text not null, + primary key (company_id, lang_tag) +); + +grant select on table surroundings_ad_i18n to guest; +grant select on table surroundings_ad_i18n to employee; +grant select, insert, update, delete on table surroundings_ad_i18n to admin; + +commit; diff --git a/deploy/translate_surroundings_ad.sql b/deploy/translate_surroundings_ad.sql new file mode 100644 index 0000000..aaf68dd --- /dev/null +++ b/deploy/translate_surroundings_ad.sql @@ -0,0 +1,26 @@ +-- Deploy camper:translate_surroundings_ad to pg +-- requires: roles +-- requires: schema_camper +-- requires: surroundings_ad_i18n + +begin; + +set search_path to camper, public; + +create or replace function translate_surroundings_ad(company_id integer, lang_tag text, title text, anchor text) returns void as +$$ + insert into surroundings_ad_i18n (company_id, lang_tag, title, anchor) + values (company_id, lang_tag, title, anchor) + on conflict (company_id, lang_tag) + do update + set title = excluded.title + , anchor = excluded.anchor + ; +$$ + language sql +; + +revoke execute on function translate_surroundings_ad(integer, text, text, text) from public; +grant execute on function translate_surroundings_ad(integer, text, text, text) to admin; + +commit; diff --git a/pkg/database/funcs.go b/pkg/database/funcs.go index 2ce8f94..66c94d4 100644 --- a/pkg/database/funcs.go +++ b/pkg/database/funcs.go @@ -190,6 +190,21 @@ func (c *Conn) RemoveSurroundingsHighlight(ctx context.Context, id int) error { return err } +func (tx *Tx) SetupSurroundingsAd(ctx context.Context, companyID int, mediaID int, title string, anchor string, href string) error { + _, err := tx.Exec(ctx, "select setup_surroundings_ad($1, $2, $3, $4, $5)", companyID, mediaID, title, anchor, href) + return err +} + +func (tx *Tx) TranslateSurroundingsAd(ctx context.Context, companyID int, langTag language.Tag, title string, anchor string) error { + _, err := tx.Exec(ctx, "select translate_surroundings_ad($1, $2, $3, $4)", companyID, langTag, title, anchor) + return err +} + +func (c *Conn) RemoveSurroundingsAd(ctx context.Context, companyID int) error { + _, err := c.Exec(ctx, "select remove_surroundings_ad($1)", companyID) + return err +} + func (tx *Tx) SetupHome(ctx context.Context, companyID int, slogan string) error { _, err := tx.Exec(ctx, "select setup_home($1, $2)", companyID, slogan) return err diff --git a/pkg/surroundings/admin.go b/pkg/surroundings/admin.go index 14349c5..366d337 100644 --- a/pkg/surroundings/admin.go +++ b/pkg/surroundings/admin.go @@ -57,6 +57,15 @@ func (h *AdminHandler) Handler(user *auth.User, company *auth.Company, conn *dat default: httplib.MethodNotAllowed(w, r, http.MethodPost) } + case "ad": + switch r.Method { + case http.MethodPut: + updateAd(w, r, user, company, conn) + case http.MethodDelete: + removeAd(w, r, company, conn) + default: + httplib.MethodNotAllowed(w, r, http.MethodPut, http.MethodDelete) + } default: id, err := strconv.Atoi(head) if err != nil { @@ -120,17 +129,27 @@ func orderHighlights(w http.ResponseWriter, r *http.Request, user *auth.User, co } func serveHighlightsIndex(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn) { + f := newAdForm(company) + if err := f.FillFromDatabase(r.Context(), company, conn); err != nil && !database.ErrorIsNotFound(err) { + panic(err) + } + serveHighlightsIndexWithForm(w, r, user, company, conn, f) +} + +func serveHighlightsIndexWithForm(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn, f *adForm) { highlights, err := collectHighlightEntries(r.Context(), company, conn) if err != nil { panic(err) } page := &highlightIndex{ + Ad: f, Highlights: highlights, } page.MustRender(w, r, user, company) } type highlightIndex struct { + Ad *adForm Highlights []*highlightEntry } @@ -325,3 +344,127 @@ func (f *highlightForm) Valid(ctx context.Context, conn *database.Conn, l *local func (f *highlightForm) MustRender(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company) { template.MustRenderAdmin(w, r, user, company, "surroundings/form.gohtml", f) } + +func updateAd(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn) { + f := newAdForm(company) + if err := f.Parse(r); err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + if err := user.VerifyCSRFToken(r); err != nil { + http.Error(w, err.Error(), http.StatusForbidden) + return + } + if ok, err := f.Valid(r.Context(), conn, user.Locale); err != nil { + panic(err) + } else if !ok { + if !httplib.IsHTMxRequest(r) { + w.WriteHeader(http.StatusUnprocessableEntity) + } + serveHighlightsIndexWithForm(w, r, user, company, conn, f) + return + } + tx := conn.MustBegin(r.Context()) + defer tx.Rollback(r.Context()) + if err := tx.SetupSurroundingsAd(r.Context(), company.ID, f.Media.Int(), f.Title[f.DefaultLang].Val, f.Anchor[f.DefaultLang].Val, f.HRef.Val); err != nil { + panic(err) + } + for lang := range company.Locales { + l := lang.String() + if l == f.DefaultLang { + continue + } + if err := tx.TranslateSurroundingsAd(r.Context(), company.ID, lang, f.Title[l].Val, f.Anchor[l].Val); err != nil { + panic(err) + } + } + tx.MustCommit(r.Context()) + httplib.Redirect(w, r, "/admin/surroundings", http.StatusSeeOther) +} + +func removeAd(w http.ResponseWriter, r *http.Request, company *auth.Company, conn *database.Conn) { + if err := conn.RemoveSurroundingsAd(r.Context(), company.ID); err != nil { + panic(err) + } + httplib.Redirect(w, r, "/admin/surroundings", http.StatusSeeOther) +} + +type adForm struct { + DefaultLang string + Media *form.Media + Title form.I18nInput + Anchor form.I18nInput + HRef *form.Input +} + +func newAdForm(company *auth.Company) *adForm { + return &adForm{ + DefaultLang: company.DefaultLanguage.String(), + Media: &form.Media{ + Input: &form.Input{ + Name: "media", + }, + Label: locale.PgettextNoop("Ad image", "input"), + Prompt: locale.PgettextNoop("Set ad image", "action"), + }, + Title: form.NewI18nInput(company.Locales, "title"), + Anchor: form.NewI18nInput(company.Locales, "anchor"), + HRef: &form.Input{Name: "href"}, + } +} + +func (f *adForm) FillFromDatabase(ctx context.Context, company *auth.Company, conn *database.Conn) error { + var titles database.RecordArray + var anchors database.RecordArray + err := conn.QueryRow(ctx, ` + select ad.media_id::text + , ad.title + , ad.anchor + , ad.href::text + , array_agg((lang_tag, i18n.title)) + , array_agg((lang_tag, i18n.anchor)) + from surroundings_ad as ad + left join surroundings_ad_i18n as i18n using (company_id) + where company_id = $1 + group by ad.media_id + , ad.title + , ad.anchor + , ad.href +`, pgx.QueryResultFormats{pgx.BinaryFormatCode}, company.ID).Scan(&f.Media.Val, &f.Title[f.DefaultLang].Val, &f.Anchor[f.DefaultLang].Val, &f.HRef.Val, &titles, &anchors) + if err != nil { + return err + } + if err := f.Title.FillArray(titles); err != nil { + return err + } + if err := f.Anchor.FillArray(anchors); err != nil { + return err + } + return nil +} + +func (f *adForm) Parse(r *http.Request) error { + if err := r.ParseForm(); err != nil { + return err + } + f.Media.FillValue(r) + f.Title.FillValue(r) + f.Anchor.FillValue(r) + f.HRef.FillValue(r) + return nil +} + +func (f *adForm) Valid(ctx context.Context, conn *database.Conn, l *locale.Locale) (bool, error) { + v := form.NewValidator(l) + if v.CheckRequired(f.Media.Input, l.GettextNoop("Ad image can not be empty.")) { + if _, err := v.CheckImageMedia(ctx, conn, f.Media.Input, l.GettextNoop("Ad image must be an image media type.")); err != nil { + return false, err + } + } + v.CheckRequired(f.Title[f.DefaultLang], l.GettextNoop("The title can not be empty.")) + v.CheckRequired(f.Anchor[f.DefaultLang], l.GettextNoop("The link text can not be empty.")) + if v.CheckRequired(f.HRef, l.GettextNoop("The ad URL can not be empty")) { + v.CheckValidURL(f.HRef, l.GettextNoop("This web address is not valid. It should be like https://domain.com/.")) + } + return v.AllOK, nil +} diff --git a/pkg/surroundings/public.go b/pkg/surroundings/public.go index 16ff5d2..ceba16d 100644 --- a/pkg/surroundings/public.go +++ b/pkg/surroundings/public.go @@ -45,6 +45,7 @@ func (h *PublicHandler) Handler(user *auth.User, company *auth.Company, conn *da type surroundingsPage struct { *template.PublicPage + Ad *surroundingsAd Highlights []*highlight } @@ -55,6 +56,7 @@ func newSurroundingsPage() *surroundingsPage { func (p *surroundingsPage) MustRender(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn) { p.Setup(r, user, company, conn) p.Highlights = mustCollectSurroundings(r.Context(), company, conn, user.Locale) + p.Ad = mustCollectAd(r.Context(), company, conn, user.Locale) template.MustRenderPublic(w, r, user, company, "surroundings.gohtml", p) } @@ -96,3 +98,31 @@ func mustCollectSurroundings(ctx context.Context, company *auth.Company, conn *d return items } + +type surroundingsAd struct { + MediaURL string + Title string + Anchor string + HRef string +} + +func mustCollectAd(ctx context.Context, company *auth.Company, conn *database.Conn, loc *locale.Locale) *surroundingsAd { + ad := &surroundingsAd{} + err := conn.QueryRow(ctx, ` + select media.path + , coalesce(i18n.title, ad.title) as l10_title + , coalesce(i18n.anchor, ad.anchor) as l10_anchor + , href::text + from surroundings_ad as ad + join media using (media_id) + left join surroundings_ad_i18n as i18n on ad.company_id = i18n.company_id and lang_tag = $1 + where ad.company_id = $2 + `, loc.Language, company.ID).Scan(&ad.MediaURL, &ad.Title, &ad.Anchor, &ad.HRef) + if err != nil { + if database.ErrorIsNotFound(err) { + return nil + } + panic(err) + } + return ad +} diff --git a/po/ca.po b/po/ca.po index 914fe4a..3d77bc4 100644 --- a/po/ca.po +++ b/po/ca.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: camper\n" "Report-Msgid-Bugs-To: jordi@tandem.blog\n" -"POT-Creation-Date: 2024-01-23 11:46+0100\n" +"POT-Creation-Date: 2024-01-23 14:38+0100\n" "PO-Revision-Date: 2023-07-22 23:45+0200\n" "Last-Translator: jordi fita mas \n" "Language-Team: Catalan \n" @@ -241,45 +241,45 @@ msgctxt "day" msgid "Sun" msgstr "dg" -#: web/templates/public/surroundings.gohtml:32 +#: web/templates/public/surroundings.gohtml:30 msgctxt "title" msgid "What to Do Outside the Campsite?" msgstr "Què fer des del càmping?" -#: web/templates/public/surroundings.gohtml:52 +#: web/templates/public/surroundings.gohtml:50 msgctxt "title" msgid "Once at the Campsite, We Can Inform You about What Activities are Available" msgstr "Un cop en el càmping, us podem informar de quines activitats fer" -#: web/templates/public/surroundings.gohtml:55 +#: web/templates/public/surroundings.gohtml:53 msgid "Cycle routes" msgstr "Rutes amb bicicleta" -#: web/templates/public/surroundings.gohtml:56 +#: web/templates/public/surroundings.gohtml:54 msgid "There are many bicycle rental companies in Olot." msgstr "A Olot podeu trobar empreses de lloguer de bicicletes." -#: web/templates/public/surroundings.gohtml:60 +#: web/templates/public/surroundings.gohtml:58 msgid "Routes" msgstr "Rutes" -#: web/templates/public/surroundings.gohtml:61 +#: web/templates/public/surroundings.gohtml:59 msgid "Routes of all kinds, climbing, mountain passes, for all levels." msgstr "Rutes de tota mena, escalada, ports de muntanya, per a tots els nivells." -#: web/templates/public/surroundings.gohtml:65 +#: web/templates/public/surroundings.gohtml:63 msgid "Family outing" msgstr "Excursions familiars" -#: web/templates/public/surroundings.gohtml:66 +#: web/templates/public/surroundings.gohtml:64 msgid "Many outing possibilities, for all ages." msgstr "Múltiples excursions per a totes les edats." -#: web/templates/public/surroundings.gohtml:70 +#: web/templates/public/surroundings.gohtml:68 msgid "Kayak" msgstr "Caiac" -#: web/templates/public/surroundings.gohtml:71 +#: web/templates/public/surroundings.gohtml:69 msgid "There are several points where you can go by kayak, from sections of the Ter river as well as on the coast…." msgstr "Hi ha diversos punts on poder anar amb caiac, des de trams del riu Ter com també a la costa…." @@ -475,6 +475,7 @@ msgstr "Contingut" #: web/templates/admin/season/form.gohtml:73 #: web/templates/admin/services/form.gohtml:80 #: web/templates/admin/surroundings/form.gohtml:69 +#: web/templates/admin/surroundings/index.gohtml:58 #: web/templates/admin/home/index.gohtml:34 #: web/templates/admin/media/form.gohtml:39 msgctxt "action" @@ -506,7 +507,7 @@ msgstr "Afegeix text legal" #: web/templates/admin/campsite/type/index.gohtml:29 #: web/templates/admin/season/index.gohtml:29 #: web/templates/admin/user/index.gohtml:20 -#: web/templates/admin/surroundings/index.gohtml:29 +#: web/templates/admin/surroundings/index.gohtml:83 msgctxt "header" msgid "Name" msgstr "Nom" @@ -636,7 +637,7 @@ msgstr "Afegeix diapositiva" #: web/templates/admin/campsite/carousel/index.gohtml:30 #: web/templates/admin/services/index.gohtml:28 -#: web/templates/admin/surroundings/index.gohtml:28 +#: web/templates/admin/surroundings/index.gohtml:82 #: web/templates/admin/home/index.gohtml:52 #: web/templates/admin/home/index.gohtml:97 msgctxt "header" @@ -656,7 +657,7 @@ msgstr "Llegenda" #: web/templates/admin/services/index.gohtml:30 #: web/templates/admin/services/index.gohtml:75 #: web/templates/admin/user/index.gohtml:23 -#: web/templates/admin/surroundings/index.gohtml:30 +#: web/templates/admin/surroundings/index.gohtml:84 #: web/templates/admin/home/index.gohtml:54 #: web/templates/admin/home/index.gohtml:99 msgctxt "header" @@ -674,7 +675,8 @@ msgstr "Esteu segur de voler esborrar aquesta diapositiva?" #: web/templates/admin/services/index.gohtml:47 #: web/templates/admin/services/index.gohtml:91 #: web/templates/admin/user/index.gohtml:37 -#: web/templates/admin/surroundings/index.gohtml:47 +#: web/templates/admin/surroundings/index.gohtml:63 +#: web/templates/admin/surroundings/index.gohtml:101 #: web/templates/admin/home/index.gohtml:71 #: web/templates/admin/home/index.gohtml:116 msgctxt "action" @@ -1209,19 +1211,43 @@ msgstr "Pàgina de l’entorn" #: web/templates/admin/surroundings/index.gohtml:14 msgctxt "title" +msgid "Ad" +msgstr "Anunci" + +#: web/templates/admin/surroundings/index.gohtml:21 +msgctxt "input" +msgid "Title" +msgstr "Títol" + +#: web/templates/admin/surroundings/index.gohtml:37 +msgctxt "input" +msgid "Link Text" +msgstr "Text de l’enllaç" + +#: web/templates/admin/surroundings/index.gohtml:50 +msgctxt "input" +msgid "Link URL" +msgstr "Adreça de l’enllaç" + +#: web/templates/admin/surroundings/index.gohtml:59 +msgid "Are you sure you wish to delete the ad?" +msgstr "Esteu segur de voler esborrar aquest anunci?" + +#: web/templates/admin/surroundings/index.gohtml:68 +msgctxt "title" msgid "Highlights" msgstr "Punts d’interès" -#: web/templates/admin/surroundings/index.gohtml:15 +#: web/templates/admin/surroundings/index.gohtml:69 msgctxt "action" msgid "Add highlight" msgstr "Afegeix punt d’interès" -#: web/templates/admin/surroundings/index.gohtml:34 +#: web/templates/admin/surroundings/index.gohtml:88 msgid "Are you sure you wish to delete this highlight?" msgstr "Esteu segur de voler esborrar aquest punt d’interès?" -#: web/templates/admin/surroundings/index.gohtml:56 +#: web/templates/admin/surroundings/index.gohtml:110 msgid "No highlights added yet." msgstr "No s’ha afegit cap punt d’interès encara." @@ -1441,7 +1467,7 @@ msgstr "No s’ha trobat cap reserva." #: pkg/legal/admin.go:258 pkg/app/user.go:249 pkg/campsite/types/option.go:357 #: pkg/campsite/types/feature.go:259 pkg/campsite/types/admin.go:483 #: pkg/season/admin.go:412 pkg/services/admin.go:316 -#: pkg/surroundings/admin.go:321 +#: pkg/surroundings/admin.go:340 msgid "Name can not be empty." msgstr "No podeu deixar el nom en blanc." @@ -1461,12 +1487,12 @@ msgid "Set slide image" msgstr "Estableix la imatge de la diapositiva" #: pkg/carousel/admin.go:346 pkg/campsite/types/carousel.go:299 -#: pkg/surroundings/admin.go:316 +#: pkg/surroundings/admin.go:335 msgid "Slide image can not be empty." msgstr "No podeu deixar la imatge de la diapositiva en blanc." #: pkg/carousel/admin.go:347 pkg/campsite/types/carousel.go:300 -#: pkg/surroundings/admin.go:317 +#: pkg/surroundings/admin.go:336 msgid "Slide image must be an image media type." msgstr "La imatge de la diapositiva ha de ser un mèdia de tipus imatge." @@ -1711,16 +1737,50 @@ msgctxt "role" msgid "admin" msgstr "administrador" -#: pkg/surroundings/admin.go:267 +#: pkg/surroundings/admin.go:286 msgctxt "input" msgid "Highlight image" msgstr "Imatge del punt d’interès" -#: pkg/surroundings/admin.go:268 +#: pkg/surroundings/admin.go:287 msgctxt "action" msgid "Set highlight image" msgstr "Estableix la imatge del punt d’interès" +#: pkg/surroundings/admin.go:407 +msgctxt "input" +msgid "Ad image" +msgstr "Imatge de l’anunci" + +#: pkg/surroundings/admin.go:408 +msgctxt "action" +msgid "Set ad image" +msgstr "Estableix la imatge de l’anunci" + +#: pkg/surroundings/admin.go:459 +msgid "Ad image can not be empty." +msgstr "No podeu deixar la imatge de l’anunci en blanc." + +#: pkg/surroundings/admin.go:460 +msgid "Ad image must be an image media type." +msgstr "La imatge de l’anunci ha de ser un mèdia de tipus imatge." + +#: pkg/surroundings/admin.go:464 +msgid "The title can not be empty." +msgstr "No podeu deixar el títol en blanc." + +#: pkg/surroundings/admin.go:465 +msgid "The link text can not be empty." +msgstr "No podeu deixar el text de l’enllaç en blanc." + +#: pkg/surroundings/admin.go:466 +msgid "The ad URL can not be empty" +msgstr "No podeu deixar l’adreça de l’enllaç en blanc." + +#: pkg/surroundings/admin.go:467 pkg/company/admin.go:221 +msgid "This web address is not valid. It should be like https://domain.com/." +msgstr "Aquesta adreça web no és vàlida. Hauria de ser similar a https://domini.com/." + #: pkg/company/admin.go:200 pkg/booking/public.go:256 msgid "Selected country is not valid." msgstr "El país escollit no és vàlid." @@ -1749,10 +1809,6 @@ msgstr "No podeu deixar el telèfon en blanc." msgid "This phone number is not valid." msgstr "Aquest número de telèfon no és vàlid." -#: pkg/company/admin.go:221 -msgid "This web address is not valid. It should be like https://domain.com/." -msgstr "Aquesta adreça web no és vàlida. Hauria de ser similar a https://domini.com/." - #: pkg/company/admin.go:223 msgid "Address can not be empty." msgstr "No podeu deixar l’adreça en blanc." @@ -2057,10 +2113,6 @@ msgstr "El valor de %s ha de ser com a màxim %d." #~ msgid "Legend" #~ msgstr "Llegenda" -#~ msgctxt "input" -#~ msgid "Title" -#~ msgstr "Títol" - #~ msgctxt "title" #~ msgid "Pages" #~ msgstr "Pàgines" diff --git a/po/es.po b/po/es.po index 522d29d..57db608 100644 --- a/po/es.po +++ b/po/es.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: camper\n" "Report-Msgid-Bugs-To: jordi@tandem.blog\n" -"POT-Creation-Date: 2024-01-23 11:46+0100\n" +"POT-Creation-Date: 2024-01-23 14:38+0100\n" "PO-Revision-Date: 2023-07-22 23:46+0200\n" "Last-Translator: jordi fita mas \n" "Language-Team: Spanish \n" @@ -241,45 +241,45 @@ msgctxt "day" msgid "Sun" msgstr "do" -#: web/templates/public/surroundings.gohtml:32 +#: web/templates/public/surroundings.gohtml:30 msgctxt "title" msgid "What to Do Outside the Campsite?" msgstr "¿Qué hacer desde el camping?" -#: web/templates/public/surroundings.gohtml:52 +#: web/templates/public/surroundings.gohtml:50 msgctxt "title" msgid "Once at the Campsite, We Can Inform You about What Activities are Available" msgstr "Una vez en el camping, os podemos informar de qué actividades hacer" -#: web/templates/public/surroundings.gohtml:55 +#: web/templates/public/surroundings.gohtml:53 msgid "Cycle routes" msgstr "Rutas en bicicleta" -#: web/templates/public/surroundings.gohtml:56 +#: web/templates/public/surroundings.gohtml:54 msgid "There are many bicycle rental companies in Olot." msgstr "A Olot podéis encontrar empresas de alquiler de bicicletas." -#: web/templates/public/surroundings.gohtml:60 +#: web/templates/public/surroundings.gohtml:58 msgid "Routes" msgstr "Rutas" -#: web/templates/public/surroundings.gohtml:61 +#: web/templates/public/surroundings.gohtml:59 msgid "Routes of all kinds, climbing, mountain passes, for all levels." msgstr "Rutas de todo tipo, escalada, puertos de montaña, para todos los niveles." -#: web/templates/public/surroundings.gohtml:65 +#: web/templates/public/surroundings.gohtml:63 msgid "Family outing" msgstr "Excusiones familiares" -#: web/templates/public/surroundings.gohtml:66 +#: web/templates/public/surroundings.gohtml:64 msgid "Many outing possibilities, for all ages." msgstr "Múltiples excursiones para todas las edades." -#: web/templates/public/surroundings.gohtml:70 +#: web/templates/public/surroundings.gohtml:68 msgid "Kayak" msgstr "Kayak" -#: web/templates/public/surroundings.gohtml:71 +#: web/templates/public/surroundings.gohtml:69 msgid "There are several points where you can go by kayak, from sections of the Ter river as well as on the coast…." msgstr "Hay diversos puntos dónde podéis ir en kayak, desde tramos del río Ter como también en la costa…." @@ -475,6 +475,7 @@ msgstr "Contenido" #: web/templates/admin/season/form.gohtml:73 #: web/templates/admin/services/form.gohtml:80 #: web/templates/admin/surroundings/form.gohtml:69 +#: web/templates/admin/surroundings/index.gohtml:58 #: web/templates/admin/home/index.gohtml:34 #: web/templates/admin/media/form.gohtml:39 msgctxt "action" @@ -506,7 +507,7 @@ msgstr "Añadir texto legal" #: web/templates/admin/campsite/type/index.gohtml:29 #: web/templates/admin/season/index.gohtml:29 #: web/templates/admin/user/index.gohtml:20 -#: web/templates/admin/surroundings/index.gohtml:29 +#: web/templates/admin/surroundings/index.gohtml:83 msgctxt "header" msgid "Name" msgstr "Nombre" @@ -636,7 +637,7 @@ msgstr "Añadir diapositiva" #: web/templates/admin/campsite/carousel/index.gohtml:30 #: web/templates/admin/services/index.gohtml:28 -#: web/templates/admin/surroundings/index.gohtml:28 +#: web/templates/admin/surroundings/index.gohtml:82 #: web/templates/admin/home/index.gohtml:52 #: web/templates/admin/home/index.gohtml:97 msgctxt "header" @@ -656,7 +657,7 @@ msgstr "Leyenda" #: web/templates/admin/services/index.gohtml:30 #: web/templates/admin/services/index.gohtml:75 #: web/templates/admin/user/index.gohtml:23 -#: web/templates/admin/surroundings/index.gohtml:30 +#: web/templates/admin/surroundings/index.gohtml:84 #: web/templates/admin/home/index.gohtml:54 #: web/templates/admin/home/index.gohtml:99 msgctxt "header" @@ -674,7 +675,8 @@ msgstr "¿Estáis seguro de querer borrar esta diapositiva?" #: web/templates/admin/services/index.gohtml:47 #: web/templates/admin/services/index.gohtml:91 #: web/templates/admin/user/index.gohtml:37 -#: web/templates/admin/surroundings/index.gohtml:47 +#: web/templates/admin/surroundings/index.gohtml:63 +#: web/templates/admin/surroundings/index.gohtml:101 #: web/templates/admin/home/index.gohtml:71 #: web/templates/admin/home/index.gohtml:116 msgctxt "action" @@ -1209,19 +1211,43 @@ msgstr "Página del entorno" #: web/templates/admin/surroundings/index.gohtml:14 msgctxt "title" +msgid "Ad" +msgstr "Anuncio" + +#: web/templates/admin/surroundings/index.gohtml:21 +msgctxt "input" +msgid "Title" +msgstr "Título" + +#: web/templates/admin/surroundings/index.gohtml:37 +msgctxt "input" +msgid "Link Text" +msgstr "Texto del enlace" + +#: web/templates/admin/surroundings/index.gohtml:50 +msgctxt "input" +msgid "Link URL" +msgstr "Dirección del enlace" + +#: web/templates/admin/surroundings/index.gohtml:59 +msgid "Are you sure you wish to delete the ad?" +msgstr "¿Estáis seguro de querer borrar este enlace?" + +#: web/templates/admin/surroundings/index.gohtml:68 +msgctxt "title" msgid "Highlights" msgstr "Puntos de interés" -#: web/templates/admin/surroundings/index.gohtml:15 +#: web/templates/admin/surroundings/index.gohtml:69 msgctxt "action" msgid "Add highlight" msgstr "Añadir punto de interés" -#: web/templates/admin/surroundings/index.gohtml:34 +#: web/templates/admin/surroundings/index.gohtml:88 msgid "Are you sure you wish to delete this highlight?" msgstr "¿Estáis seguro de querer borrar este punto de interés?" -#: web/templates/admin/surroundings/index.gohtml:56 +#: web/templates/admin/surroundings/index.gohtml:110 msgid "No highlights added yet." msgstr "No se ha añadido ningún punto de interés todavía." @@ -1441,7 +1467,7 @@ msgstr "No se ha encontrado ninguna reserva." #: pkg/legal/admin.go:258 pkg/app/user.go:249 pkg/campsite/types/option.go:357 #: pkg/campsite/types/feature.go:259 pkg/campsite/types/admin.go:483 #: pkg/season/admin.go:412 pkg/services/admin.go:316 -#: pkg/surroundings/admin.go:321 +#: pkg/surroundings/admin.go:340 msgid "Name can not be empty." msgstr "No podéis dejar el nombre en blanco." @@ -1461,12 +1487,12 @@ msgid "Set slide image" msgstr "Establecer la imagen de la diapositiva" #: pkg/carousel/admin.go:346 pkg/campsite/types/carousel.go:299 -#: pkg/surroundings/admin.go:316 +#: pkg/surroundings/admin.go:335 msgid "Slide image can not be empty." msgstr "No podéis dejar la imagen de la diapositiva en blanco." #: pkg/carousel/admin.go:347 pkg/campsite/types/carousel.go:300 -#: pkg/surroundings/admin.go:317 +#: pkg/surroundings/admin.go:336 msgid "Slide image must be an image media type." msgstr "La imagen de la diapositiva tiene que ser un medio de tipo imagen." @@ -1711,16 +1737,50 @@ msgctxt "role" msgid "admin" msgstr "administrador" -#: pkg/surroundings/admin.go:267 +#: pkg/surroundings/admin.go:286 msgctxt "input" msgid "Highlight image" msgstr "Imagen del punto de interés" -#: pkg/surroundings/admin.go:268 +#: pkg/surroundings/admin.go:287 msgctxt "action" msgid "Set highlight image" msgstr "Establecer la imagen del punto de interés" +#: pkg/surroundings/admin.go:407 +msgctxt "input" +msgid "Ad image" +msgstr "Imagen del anuncio" + +#: pkg/surroundings/admin.go:408 +msgctxt "action" +msgid "Set ad image" +msgstr "Establecer la imagen del anuncio" + +#: pkg/surroundings/admin.go:459 +msgid "Ad image can not be empty." +msgstr "No podéis dejar la imagen del anuncio en blanco." + +#: pkg/surroundings/admin.go:460 +msgid "Ad image must be an image media type." +msgstr "La imagen del anuncio tiene que ser un medio de tipo imagen." + +#: pkg/surroundings/admin.go:464 +msgid "The title can not be empty." +msgstr "No podéis dejar el título en blanco." + +#: pkg/surroundings/admin.go:465 +msgid "The link text can not be empty." +msgstr "No podéis dejar el texto del enlace en blanco." + +#: pkg/surroundings/admin.go:466 +msgid "The ad URL can not be empty" +msgstr "No podéis dejar la dirección del enlace en blanco." + +#: pkg/surroundings/admin.go:467 pkg/company/admin.go:221 +msgid "This web address is not valid. It should be like https://domain.com/." +msgstr "Esta dirección web no es válida. Tiene que ser parecido a https://dominio.com/." + #: pkg/company/admin.go:200 pkg/booking/public.go:256 msgid "Selected country is not valid." msgstr "El país escogido no es válido." @@ -1749,10 +1809,6 @@ msgstr "No podéis dejar el teléfono en blanco." msgid "This phone number is not valid." msgstr "Este teléfono no es válido." -#: pkg/company/admin.go:221 -msgid "This web address is not valid. It should be like https://domain.com/." -msgstr "Esta dirección web no es válida. Tiene que ser parecido a https://dominio.com/." - #: pkg/company/admin.go:223 msgid "Address can not be empty." msgstr "No podéis dejar la dirección en blanco." @@ -2057,10 +2113,6 @@ msgstr "%s tiene que ser como máximo %d" #~ msgid "Legend" #~ msgstr "Leyenda" -#~ msgctxt "input" -#~ msgid "Title" -#~ msgstr "Título" - #~ msgctxt "title" #~ msgid "Pages" #~ msgstr "Páginas" diff --git a/po/fr.po b/po/fr.po index 8499d72..f1ae6cf 100644 --- a/po/fr.po +++ b/po/fr.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: camper\n" "Report-Msgid-Bugs-To: jordi@tandem.blog\n" -"POT-Creation-Date: 2024-01-23 11:46+0100\n" +"POT-Creation-Date: 2024-01-23 14:38+0100\n" "PO-Revision-Date: 2023-12-20 10:13+0100\n" "Last-Translator: Oriol Carbonell \n" "Language-Team: French \n" @@ -242,45 +242,45 @@ msgctxt "day" msgid "Sun" msgstr "Dim." -#: web/templates/public/surroundings.gohtml:32 +#: web/templates/public/surroundings.gohtml:30 msgctxt "title" msgid "What to Do Outside the Campsite?" msgstr "Que faire à l’extérieur du camping ?" -#: web/templates/public/surroundings.gohtml:52 +#: web/templates/public/surroundings.gohtml:50 msgctxt "title" msgid "Once at the Campsite, We Can Inform You about What Activities are Available" msgstr "Une fois au camping, nous pourrons vous informer sur les activités disponibles" -#: web/templates/public/surroundings.gohtml:55 +#: web/templates/public/surroundings.gohtml:53 msgid "Cycle routes" msgstr "Pistes cyclables" -#: web/templates/public/surroundings.gohtml:56 +#: web/templates/public/surroundings.gohtml:54 msgid "There are many bicycle rental companies in Olot." msgstr "Il existe de nombreuses sociétés de location de vélos à Olot." -#: web/templates/public/surroundings.gohtml:60 +#: web/templates/public/surroundings.gohtml:58 msgid "Routes" msgstr "Itinéraires" -#: web/templates/public/surroundings.gohtml:61 +#: web/templates/public/surroundings.gohtml:59 msgid "Routes of all kinds, climbing, mountain passes, for all levels." msgstr "Itinéraires de toutes sortes, escalade, cols de montagne, pour tous les niveaux." -#: web/templates/public/surroundings.gohtml:65 +#: web/templates/public/surroundings.gohtml:63 msgid "Family outing" msgstr "Sortie en famille" -#: web/templates/public/surroundings.gohtml:66 +#: web/templates/public/surroundings.gohtml:64 msgid "Many outing possibilities, for all ages." msgstr "Nombreuses possibilités de sorties, pour tous les âges." -#: web/templates/public/surroundings.gohtml:70 +#: web/templates/public/surroundings.gohtml:68 msgid "Kayak" msgstr "Kayak" -#: web/templates/public/surroundings.gohtml:71 +#: web/templates/public/surroundings.gohtml:69 msgid "There are several points where you can go by kayak, from sections of the Ter river as well as on the coast…." msgstr "Il y a plusieurs points où vous pouvez aller en kayak, à partir de sections de la rivière Ter ainsi que sur la côte…." @@ -476,6 +476,7 @@ msgstr "Contenu" #: web/templates/admin/season/form.gohtml:73 #: web/templates/admin/services/form.gohtml:80 #: web/templates/admin/surroundings/form.gohtml:69 +#: web/templates/admin/surroundings/index.gohtml:58 #: web/templates/admin/home/index.gohtml:34 #: web/templates/admin/media/form.gohtml:39 msgctxt "action" @@ -507,7 +508,7 @@ msgstr "Ajouter un texte juridique" #: web/templates/admin/campsite/type/index.gohtml:29 #: web/templates/admin/season/index.gohtml:29 #: web/templates/admin/user/index.gohtml:20 -#: web/templates/admin/surroundings/index.gohtml:29 +#: web/templates/admin/surroundings/index.gohtml:83 msgctxt "header" msgid "Name" msgstr "Nom" @@ -637,7 +638,7 @@ msgstr "Ajouter la diapositive" #: web/templates/admin/campsite/carousel/index.gohtml:30 #: web/templates/admin/services/index.gohtml:28 -#: web/templates/admin/surroundings/index.gohtml:28 +#: web/templates/admin/surroundings/index.gohtml:82 #: web/templates/admin/home/index.gohtml:52 #: web/templates/admin/home/index.gohtml:97 msgctxt "header" @@ -657,7 +658,7 @@ msgstr "Légende" #: web/templates/admin/services/index.gohtml:30 #: web/templates/admin/services/index.gohtml:75 #: web/templates/admin/user/index.gohtml:23 -#: web/templates/admin/surroundings/index.gohtml:30 +#: web/templates/admin/surroundings/index.gohtml:84 #: web/templates/admin/home/index.gohtml:54 #: web/templates/admin/home/index.gohtml:99 msgctxt "header" @@ -675,7 +676,8 @@ msgstr "Êtes-vous sûr de vouloir supprimer cette diapositive ?" #: web/templates/admin/services/index.gohtml:47 #: web/templates/admin/services/index.gohtml:91 #: web/templates/admin/user/index.gohtml:37 -#: web/templates/admin/surroundings/index.gohtml:47 +#: web/templates/admin/surroundings/index.gohtml:63 +#: web/templates/admin/surroundings/index.gohtml:101 #: web/templates/admin/home/index.gohtml:71 #: web/templates/admin/home/index.gohtml:116 msgctxt "action" @@ -1210,19 +1212,43 @@ msgstr "Page de l’entourage" #: web/templates/admin/surroundings/index.gohtml:14 msgctxt "title" +msgid "Ad" +msgstr "Annonce" + +#: web/templates/admin/surroundings/index.gohtml:21 +msgctxt "input" +msgid "Title" +msgstr "Titre" + +#: web/templates/admin/surroundings/index.gohtml:37 +msgctxt "input" +msgid "Link Text" +msgstr "Texte du lien" + +#: web/templates/admin/surroundings/index.gohtml:50 +msgctxt "input" +msgid "Link URL" +msgstr "Address du lien" + +#: web/templates/admin/surroundings/index.gohtml:59 +msgid "Are you sure you wish to delete the ad?" +msgstr "Êtes-vous sûr de vouloir supprimer cette annonce ?" + +#: web/templates/admin/surroundings/index.gohtml:68 +msgctxt "title" msgid "Highlights" msgstr "Points d’intérêt" -#: web/templates/admin/surroundings/index.gohtml:15 +#: web/templates/admin/surroundings/index.gohtml:69 msgctxt "action" msgid "Add highlight" msgstr "Ajouter un point d’intérêt" -#: web/templates/admin/surroundings/index.gohtml:34 +#: web/templates/admin/surroundings/index.gohtml:88 msgid "Are you sure you wish to delete this highlight?" msgstr "Êtes-vous sûr de vouloir supprimer cette point d’intérêt ?" -#: web/templates/admin/surroundings/index.gohtml:56 +#: web/templates/admin/surroundings/index.gohtml:110 msgid "No highlights added yet." msgstr "Aucun point d’intérêt n’a encore été ajoutée." @@ -1442,7 +1468,7 @@ msgstr "Aucune réservation trouvée." #: pkg/legal/admin.go:258 pkg/app/user.go:249 pkg/campsite/types/option.go:357 #: pkg/campsite/types/feature.go:259 pkg/campsite/types/admin.go:483 #: pkg/season/admin.go:412 pkg/services/admin.go:316 -#: pkg/surroundings/admin.go:321 +#: pkg/surroundings/admin.go:340 msgid "Name can not be empty." msgstr "Le nom ne peut pas être laissé vide." @@ -1462,12 +1488,12 @@ msgid "Set slide image" msgstr "Définir l’image de la diapositive" #: pkg/carousel/admin.go:346 pkg/campsite/types/carousel.go:299 -#: pkg/surroundings/admin.go:316 +#: pkg/surroundings/admin.go:335 msgid "Slide image can not be empty." msgstr "L’image de la diapositive ne peut pas être vide." #: pkg/carousel/admin.go:347 pkg/campsite/types/carousel.go:300 -#: pkg/surroundings/admin.go:317 +#: pkg/surroundings/admin.go:336 msgid "Slide image must be an image media type." msgstr "L’image de la diapositive doit être de type média d’image." @@ -1712,16 +1738,50 @@ msgctxt "role" msgid "admin" msgstr "administrateur" -#: pkg/surroundings/admin.go:267 +#: pkg/surroundings/admin.go:286 msgctxt "input" msgid "Highlight image" msgstr "Image du point d’intérêt" -#: pkg/surroundings/admin.go:268 +#: pkg/surroundings/admin.go:287 msgctxt "action" msgid "Set highlight image" msgstr "Définir l’image du point d’intérêt" +#: pkg/surroundings/admin.go:407 +msgctxt "input" +msgid "Ad image" +msgstr "Image de l’annonce" + +#: pkg/surroundings/admin.go:408 +msgctxt "action" +msgid "Set ad image" +msgstr "Définir l’image de l’annonce" + +#: pkg/surroundings/admin.go:459 +msgid "Ad image can not be empty." +msgstr "L’image de l’annonce ne peut pas être vide." + +#: pkg/surroundings/admin.go:460 +msgid "Ad image must be an image media type." +msgstr "L’image de l’annonce doit être de type média d’image." + +#: pkg/surroundings/admin.go:464 +msgid "The title can not be empty." +msgstr "Le titre ne peut pas être vide." + +#: pkg/surroundings/admin.go:465 +msgid "The link text can not be empty." +msgstr "Le texte du lien ne peut pas être vide." + +#: pkg/surroundings/admin.go:466 +msgid "The ad URL can not be empty" +msgstr "L’addresse du lien ne peut pas être vide." + +#: pkg/surroundings/admin.go:467 pkg/company/admin.go:221 +msgid "This web address is not valid. It should be like https://domain.com/." +msgstr "Cette adresse web n’est pas valide. Il devrait en être https://domain.com/." + #: pkg/company/admin.go:200 pkg/booking/public.go:256 msgid "Selected country is not valid." msgstr "Le pays sélectionné n’est pas valide." @@ -1750,10 +1810,6 @@ msgstr "Le téléphone ne peut pas être vide." msgid "This phone number is not valid." msgstr "Ce numéro de téléphone n’est pas valide." -#: pkg/company/admin.go:221 -msgid "This web address is not valid. It should be like https://domain.com/." -msgstr "Cette adresse web n’est pas valide. Il devrait en être https://domain.com/." - #: pkg/company/admin.go:223 msgid "Address can not be empty." msgstr "L’adresse ne peut pas être vide." diff --git a/revert/remove_surroundings_ad.sql b/revert/remove_surroundings_ad.sql new file mode 100644 index 0000000..a788596 --- /dev/null +++ b/revert/remove_surroundings_ad.sql @@ -0,0 +1,7 @@ +-- Revert camper:remove_surroundings_ad from pg + +begin; + +drop function if exists camper.remove_surroundings_ad(integer); + +commit; diff --git a/revert/setup_surroundings_ad.sql b/revert/setup_surroundings_ad.sql new file mode 100644 index 0000000..2ed6f65 --- /dev/null +++ b/revert/setup_surroundings_ad.sql @@ -0,0 +1,7 @@ +-- Revert camper:setup_surroundings_ad from pg + +begin; + +drop function if exists camper.setup_surroundings_ad(integer, integer, text, text, uri); + +commit; diff --git a/revert/surroundings_ad.sql b/revert/surroundings_ad.sql new file mode 100644 index 0000000..766618a --- /dev/null +++ b/revert/surroundings_ad.sql @@ -0,0 +1,7 @@ +-- Revert camper:surroundings_ad from pg + +begin; + +drop table if exists camper.surroundings_ad; + +commit; diff --git a/revert/surroundings_ad_i18n.sql b/revert/surroundings_ad_i18n.sql new file mode 100644 index 0000000..6ce9818 --- /dev/null +++ b/revert/surroundings_ad_i18n.sql @@ -0,0 +1,7 @@ +-- Revert camper:surroundings_ad_i18n from pg + +begin; + +drop table if exists camper.surroundings_ad_i18n; + +commit; diff --git a/revert/translate_surroundings_ad.sql b/revert/translate_surroundings_ad.sql new file mode 100644 index 0000000..e9029b7 --- /dev/null +++ b/revert/translate_surroundings_ad.sql @@ -0,0 +1,7 @@ +-- Revert camper:translate_surroundings_ad from pg + +begin; + +drop function if exists camper.translate_surroundings_ad(integer, text, text, text); + +commit; diff --git a/sqitch.plan b/sqitch.plan index d01074f..bc390ab 100644 --- a/sqitch.plan +++ b/sqitch.plan @@ -172,3 +172,8 @@ home [roles schema_camper company user_profile] 2024-01-23T10:02:08Z jordi fita setup_home [roles schema_camper home] 2024-01-23T10:14:14Z jordi fita mas # Add function to set up home page home_i18n [roles schema_camper home] 2024-01-23T10:19:47Z jordi fita mas # Add table to hold translated texts for home page translate_home [roles schema_camper home_i18n] 2024-01-23T10:24:02Z jordi fita mas # Add function to translate home texts +surroundings_ad [roles schema_camper company user_profile] 2024-01-23T11:23:58Z jordi fita mas # Add table to hold the ad in surroundings page +setup_surroundings_ad [roles schema_camper surroundings_ad] 2024-01-23T11:32:26Z jordi fita mas # Add function to set up surroundings ad +surroundings_ad_i18n [roles schema_camper surroundings_ad language] 2024-01-23T11:44:44Z jordi fita mas # Add relation for the translation of the surrounding ad +remove_surroundings_ad [roles schema_camper surroundings_ad surroundings_ad_i18n] 2024-01-23T11:41:47Z jordi fita mas # Add function to remove surroundings ad +translate_surroundings_ad [roles schema_camper surroundings_ad_i18n] 2024-01-23T12:06:32Z jordi fita mas # Add function to translate surroundings ad diff --git a/test/remove_surroundings_ad.sql b/test/remove_surroundings_ad.sql new file mode 100644 index 0000000..93d7996 --- /dev/null +++ b/test/remove_surroundings_ad.sql @@ -0,0 +1,99 @@ +-- Test remove_surroundings_ad +set client_min_messages to warning; +create extension if not exists pgtap; +reset client_min_messages; + +begin; + +select plan(12); + +set search_path to camper, public; + +select has_function('camper', 'remove_surroundings_ad', array['integer']); +select function_lang_is('camper', 'remove_surroundings_ad', array['integer'], 'sql'); +select function_returns('camper', 'remove_surroundings_ad', array['integer'], 'void'); +select isnt_definer('camper', 'remove_surroundings_ad', array['integer']); +select volatility_is('camper', 'remove_surroundings_ad', array['integer'], 'volatile'); +select function_privs_are('camper', 'remove_surroundings_ad', array['integer'], 'guest', array[]::text[]); +select function_privs_are('camper', 'remove_surroundings_ad', array['integer'], 'employee', array[]::text[]); +select function_privs_are('camper', 'remove_surroundings_ad', array['integer'], 'admin', array['EXECUTE']); +select function_privs_are('camper', 'remove_surroundings_ad', array['integer'], 'authenticator', array[]::text[]); + +set client_min_messages to warning; +truncate surroundings_ad_i18n cascade; +truncate surroundings_ad cascade; +truncate media cascade; +truncate media_content cascade; +truncate company_host cascade; +truncate company_user cascade; +truncate company cascade; +truncate auth."user" cascade; +reset client_min_messages; + +insert into auth."user" (user_id, email, name, password, cookie, cookie_expires_at) +values (1, 'demo@tandem.blog', 'Demo', 'test', '44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e', current_timestamp + interval '1 month') + , (5, 'admin@tandem.blog', 'Demo', 'test', '12af4c88b528c2ad4222e3740496ecbc58e76e26f087657524', current_timestamp + interval '1 month') +; + +insert into company (company_id, business_name, vatin, trade_name, phone, email, web, address, city, province, postal_code, rtc_number, tourist_tax, country_code, currency_code, default_lang_tag) +values (2, 'Company 2', 'XX123', '', '555-555-555', 'a@a', '', '', '', '', '', '', 60, 'ES', 'EUR', 'ca') + , (4, 'Company 4', 'XX234', '', '666-666-666', 'b@b', '', '', '', '', '', '', 60, 'FR', 'USD', 'ca') +; + +insert into company_user (company_id, user_id, role) +values (2, 1, 'admin') + , (4, 5, 'admin') +; + +insert into company_host (company_id, host) +values (2, 'co2') + , (4, 'co4') +; + +insert into media_content (media_type, bytes) +values ('text/plain', 'content2') + , ('text/plain', 'content4') +; + +insert into media (media_id, company_id, original_filename, content_hash) +values ( 7, 2, 'text2.txt', sha256('content2')) + , ( 8, 4, 'text3.txt', sha256('content4')) +; + +insert into surroundings_ad (company_id, media_id, title, anchor, href) +values (2, 7, 'Ad 2', 'Go!', 'https://ddg.gg/') + , (4, 8, 'Ad 4', 'Go!', 'https://ddg.gg/') +; + +insert into surroundings_ad_i18n (company_id, lang_tag, title, anchor) +values (2, 'ca', 'Anunci 2', 'Ves!') + , (2, 'es', 'Anuncio 2', '¡Ve!') + , (4, 'ca', 'Anunci 4', 'Ves!') + , (4, 'es', 'Anuncio 4', '¡Ve!') +; + +select lives_ok( + $$ select remove_surroundings_ad(2) $$, + 'Should be able to delete the ad from the first company' +); + +select bag_eq( + $$ select company_id, media_id, title, anchor, href::text from surroundings_ad $$, + $$ values (4, 8, 'Ad 4', 'Go!', 'https://ddg.gg/') + $$, + 'The row should have been deleted.' +); + +select bag_eq( + $$ select company_id, lang_tag, title, anchor from surroundings_ad_i18n $$, + $$ values (4, 'ca', 'Anunci 4', 'Ves!') + , (4, 'es', 'Anuncio 4', '¡Ve!') + $$, + 'The translations should have been deleted.' +); + + +select * +from finish(); + +rollback; diff --git a/test/setup_surroundings_ad.sql b/test/setup_surroundings_ad.sql new file mode 100644 index 0000000..2a6303f --- /dev/null +++ b/test/setup_surroundings_ad.sql @@ -0,0 +1,95 @@ +-- Test setup_surroundings_ad +set client_min_messages to warning; +create extension if not exists pgtap; +reset client_min_messages; + +begin; + +select plan(15); + +set search_path to camper, public; + +select has_function('camper', 'setup_surroundings_ad', array['integer', 'integer', 'text', 'text', 'uri']); +select function_lang_is('camper', 'setup_surroundings_ad', array['integer', 'integer', 'text', 'text', 'uri'], 'sql'); +select function_returns('camper', 'setup_surroundings_ad', array['integer', 'integer', 'text', 'text', 'uri'], 'void'); +select isnt_definer('camper', 'setup_surroundings_ad', array['integer', 'integer', 'text', 'text', 'uri']); +select volatility_is('camper', 'setup_surroundings_ad', array['integer', 'integer', 'text', 'text', 'uri'], 'volatile'); +select function_privs_are('camper', 'setup_surroundings_ad', array ['integer', 'integer', 'text', 'text', 'uri'], 'guest', array[]::text[]); +select function_privs_are('camper', 'setup_surroundings_ad', array ['integer', 'integer', 'text', 'text', 'uri'], 'employee', array[]::text[]); +select function_privs_are('camper', 'setup_surroundings_ad', array ['integer', 'integer', 'text', 'text', 'uri'], 'admin', array['EXECUTE']); +select function_privs_are('camper', 'setup_surroundings_ad', array ['integer', 'integer', 'text', 'text', 'uri'], 'authenticator', array[]::text[]); + + +set client_min_messages to warning; +truncate surroundings_ad cascade; +truncate media cascade; +truncate media_content cascade; +truncate company cascade; +reset client_min_messages; + +insert into company (company_id, business_name, vatin, trade_name, phone, email, web, address, city, province, postal_code, rtc_number, tourist_tax, country_code, currency_code, default_lang_tag) +values (1, 'Company 2', 'XX123', '', '555-555-555', 'a@a', '', '', '', '', '', '', 60, 'ES', 'EUR', 'ca') + , (2, 'Company 4', 'XX234', '', '666-666-666', 'b@b', '', '', '', '', '', '', 60, 'FR', 'USD', 'ca') +; + +insert into media_content (media_type, bytes) +values ('text/plain', 'content2') + , ('text/plain', 'content3') + , ('text/plain', 'content4') + , ('text/plain', 'content5') +; + +insert into media (media_id, company_id, original_filename, content_hash) +values ( 7, 1, 'text2.txt', sha256('content2')) + , ( 8, 1, 'text3.txt', sha256('content3')) + , ( 9, 2, 'text4.txt', sha256('content4')) + , (10, 2, 'text5.txt', sha256('content5')) +; + + +prepare surroundings_ad_data as +select company_id, media_id, title, anchor, href::text +from surroundings_ad +; + +select lives_ok( + $$ select setup_surroundings_ad(1, 7, 'Enjoy!', 'Good Link', 'https://ddg.gg/') $$, + 'Should be able to setup surroundings_ad for the first company' +); + +select lives_ok( + $$ select setup_surroundings_ad(2, 9, 'Go Away!', 'Bad Link', 'https://google.es/') $$, + 'Should be able to setup surroundings_ad for the second company' +); + +select bag_eq( + 'surroundings_ad_data', + $$ values (1, 7, 'Enjoy!', 'Good Link', 'https://ddg.gg/') + , (2, 9, 'Go Away!', 'Bad Link', 'https://google.es/') + $$, + 'Should have inserted all surrounding ad' +); + +select lives_ok( + $$ select setup_surroundings_ad(1, 8, 'Come Back!', 'Good Memories', 'https://astalavista.box.sk/') $$, + 'Should be able to update surroundings_ad for the first company' +); + +select lives_ok( + $$ select setup_surroundings_ad(2, 10, 'Quoi?', 'Ecs', 'https://yahoo.fr/') $$, + 'Should be able to update surroundings_ad for the second company' +); + +select bag_eq( + 'surroundings_ad_data', + $$ values (1, 8, 'Come Back!', 'Good Memories', 'https://astalavista.box.sk/') + , (2, 10, 'Quoi?', 'Ecs', 'https://yahoo.fr/') + $$, + 'Should have updated all surrounding ad' +); + + +select * +from finish(); + +rollback; diff --git a/test/surroundings_ad.sql b/test/surroundings_ad.sql new file mode 100644 index 0000000..a3c903e --- /dev/null +++ b/test/surroundings_ad.sql @@ -0,0 +1,196 @@ +-- Test surroundings_ad +set client_min_messages to warning; +create extension if not exists pgtap; +reset client_min_messages; + +begin; + +select plan(44); + +set search_path to camper, public; + +select has_table('surroundings_ad'); +select has_pk('surroundings_ad'); +select table_privs_are('surroundings_ad', 'guest', array['SELECT']); +select table_privs_are('surroundings_ad', 'employee', array['SELECT']); +select table_privs_are('surroundings_ad', 'admin', array['SELECT', 'INSERT', 'UPDATE', 'DELETE']); +select table_privs_are('surroundings_ad', 'authenticator', array[]::text[]); + +select has_column('surroundings_ad', 'company_id'); +select col_is_pk('surroundings_ad', 'company_id'); +select col_is_fk('surroundings_ad', 'company_id'); +select fk_ok('surroundings_ad', 'company_id', 'company', 'company_id'); +select col_type_is('surroundings_ad', 'company_id', 'integer'); +select col_not_null('surroundings_ad', 'company_id'); +select col_hasnt_default('surroundings_ad', 'company_id'); + +select has_column('surroundings_ad', 'media_id'); +select col_is_fk('surroundings_ad', 'media_id'); +select fk_ok('surroundings_ad', 'media_id', 'media', 'media_id'); +select col_type_is('surroundings_ad', 'media_id', 'integer'); +select col_not_null('surroundings_ad', 'media_id'); +select col_hasnt_default('surroundings_ad', 'media_id'); + +select has_column('surroundings_ad', 'title'); +select col_type_is('surroundings_ad', 'title', 'text'); +select col_not_null('surroundings_ad', 'title'); +select col_hasnt_default('surroundings_ad', 'title'); + +select has_column('surroundings_ad', 'anchor'); +select col_type_is('surroundings_ad', 'anchor', 'text'); +select col_not_null('surroundings_ad', 'anchor'); +select col_hasnt_default('surroundings_ad', 'anchor'); + +select has_column('surroundings_ad', 'href'); +select col_type_is('surroundings_ad', 'href', 'uri'); +select col_not_null('surroundings_ad', 'href'); +select col_hasnt_default('surroundings_ad', 'href'); + + +set client_min_messages to warning; +truncate surroundings_ad cascade; +truncate media cascade; +truncate media_content cascade; +truncate company_host cascade; +truncate company_user cascade; +truncate company cascade; +truncate auth."user" cascade; +reset client_min_messages; + +insert into auth."user" (user_id, email, name, password, cookie, cookie_expires_at) +values (1, 'demo@tandem.blog', 'Demo', 'test', '44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e', current_timestamp + interval '1 month') + , (5, 'admin@tandem.blog', 'Demo', 'test', '12af4c88b528c2ad4222e3740496ecbc58e76e26f087657524', current_timestamp + interval '1 month') +; + +insert into company (company_id, business_name, vatin, trade_name, phone, email, web, address, city, province, postal_code, rtc_number, tourist_tax, country_code, currency_code, default_lang_tag) +values (2, 'Company 2', 'XX123', '', '555-555-555', 'a@a', '', '', '', '', '', '', 60, 'ES', 'EUR', 'ca') + , (4, 'Company 4', 'XX234', '', '666-666-666', 'b@b', '', '', '', '', '', '', 60, 'FR', 'USD', 'ca') + , (6, 'Company 5', 'XX345', '', '777-777-777', 'c@c', '', '', '', '', '', '', 60, 'FR', 'USD', 'ca') +; + +insert into company_user (company_id, user_id, role) +values (2, 1, 'admin') + , (4, 5, 'admin') +; + +insert into company_host (company_id, host) +values (2, 'co2') + , (4, 'co4') +; + +insert into media_content (media_type, bytes) +values ('text/plain', 'content2') + , ('text/plain', 'content4') +; + +insert into media (media_id, company_id, original_filename, content_hash) +values ( 7, 2, 'text2.txt', sha256('content2')) + , ( 8, 4, 'text3.txt', sha256('content4')) +; + +insert into surroundings_ad (company_id, media_id, title, anchor, href) +values (2, 7, 'Ad 2', 'Go!', 'https://ddg.gg/') + , (4, 8, 'Ad 4', 'Go!', 'https://ddg.gg/') +; + +prepare surroundings_ad_data as +select company_id, title +from surroundings_ad +order by company_id, title; + +set role guest; +select bag_eq( + 'surroundings_ad_data', + $$ values (2, 'Ad 2') + , (4, 'Ad 4') + $$, + 'Everyone should be able to list all surrounding ad across all companies' +); +reset role; + +select set_cookie('44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e/demo@tandem.blog', 'co2'); + +select lives_ok( + $$ delete from surroundings_ad where company_id = 2 $$, + 'Admin from company 2 should be able to delete surrounding ad from that company.' +); + +select bag_eq( + 'surroundings_ad_data', + $$ values (4, 'Ad 4') + $$, + 'The row should have been deleted.' +); + +select lives_ok( + $$ insert into surroundings_ad(company_id, media_id, title, anchor, href) values (2, 7, 'Another Ad', 'Go!', 'https://ddg.gg/') $$, + 'Admin from company 2 should be able to insert a new surrounding ad to that company.' +); + +select bag_eq( + 'surroundings_ad_data', + $$ values (2, 'Another Ad') + , (4, 'Ad 4') + $$, + 'The new row should have been added' +); + +select lives_ok( + $$ update surroundings_ad set title = 'Ad 2' where company_id = 2 $$, + 'Admin from company 2 should be able to update surrounding ad of that company.' +); + +select bag_eq( + 'surroundings_ad_data', + $$ values (2, 'Ad 2') + , (4, 'Ad 4') + $$, + 'The row should have been updated.' +); + +select throws_ok( + $$ insert into surroundings_ad (company_id, title) values (6, 'Ad 6') $$, + '42501', 'new row violates row-level security policy for table "surroundings_ad"', + 'Admin from company 2 should NOT be able to insert new surrounding ad to company 6.' +); + +select lives_ok( + $$ update surroundings_ad set title = 'Nope' where company_id = 4 $$, + 'Admin from company 2 should not be able to update new surrounding ad of company 4, but no error if company_id is not changed.' +); + +select bag_eq( + 'surroundings_ad_data', + $$ values (2, 'Ad 2') + , (4, 'Ad 4') + $$, + 'No row should have been changed.' +); + +select throws_ok( + $$ update surroundings_ad set company_id = 6 where company_id = 2 $$, + '42501', 'new row violates row-level security policy for table "surroundings_ad"', + 'Admin from company 2 should NOT be able to move surrounding ad to company 6' +); + +select lives_ok( + $$ delete from surroundings_ad where company_id = 4 $$, + 'Admin from company 2 should NOT be able to delete surrounding ad from company 4, but not error is thrown' +); + +select bag_eq( + 'surroundings_ad_data', + $$ values (2, 'Ad 2') + , (4, 'Ad 4') + $$, + 'No row should have been changed' +); + +reset role; + + +select * +from finish(); + +rollback; + diff --git a/test/surroundings_ad_i18n.sql b/test/surroundings_ad_i18n.sql new file mode 100644 index 0000000..d262e14 --- /dev/null +++ b/test/surroundings_ad_i18n.sql @@ -0,0 +1,49 @@ +-- Test surroundings_ad_i18n +set client_min_messages to warning; +create extension if not exists pgtap; +reset client_min_messages; + +begin; + +select plan(27); + +set search_path to camper, public; + +select has_table('surroundings_ad_i18n'); +select has_pk('surroundings_ad_i18n'); +select col_is_pk('surroundings_ad_i18n', array['company_id', 'lang_tag']); +select table_privs_are('surroundings_ad_i18n', 'guest', array['SELECT']); +select table_privs_are('surroundings_ad_i18n', 'employee', array['SELECT']); +select table_privs_are('surroundings_ad_i18n', 'admin', array['SELECT', 'INSERT', 'UPDATE', 'DELETE']); +select table_privs_are('surroundings_ad_i18n', 'authenticator', array[]::text[]); + +select has_column('surroundings_ad_i18n', 'company_id'); +select col_is_fk('surroundings_ad_i18n', 'company_id'); +select fk_ok('surroundings_ad_i18n', 'company_id', 'surroundings_ad', 'company_id'); +select col_type_is('surroundings_ad_i18n', 'company_id', 'integer'); +select col_not_null('surroundings_ad_i18n', 'company_id'); +select col_hasnt_default('surroundings_ad_i18n', 'company_id'); + +select has_column('surroundings_ad_i18n', 'lang_tag'); +select col_is_fk('surroundings_ad_i18n', 'lang_tag'); +select fk_ok('surroundings_ad_i18n', 'lang_tag', 'language', 'lang_tag'); +select col_type_is('surroundings_ad_i18n', 'lang_tag', 'text'); +select col_not_null('surroundings_ad_i18n', 'lang_tag'); +select col_hasnt_default('surroundings_ad_i18n', 'lang_tag'); + +select has_column('surroundings_ad_i18n', 'title'); +select col_type_is('surroundings_ad_i18n', 'title', 'text'); +select col_not_null('surroundings_ad_i18n', 'title'); +select col_hasnt_default('surroundings_ad_i18n', 'title'); + +select has_column('surroundings_ad_i18n', 'anchor'); +select col_type_is('surroundings_ad_i18n', 'anchor', 'text'); +select col_not_null('surroundings_ad_i18n', 'anchor'); +select col_hasnt_default('surroundings_ad_i18n', 'anchor'); + + +select * +from finish(); + +rollback; + diff --git a/test/translate_surroundings_ad.sql b/test/translate_surroundings_ad.sql new file mode 100644 index 0000000..c90350c --- /dev/null +++ b/test/translate_surroundings_ad.sql @@ -0,0 +1,101 @@ +-- Test translate_surroundings_ad +set client_min_messages to warning; +create extension if not exists pgtap; +reset client_min_messages; + +begin; + +select plan(13); + +set search_path to camper, public; + +select has_function('camper', 'translate_surroundings_ad', array['integer', 'text', 'text', 'text']); +select function_lang_is('camper', 'translate_surroundings_ad', array['integer', 'text', 'text', 'text'], 'sql'); +select function_returns('camper', 'translate_surroundings_ad', array['integer', 'text', 'text', 'text'], 'void'); +select isnt_definer('camper', 'translate_surroundings_ad', array['integer', 'text', 'text', 'text']); +select volatility_is('camper', 'translate_surroundings_ad', array['integer', 'text', 'text', 'text'], 'volatile'); +select function_privs_are('camper', 'translate_surroundings_ad', array['integer', 'text', 'text', 'text'], 'guest', array[]::text[]); +select function_privs_are('camper', 'translate_surroundings_ad', array['integer', 'text', 'text', 'text'], 'employee', array[]::text[]); +select function_privs_are('camper', 'translate_surroundings_ad', array['integer', 'text', 'text', 'text'], 'admin', array['EXECUTE']); +select function_privs_are('camper', 'translate_surroundings_ad', array['integer', 'text', 'text', 'text'], 'authenticator', array[]::text[]); + + +set client_min_messages to warning; +truncate surroundings_ad_i18n cascade; +truncate surroundings_ad cascade; +truncate media cascade; +truncate media_content cascade; +truncate company_host cascade; +truncate company_user cascade; +truncate company cascade; +truncate auth."user" cascade; +reset client_min_messages; + +insert into auth."user" (user_id, email, name, password, cookie, cookie_expires_at) +values (1, 'demo@tandem.blog', 'Demo', 'test', '44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e', current_timestamp + interval '1 month') + , (5, 'admin@tandem.blog', 'Demo', 'test', '12af4c88b528c2ad4222e3740496ecbc58e76e26f087657524', current_timestamp + interval '1 month') +; + +insert into company (company_id, business_name, vatin, trade_name, phone, email, web, address, city, province, postal_code, rtc_number, tourist_tax, country_code, currency_code, default_lang_tag) +values (2, 'Company 2', 'XX123', '', '555-555-555', 'a@a', '', '', '', '', '', '', 60, 'ES', 'EUR', 'ca') + , (4, 'Company 4', 'XX234', '', '666-666-666', 'b@b', '', '', '', '', '', '', 60, 'FR', 'USD', 'ca') +; + +insert into company_user (company_id, user_id, role) +values (2, 1, 'admin') + , (4, 5, 'admin') +; + +insert into company_host (company_id, host) +values (2, 'co2') + , (4, 'co4') +; + +insert into media_content (media_type, bytes) +values ('text/plain', 'content2') + , ('text/plain', 'content4') +; + +insert into media (media_id, company_id, original_filename, content_hash) +values ( 7, 2, 'text2.txt', sha256('content2')) + , ( 8, 4, 'text3.txt', sha256('content4')) +; + +insert into surroundings_ad (company_id, media_id, title, anchor, href) +values (2, 7, 'Ad 2', 'Go!', 'https://ddg.gg/') + , (4, 8, 'Ad 4', 'Go!', 'https://ddg.gg/') +; + +insert into surroundings_ad_i18n (company_id, lang_tag, title, anchor) +values (2, 'ca', 'anun 2', 'au!') +; + +select lives_ok( + $$ select translate_surroundings_ad(4, 'es', 'Anuncio 4', '¡Ve!') $$, + 'Should be able to translate the ad from the first company to Spanish' +); + +select lives_ok( + $$ select translate_surroundings_ad(4, 'ca', 'Anunci 4', 'Ves!') $$, + 'Should be able to translate the ad from the first company to Catalan' +); + +select lives_ok( + $$ select translate_surroundings_ad(2, 'ca', 'Anunci 2', 'Ups!') $$, + 'Should be able to update Catalan translation of the ad from the first company' +); + +select bag_eq( + $$ select company_id, lang_tag, title, anchor from surroundings_ad_i18n $$, + $$ values (2, 'ca', 'Anunci 2', 'Ups!') + , (4, 'ca', 'Anunci 4', 'Ves!') + , (4, 'es', 'Anuncio 4', '¡Ve!') + $$, + 'The translations should have been updated.' +); + + +select * +from finish(); + +rollback; diff --git a/verify/remove_surroundings_ad.sql b/verify/remove_surroundings_ad.sql new file mode 100644 index 0000000..c9cfa4d --- /dev/null +++ b/verify/remove_surroundings_ad.sql @@ -0,0 +1,7 @@ +-- Verify camper:remove_surroundings_ad on pg + +begin; + +select has_function_privilege('camper.remove_surroundings_ad(integer)', 'execute'); + +rollback; diff --git a/verify/setup_surroundings_ad.sql b/verify/setup_surroundings_ad.sql new file mode 100644 index 0000000..9c3c38b --- /dev/null +++ b/verify/setup_surroundings_ad.sql @@ -0,0 +1,7 @@ +-- Verify camper:setup_surroundings_ad on pg + +begin; + +select has_function_privilege('camper.setup_surroundings_ad(integer, integer, text, text, uri)', 'execute'); + +rollback; diff --git a/verify/surroundings_ad.sql b/verify/surroundings_ad.sql new file mode 100644 index 0000000..7b75f61 --- /dev/null +++ b/verify/surroundings_ad.sql @@ -0,0 +1,19 @@ +-- Verify camper:surroundings_ad on pg + +begin; + +select company_id + , media_id + , title + , anchor + , href +from camper.surroundings_ad +where false; + +select 1 / count(*) from pg_class where oid = 'camper.surroundings_ad'::regclass and relrowsecurity; +select 1 / count(*) from pg_policy where polname = 'guest_ok' and polrelid = 'camper.surroundings_ad'::regclass; +select 1 / count(*) from pg_policy where polname = 'insert_to_company' and polrelid = 'camper.surroundings_ad'::regclass; +select 1 / count(*) from pg_policy where polname = 'update_company' and polrelid = 'camper.surroundings_ad'::regclass; +select 1 / count(*) from pg_policy where polname = 'delete_from_company' and polrelid = 'camper.surroundings_ad'::regclass; + +rollback; diff --git a/verify/surroundings_ad_i18n.sql b/verify/surroundings_ad_i18n.sql new file mode 100644 index 0000000..3081a1d --- /dev/null +++ b/verify/surroundings_ad_i18n.sql @@ -0,0 +1,12 @@ +-- Verify camper:surroundings_ad_i18n on pg + +begin; + +select company_id + , lang_tag + , title + , anchor +from camper.surroundings_ad_i18n +where false; + +rollback; diff --git a/verify/translate_surroundings_ad.sql b/verify/translate_surroundings_ad.sql new file mode 100644 index 0000000..dc84217 --- /dev/null +++ b/verify/translate_surroundings_ad.sql @@ -0,0 +1,7 @@ +-- Verify camper:translate_surroundings_ad on pg + +begin; + +select has_function_privilege('camper.translate_surroundings_ad(integer, text, text, text)', 'execute'); + +rollback; diff --git a/web/static/public.css b/web/static/public.css index b2184fe..9b7dc2b 100644 --- a/web/static/public.css +++ b/web/static/public.css @@ -530,7 +530,7 @@ dl, .nature > div, .outside_activities > div { padding: .55rem 1.5rem 1rem; background-color: var(--accent); color: var(--base); - border-top-left-radius: .6rem; + border-top-left-radius: .6rem; border-bottom-right-radius: .6rem; } @@ -675,7 +675,7 @@ dt { } .outside_activities img { - border-radius: .6rem; + border-radius: .6rem; } .outside_activities h3, .campsite_services .spiel { @@ -1443,65 +1443,66 @@ address { /* surrounding */ -.ad-container { +#surroundings-ad { display: flex; - flex-direction: row; - flex-wrap: wrap; - margin: 50px 0; -} - -.ad-image-container { - width: 50%; - min-height: 300px; - border-top-left-radius: .6rem; - border-bottom-left-radius:.8rem; - background-image: url(https://campingmontagut.tandem.ws/media/0c0625998215b6caec6e871ab26d791c330f34bb46a2facc9d502d769d207e7b/barranquisme.jpg); - background-repeat: no-repeat; - background-position: center center; - background-size: cover; -} - -.ad-description-container { - width: 50%; - min-height: 300px; - display: flex; - flex-direction: column; - justify-content: center; - padding: 50px; - border-top-right-radius: .6rem; - border-bottom-right-radius: .6rem; + margin: 5rem 0; + border-radius: .6rem; + overflow: hidden; background-color: var(--accent-2); } -.ad-description-container h3 { - font-size: calc(16px + .7vw); - font-weight: 400; - line-height: 9rem; +#surroundings-ad::before { + content: ''; + background: var(--background-image) center center no-repeat; + background-size: cover; + min-height: 30rem; } -.ad-button { - font-size: calc(18px + 1.7vw); +#surroundings-ad::before, #surroundings-ad > div { + flex: 1; +} + +#surroundings-ad > div { + display: flex; + flex-direction: column; + justify-content: center; + padding: 5rem; +} + +#surroundings-ad h3 { + font-size: calc(1.6rem + .7vw); + font-weight: 400; + margin-bottom: 2.585rem; +} + +#surroundings-ad a { + font-size: calc(1.8rem + 1.7vw); font-weight: 600; line-height: 0.9em; display: flex; align-items: flex-start; - column-gap: 0.5em; - border-radius: .6rem; + gap: 0.5em; color: var(--contrast); } -.ad-button .ad-icon svg { - width: 40px; +#surroundings-ad svg { + width: 4rem; transform: rotate(320deg) translate3d(-5px, -10px, 0); - transition: all 0.5s ease; + transition: transform 0.5s ease; } -.ad-button:hover .gb-icon svg { +#surroundings-ad a:hover svg { transform: rotate(320deg) translate3d(10px, 0, 0); } -.arrow_link { - fill: var(--contrast); +@media (max-width: 48rem) { + #surroundings-ad { + flex-direction: column-reverse; + } + + #surroundings-ad > div { + justify-content: start; + } } /* services */ diff --git a/web/templates/admin/surroundings/index.gohtml b/web/templates/admin/surroundings/index.gohtml index 18a36f0..dc4ba62 100644 --- a/web/templates/admin/surroundings/index.gohtml +++ b/web/templates/admin/surroundings/index.gohtml @@ -11,6 +11,60 @@ {{ define "content" -}} {{- /*gotype: dev.tandem.ws/tandem/camper/pkg/surroundings.highlightIndex*/ -}} +

{{( pgettext "Ad" "title" )}}

+ {{ with .Ad -}} +
+ {{ CSRFInput }} +
+ {{ with .Title -}} +
+ {{( pgettext "Title" "input")}} + {{ template "lang-selector" . }} + {{ range $lang, $input := . -}} + + {{- end }} + {{ template "error-message" . }} +
+ {{- end }} + {{ with .Media -}} + {{ template "media-picker" . }} + {{- end }} + {{ with .Anchor -}} +
+ {{( pgettext "Link Text" "input")}} + {{ template "lang-selector" . }} + {{ range $lang, $input := . -}} + + {{- end }} + {{ template "error-message" . }} +
+ {{- end }} + {{ with .HRef -}} + + {{ template "error-message" . }} + {{- end }} +
+
+ + {{ $confirm := ( gettext "Are you sure you wish to delete the ad?" )}} + +
+
+ {{- end }}

{{( pgettext "Highlights" "title" )}}

{{( pgettext "Add highlight" "action" )}} {{ if .Highlights -}} diff --git a/web/templates/public/surroundings.gohtml b/web/templates/public/surroundings.gohtml index 12f6f25..54b3471 100644 --- a/web/templates/public/surroundings.gohtml +++ b/web/templates/public/surroundings.gohtml @@ -11,22 +11,20 @@ {{- /*gotype: dev.tandem.ws/tandem/camper/pkg/surroundings.surroundingsPage*/ -}}

{{( pgettext "Surroundings" "title" )}}

-
-
+ {{- end }}

{{( pgettext "What to Do Outside the Campsite?" "title" )}}