Add campsite map in SVG
I intend to use the same SVG file for customers and employees, so i had to change Oriol’s design to add a class to layers that are supposed to be only for customers, like trees. These are hidden in the admin area. I understood that customers and employees have to click on a campsite to select it, and then they can book or whatever they need to do to them. Since customers and employees most certainly will need to have different listeners on campsites, i decided to add the link with JavaScript. To do so, i need a custom XML attribute with the campsite’s identifier. Since i have seen that all campsites have a label, i changed the “identifier” to the unique combination (company_id, label). The company_id is there because different companies could have the same label; i left the campsite_id primary key for foreign constraints. In this case, as a test, i add an <a> element to the campsite with a link to edit it; we’ll discuss with Oriol what exactly it needs to do. However, the original design had the labels in a different layer, that interfered with the link, as the numbers must be above the path and the link must wrap the path in order to “inherit” its shape. I had no other recourse than to move the labels in the same layer as the paths’.
This commit is contained in:
parent
8c0dbf7806
commit
e3503187d3
|
@ -99,6 +99,86 @@ values (72, 'en', 'Plots', '')
|
|||
, (75, 'es', 'Cabañas de madera', '')
|
||||
;
|
||||
|
||||
select add_campsite(72, '2');
|
||||
select add_campsite(72, '3');
|
||||
select add_campsite(72, '4');
|
||||
select add_campsite(72, '5');
|
||||
select add_campsite(72, '6');
|
||||
select add_campsite(72, '7');
|
||||
select add_campsite(72, '8');
|
||||
select add_campsite(72, '9');
|
||||
select add_campsite(72, '10');
|
||||
select add_campsite(72, '11');
|
||||
select add_campsite(72, '12');
|
||||
select add_campsite(72, '14');
|
||||
select add_campsite(72, '15');
|
||||
select add_campsite(72, '16');
|
||||
select add_campsite(72, '17');
|
||||
select add_campsite(72, '18');
|
||||
select add_campsite(72, '19');
|
||||
select add_campsite(72, '20');
|
||||
select add_campsite(72, '21');
|
||||
select add_campsite(72, '22');
|
||||
select add_campsite(72, '23');
|
||||
select add_campsite(72, '24');
|
||||
select add_campsite(72, '25');
|
||||
select add_campsite(72, '26');
|
||||
select add_campsite(72, '27');
|
||||
select add_campsite(72, '28');
|
||||
select add_campsite(72, '29');
|
||||
select add_campsite(72, '42');
|
||||
select add_campsite(72, '43');
|
||||
select add_campsite(72, '44');
|
||||
select add_campsite(72, '45');
|
||||
select add_campsite(72, '46');
|
||||
select add_campsite(72, '47');
|
||||
select add_campsite(72, '48');
|
||||
select add_campsite(72, '50');
|
||||
select add_campsite(72, '51');
|
||||
select add_campsite(72, '52');
|
||||
select add_campsite(72, '53');
|
||||
select add_campsite(72, '54');
|
||||
select add_campsite(72, '55');
|
||||
select add_campsite(72, '56');
|
||||
select add_campsite(72, '57');
|
||||
select add_campsite(72, '58');
|
||||
select add_campsite(72, '59');
|
||||
select add_campsite(72, '60');
|
||||
select add_campsite(72, '61');
|
||||
select add_campsite(72, '62');
|
||||
select add_campsite(72, '63');
|
||||
select add_campsite(72, '64');
|
||||
select add_campsite(72, '65');
|
||||
select add_campsite(72, '69');
|
||||
select add_campsite(72, '70');
|
||||
select add_campsite(72, '71');
|
||||
select add_campsite(72, '72');
|
||||
select add_campsite(72, '73');
|
||||
select add_campsite(72, '74');
|
||||
select add_campsite(72, '75');
|
||||
select add_campsite(72, '76');
|
||||
select add_campsite(72, '77');
|
||||
select add_campsite(72, '79');
|
||||
select add_campsite(72, '80');
|
||||
select add_campsite(72, '81');
|
||||
select add_campsite(72, '82');
|
||||
select add_campsite(72, '83');
|
||||
select add_campsite(72, '89');
|
||||
select add_campsite(72, '90');
|
||||
select add_campsite(72, '91');
|
||||
select add_campsite(72, '92');
|
||||
select add_campsite(72, '93');
|
||||
select add_campsite(72, '94');
|
||||
select add_campsite(72, '95');
|
||||
select add_campsite(72, '96');
|
||||
select add_campsite(72, '97');
|
||||
select add_campsite(72, '98');
|
||||
select add_campsite(72, 'B1');
|
||||
select add_campsite(72, 'D1');
|
||||
select add_campsite(72, 'D2');
|
||||
select add_campsite(72, 'D3');
|
||||
select add_campsite(72, 'D4');
|
||||
|
||||
alter sequence service_service_id_seq restart with 82;
|
||||
insert into service (company_id, icon_name, name, description)
|
||||
values (52, 'information', 'Informació', '<p>A la recepció l’informarem del que pot fer des del càmping mateix o pels voltants.</p>')
|
||||
|
|
|
@ -8,21 +8,21 @@ begin;
|
|||
|
||||
set search_path to camper, public;
|
||||
|
||||
create or replace function add_campsite(campsite_type integer, label text) returns uuid as
|
||||
create or replace function add_campsite(campsite_type integer, label text) returns integer as
|
||||
$$
|
||||
declare
|
||||
campsite_slug uuid;
|
||||
cid integer;
|
||||
begin
|
||||
insert into campsite (company_id, campsite_type_id, label)
|
||||
select company_id, campsite_type_id, label
|
||||
from campsite_type
|
||||
where campsite_type_id = add_campsite.campsite_type
|
||||
returning slug into campsite_slug
|
||||
returning campsite_id into cid
|
||||
;
|
||||
if campsite_slug is null then
|
||||
if cid is null then
|
||||
raise foreign_key_violation using message = 'insert or update on table "campsite" violates foreign key constraint "campsite_campsite_type_id_fkey"';
|
||||
end if;
|
||||
return campsite_slug;
|
||||
return cid;
|
||||
end
|
||||
$$
|
||||
language plpgsql
|
||||
|
|
|
@ -12,10 +12,10 @@ set search_path to camper, public;
|
|||
create table campsite (
|
||||
campsite_id serial primary key,
|
||||
company_id integer not null references company,
|
||||
slug uuid unique not null default gen_random_uuid(),
|
||||
campsite_type_id integer not null references campsite_type,
|
||||
label text not null constraint label_not_empty check(length(trim(label)) > 0),
|
||||
active boolean not null default true
|
||||
campsite_type_id integer not null references campsite_type,
|
||||
active boolean not null default true,
|
||||
unique (company_id, label)
|
||||
);
|
||||
|
||||
grant select on table campsite to guest;
|
||||
|
|
|
@ -7,19 +7,19 @@ begin;
|
|||
|
||||
set search_path to camper, public;
|
||||
|
||||
create or replace function edit_campsite(slug uuid, campsite_type integer, label text, active boolean) returns uuid as
|
||||
create or replace function edit_campsite(campsite_id integer, campsite_type integer, new_label text, active boolean) returns integer as
|
||||
$$
|
||||
update campsite
|
||||
set label = edit_campsite.label
|
||||
set label = edit_campsite.new_label
|
||||
, campsite_type_id = edit_campsite.campsite_type
|
||||
, active = edit_campsite.active
|
||||
where slug = edit_campsite.slug
|
||||
returning slug;
|
||||
where campsite_id = edit_campsite.campsite_id
|
||||
returning campsite_id;
|
||||
$$
|
||||
language sql
|
||||
;
|
||||
|
||||
revoke execute on function edit_campsite(uuid, integer, text, boolean) from public;
|
||||
grant execute on function edit_campsite(uuid, integer, text, boolean) to admin;
|
||||
revoke execute on function edit_campsite(integer, integer, text, boolean) from public;
|
||||
grant execute on function edit_campsite(integer, integer, text, boolean) to admin;
|
||||
|
||||
commit;
|
||||
|
|
|
@ -16,7 +16,6 @@ import (
|
|||
httplib "dev.tandem.ws/tandem/camper/pkg/http"
|
||||
"dev.tandem.ws/tandem/camper/pkg/locale"
|
||||
"dev.tandem.ws/tandem/camper/pkg/template"
|
||||
"dev.tandem.ws/tandem/camper/pkg/uuid"
|
||||
)
|
||||
|
||||
type AdminHandler struct {
|
||||
|
@ -55,25 +54,28 @@ func (h *AdminHandler) Handler(user *auth.User, company *auth.Company, conn *dat
|
|||
httplib.MethodNotAllowed(w, r, http.MethodGet, http.MethodPost)
|
||||
}
|
||||
default:
|
||||
if !uuid.Valid(head) {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
f := newCampsiteForm(r.Context(), conn)
|
||||
if err := f.FillFromDatabase(r.Context(), conn, head); err != nil {
|
||||
if err := f.FillFromDatabase(r.Context(), conn, company, head); err != nil {
|
||||
if database.ErrorIsNotFound(err) {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
panic(err)
|
||||
}
|
||||
switch r.Method {
|
||||
case http.MethodGet:
|
||||
f.MustRender(w, r, user, company)
|
||||
case http.MethodPut:
|
||||
editCampsite(w, r, user, company, conn, f)
|
||||
|
||||
head, r.URL.Path = httplib.ShiftPath(r.URL.Path)
|
||||
switch head {
|
||||
case "":
|
||||
switch r.Method {
|
||||
case http.MethodGet:
|
||||
f.MustRender(w, r, user, company)
|
||||
case http.MethodPut:
|
||||
editCampsite(w, r, user, company, conn, f)
|
||||
default:
|
||||
httplib.MethodNotAllowed(w, r, http.MethodGet, http.MethodPut)
|
||||
}
|
||||
default:
|
||||
httplib.MethodNotAllowed(w, r, http.MethodGet, http.MethodPut)
|
||||
http.NotFound(w, r)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -92,8 +94,7 @@ func serveCampsiteIndex(w http.ResponseWriter, r *http.Request, user *auth.User,
|
|||
|
||||
func collectCampsiteEntries(ctx context.Context, company *auth.Company, conn *database.Conn) ([]*campsiteEntry, error) {
|
||||
rows, err := conn.Query(ctx, `
|
||||
select campsite.slug
|
||||
, campsite.label
|
||||
select campsite.label
|
||||
, campsite_type.name
|
||||
, campsite.active
|
||||
from campsite
|
||||
|
@ -108,7 +109,7 @@ func collectCampsiteEntries(ctx context.Context, company *auth.Company, conn *da
|
|||
var campsites []*campsiteEntry
|
||||
for rows.Next() {
|
||||
entry := &campsiteEntry{}
|
||||
if err = rows.Scan(&entry.Slug, &entry.Label, &entry.Type, &entry.Active); err != nil {
|
||||
if err = rows.Scan(&entry.Label, &entry.Type, &entry.Active); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
campsites = append(campsites, entry)
|
||||
|
@ -118,7 +119,6 @@ func collectCampsiteEntries(ctx context.Context, company *auth.Company, conn *da
|
|||
}
|
||||
|
||||
type campsiteEntry struct {
|
||||
Slug string
|
||||
Label string
|
||||
Type string
|
||||
Active bool
|
||||
|
@ -129,7 +129,7 @@ type campsiteIndex struct {
|
|||
}
|
||||
|
||||
func (page *campsiteIndex) MustRender(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company) {
|
||||
template.MustRenderAdmin(w, r, user, company, "campsite/index.gohtml", page)
|
||||
template.MustRenderAdminFiles(w, r, user, company, page, "campsite/index.gohtml", "web/templates/campsite_map.svg")
|
||||
}
|
||||
|
||||
func addCampsite(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn) {
|
||||
|
@ -169,12 +169,13 @@ func editCampsite(w http.ResponseWriter, r *http.Request, user *auth.User, compa
|
|||
f.MustRender(w, r, user, company)
|
||||
return
|
||||
}
|
||||
conn.MustExec(r.Context(), "select edit_campsite($1, $2, $3, $4)", f.Slug, f.CampsiteType, f.Label, f.Active)
|
||||
conn.MustExec(r.Context(), "select edit_campsite($1, $2, $3, $4)", f.ID, f.CampsiteType, f.Label, f.Active)
|
||||
httplib.Redirect(w, r, "/admin/campsites", http.StatusSeeOther)
|
||||
}
|
||||
|
||||
type campsiteForm struct {
|
||||
Slug string
|
||||
ID int
|
||||
CurrentLabel string
|
||||
Active *form.Checkbox
|
||||
CampsiteType *form.Select
|
||||
Label *form.Input
|
||||
|
@ -197,10 +198,17 @@ func newCampsiteForm(ctx context.Context, conn *database.Conn) *campsiteForm {
|
|||
}
|
||||
}
|
||||
|
||||
func (f *campsiteForm) FillFromDatabase(ctx context.Context, conn *database.Conn, slug string) error {
|
||||
f.Slug = slug
|
||||
row := conn.QueryRow(ctx, "select array[campsite_type_id::text], label, active from campsite where slug = $1", slug)
|
||||
return row.Scan(&f.CampsiteType.Selected, &f.Label.Val, &f.Active.Checked)
|
||||
func (f *campsiteForm) FillFromDatabase(ctx context.Context, conn *database.Conn, company *auth.Company, label string) error {
|
||||
f.CurrentLabel = label
|
||||
row := conn.QueryRow(ctx, `
|
||||
select campsite_id
|
||||
, array[campsite_type_id::text]
|
||||
, label
|
||||
, active
|
||||
from campsite
|
||||
where company_id = $1
|
||||
and label = $2`, company.ID, label)
|
||||
return row.Scan(&f.ID, &f.CampsiteType.Selected, &f.Label.Val, &f.Active.Checked)
|
||||
}
|
||||
|
||||
func (f *campsiteForm) Parse(r *http.Request) error {
|
||||
|
|
|
@ -33,6 +33,15 @@ func MustRenderAdmin(w io.Writer, r *http.Request, user *auth.User, company *aut
|
|||
mustRenderLayout(w, user, company, adminTemplateFile, data, layout, filename)
|
||||
}
|
||||
|
||||
func MustRenderAdminFiles(w io.Writer, r *http.Request, user *auth.User, company *auth.Company, data interface{}, filenames ...string) {
|
||||
layout := "layout.gohtml"
|
||||
if httplib.IsHTMxRequest(r) {
|
||||
layout = "htmx.gohtml"
|
||||
}
|
||||
filenames = append([]string{layout}, filenames...)
|
||||
mustRenderLayout(w, user, company, adminTemplateFile, data, filenames...)
|
||||
}
|
||||
|
||||
func MustRenderNoLayout(w io.Writer, r *http.Request, user *auth.User, company *auth.Company, filename string, data interface{}) {
|
||||
mustRenderLayout(w, user, company, adminTemplateFile, data, filename)
|
||||
}
|
||||
|
@ -73,7 +82,11 @@ func mustRenderLayout(w io.Writer, user *auth.User, company *auth.Company, templ
|
|||
templates = append(templates, "form.gohtml")
|
||||
files := make([]string, len(templates))
|
||||
for i, tmpl := range templates {
|
||||
files[i] = templateFile(tmpl)
|
||||
if len(tmpl) > 4 && tmpl[0] == 'w' && tmpl[1] == 'e' && tmpl[2] == 'b' && tmpl[3] == '/' {
|
||||
files[i] = tmpl
|
||||
} else {
|
||||
files[i] = templateFile(tmpl)
|
||||
}
|
||||
}
|
||||
if _, err := t.ParseFiles(files...); err != nil {
|
||||
panic(err)
|
||||
|
|
38
po/ca.po
38
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: 2023-09-22 02:14+0200\n"
|
||||
"POT-Creation-Date: 2023-09-24 03:04+0200\n"
|
||||
"PO-Revision-Date: 2023-07-22 23:45+0200\n"
|
||||
"Last-Translator: jordi fita mas <jordi@tandem.blog>\n"
|
||||
"Language-Team: Catalan <ca@dodds.net>\n"
|
||||
|
@ -217,7 +217,7 @@ msgid "New Campsite"
|
|||
msgstr "Nou allotjament"
|
||||
|
||||
#: web/templates/admin/campsite/form.gohtml:38
|
||||
#: web/templates/admin/campsite/index.gohtml:20
|
||||
#: web/templates/admin/campsite/index.gohtml:21
|
||||
msgctxt "campsite"
|
||||
msgid "Active"
|
||||
msgstr "Actiu"
|
||||
|
@ -238,7 +238,7 @@ msgstr "Etiqueta"
|
|||
|
||||
#: web/templates/admin/campsite/index.gohtml:6
|
||||
#: web/templates/admin/campsite/index.gohtml:13
|
||||
#: web/templates/admin/layout.gohtml:70
|
||||
#: web/templates/admin/layout.gohtml:52 web/templates/admin/layout.gohtml:73
|
||||
msgctxt "title"
|
||||
msgid "Campsites"
|
||||
msgstr "Allotjaments"
|
||||
|
@ -248,29 +248,29 @@ msgctxt "action"
|
|||
msgid "Add Campsite"
|
||||
msgstr "Afegeix allotjament"
|
||||
|
||||
#: web/templates/admin/campsite/index.gohtml:18
|
||||
#: web/templates/admin/campsite/index.gohtml:19
|
||||
msgctxt "header"
|
||||
msgid "Label"
|
||||
msgstr "Etiqueta"
|
||||
|
||||
#: web/templates/admin/campsite/index.gohtml:19
|
||||
#: web/templates/admin/campsite/index.gohtml:20
|
||||
msgctxt "header"
|
||||
msgid "Type"
|
||||
msgstr "Tipus"
|
||||
|
||||
#: web/templates/admin/campsite/index.gohtml:28
|
||||
#: web/templates/admin/campsite/index.gohtml:29
|
||||
#: web/templates/admin/campsite/type/index.gohtml:36
|
||||
#: web/templates/admin/season/index.gohtml:32
|
||||
msgid "Yes"
|
||||
msgstr "Sí"
|
||||
|
||||
#: web/templates/admin/campsite/index.gohtml:28
|
||||
#: web/templates/admin/campsite/index.gohtml:29
|
||||
#: web/templates/admin/campsite/type/index.gohtml:36
|
||||
#: web/templates/admin/season/index.gohtml:32
|
||||
msgid "No"
|
||||
msgstr "No"
|
||||
|
||||
#: web/templates/admin/campsite/index.gohtml:34
|
||||
#: web/templates/admin/campsite/index.gohtml:35
|
||||
msgid "No campsites added yet."
|
||||
msgstr "No s’ha afegit cap allotjament encara."
|
||||
|
||||
|
@ -308,7 +308,7 @@ msgstr "Descripció"
|
|||
|
||||
#: web/templates/admin/campsite/type/index.gohtml:6
|
||||
#: web/templates/admin/campsite/type/index.gohtml:13
|
||||
#: web/templates/admin/layout.gohtml:67
|
||||
#: web/templates/admin/layout.gohtml:70
|
||||
msgctxt "title"
|
||||
msgid "Campsite Types"
|
||||
msgstr "Tipus d’allotjaments"
|
||||
|
@ -366,7 +366,7 @@ msgstr "Color"
|
|||
|
||||
#: web/templates/admin/season/index.gohtml:6
|
||||
#: web/templates/admin/season/index.gohtml:13
|
||||
#: web/templates/admin/layout.gohtml:73
|
||||
#: web/templates/admin/layout.gohtml:76
|
||||
msgctxt "title"
|
||||
msgid "Seasons"
|
||||
msgstr "Temporades"
|
||||
|
@ -413,7 +413,7 @@ msgid "Login"
|
|||
msgstr "Entra"
|
||||
|
||||
#: web/templates/admin/services/index.gohtml:6
|
||||
#: web/templates/admin/layout.gohtml:79
|
||||
#: web/templates/admin/layout.gohtml:82
|
||||
msgctxt "title"
|
||||
msgid "Services Page"
|
||||
msgstr "Pàgina de serveis"
|
||||
|
@ -493,7 +493,7 @@ msgstr "Desa els canvis"
|
|||
|
||||
#: web/templates/admin/taxDetails.gohtml:6
|
||||
#: web/templates/admin/taxDetails.gohtml:13
|
||||
#: web/templates/admin/layout.gohtml:64
|
||||
#: web/templates/admin/layout.gohtml:67
|
||||
msgctxt "title"
|
||||
msgid "Tax Details"
|
||||
msgstr "Configuració fiscal"
|
||||
|
@ -579,12 +579,12 @@ msgctxt "action"
|
|||
msgid "Logout"
|
||||
msgstr "Surt"
|
||||
|
||||
#: web/templates/admin/layout.gohtml:76 web/templates/admin/home/index.gohtml:6
|
||||
#: web/templates/admin/layout.gohtml:79 web/templates/admin/home/index.gohtml:6
|
||||
msgctxt "title"
|
||||
msgid "Home Page"
|
||||
msgstr "Pàgina d’inici"
|
||||
|
||||
#: web/templates/admin/layout.gohtml:82
|
||||
#: web/templates/admin/layout.gohtml:85
|
||||
#: web/templates/admin/media/index.gohtml:6
|
||||
#: web/templates/admin/media/index.gohtml:12
|
||||
msgctxt "title"
|
||||
|
@ -619,17 +619,17 @@ msgctxt "action"
|
|||
msgid "Upload"
|
||||
msgstr "Puja"
|
||||
|
||||
#: web/templates/admin/media/picker.gohtml:44
|
||||
#: web/templates/admin/media/picker.gohtml:47
|
||||
msgctxt "title"
|
||||
msgid "Choose Existing Media"
|
||||
msgstr "Elecció d’un mèdia existent"
|
||||
|
||||
#: web/templates/admin/media/picker.gohtml:55
|
||||
#: web/templates/admin/media/picker.gohtml:58
|
||||
#: web/templates/admin/media/index.gohtml:21
|
||||
msgid "No media uploaded yet."
|
||||
msgstr "No s’ha pujat cap mèdia encara."
|
||||
|
||||
#: web/templates/admin/media/picker.gohtml:58
|
||||
#: web/templates/admin/media/picker.gohtml:61
|
||||
msgctxt "action"
|
||||
msgid "Cancel"
|
||||
msgstr "Canceŀla"
|
||||
|
@ -739,11 +739,11 @@ msgstr "No podeu deixar la imatge de portada en blanc."
|
|||
msgid "Cover image must be an image media type."
|
||||
msgstr "La imatge de portada ha de ser un mèdia de tipus imatge."
|
||||
|
||||
#: pkg/campsite/admin.go:218
|
||||
#: pkg/campsite/admin.go:226
|
||||
msgid "Selected campsite type is not valid."
|
||||
msgstr "El tipus d’allotjament escollit no és vàlid."
|
||||
|
||||
#: pkg/campsite/admin.go:219
|
||||
#: pkg/campsite/admin.go:227
|
||||
msgid "Label can not be empty."
|
||||
msgstr "No podeu deixar l’etiqueta en blanc."
|
||||
|
||||
|
|
38
po/es.po
38
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: 2023-09-22 02:16+0200\n"
|
||||
"POT-Creation-Date: 2023-09-24 03:04+0200\n"
|
||||
"PO-Revision-Date: 2023-07-22 23:46+0200\n"
|
||||
"Last-Translator: jordi fita mas <jordi@tandem.blog>\n"
|
||||
"Language-Team: Spanish <es@tp.org.es>\n"
|
||||
|
@ -217,7 +217,7 @@ msgid "New Campsite"
|
|||
msgstr "Nuevo alojamiento"
|
||||
|
||||
#: web/templates/admin/campsite/form.gohtml:38
|
||||
#: web/templates/admin/campsite/index.gohtml:20
|
||||
#: web/templates/admin/campsite/index.gohtml:21
|
||||
msgctxt "campsite"
|
||||
msgid "Active"
|
||||
msgstr "Activo"
|
||||
|
@ -238,7 +238,7 @@ msgstr "Etiqueta"
|
|||
|
||||
#: web/templates/admin/campsite/index.gohtml:6
|
||||
#: web/templates/admin/campsite/index.gohtml:13
|
||||
#: web/templates/admin/layout.gohtml:70
|
||||
#: web/templates/admin/layout.gohtml:52 web/templates/admin/layout.gohtml:73
|
||||
msgctxt "title"
|
||||
msgid "Campsites"
|
||||
msgstr "Alojamientos"
|
||||
|
@ -248,29 +248,29 @@ msgctxt "action"
|
|||
msgid "Add Campsite"
|
||||
msgstr "Añadir alojamiento"
|
||||
|
||||
#: web/templates/admin/campsite/index.gohtml:18
|
||||
#: web/templates/admin/campsite/index.gohtml:19
|
||||
msgctxt "header"
|
||||
msgid "Label"
|
||||
msgstr "Etiqueta"
|
||||
|
||||
#: web/templates/admin/campsite/index.gohtml:19
|
||||
#: web/templates/admin/campsite/index.gohtml:20
|
||||
msgctxt "header"
|
||||
msgid "Type"
|
||||
msgstr "Tipo"
|
||||
|
||||
#: web/templates/admin/campsite/index.gohtml:28
|
||||
#: web/templates/admin/campsite/index.gohtml:29
|
||||
#: web/templates/admin/campsite/type/index.gohtml:36
|
||||
#: web/templates/admin/season/index.gohtml:32
|
||||
msgid "Yes"
|
||||
msgstr "Sí"
|
||||
|
||||
#: web/templates/admin/campsite/index.gohtml:28
|
||||
#: web/templates/admin/campsite/index.gohtml:29
|
||||
#: web/templates/admin/campsite/type/index.gohtml:36
|
||||
#: web/templates/admin/season/index.gohtml:32
|
||||
msgid "No"
|
||||
msgstr "No"
|
||||
|
||||
#: web/templates/admin/campsite/index.gohtml:34
|
||||
#: web/templates/admin/campsite/index.gohtml:35
|
||||
msgid "No campsites added yet."
|
||||
msgstr "No se ha añadido ningún alojamiento todavía."
|
||||
|
||||
|
@ -308,7 +308,7 @@ msgstr "Descripción"
|
|||
|
||||
#: web/templates/admin/campsite/type/index.gohtml:6
|
||||
#: web/templates/admin/campsite/type/index.gohtml:13
|
||||
#: web/templates/admin/layout.gohtml:67
|
||||
#: web/templates/admin/layout.gohtml:70
|
||||
msgctxt "title"
|
||||
msgid "Campsite Types"
|
||||
msgstr "Tipos de alojamientos"
|
||||
|
@ -366,7 +366,7 @@ msgstr "Color"
|
|||
|
||||
#: web/templates/admin/season/index.gohtml:6
|
||||
#: web/templates/admin/season/index.gohtml:13
|
||||
#: web/templates/admin/layout.gohtml:73
|
||||
#: web/templates/admin/layout.gohtml:76
|
||||
msgctxt "title"
|
||||
msgid "Seasons"
|
||||
msgstr "Temporadas"
|
||||
|
@ -413,7 +413,7 @@ msgid "Login"
|
|||
msgstr "Entrar"
|
||||
|
||||
#: web/templates/admin/services/index.gohtml:6
|
||||
#: web/templates/admin/layout.gohtml:79
|
||||
#: web/templates/admin/layout.gohtml:82
|
||||
msgctxt "title"
|
||||
msgid "Services Page"
|
||||
msgstr "Página de servicios"
|
||||
|
@ -493,7 +493,7 @@ msgstr "Guardar los cambios"
|
|||
|
||||
#: web/templates/admin/taxDetails.gohtml:6
|
||||
#: web/templates/admin/taxDetails.gohtml:13
|
||||
#: web/templates/admin/layout.gohtml:64
|
||||
#: web/templates/admin/layout.gohtml:67
|
||||
msgctxt "title"
|
||||
msgid "Tax Details"
|
||||
msgstr "Configuración fiscal"
|
||||
|
@ -579,12 +579,12 @@ msgctxt "action"
|
|||
msgid "Logout"
|
||||
msgstr "Salir"
|
||||
|
||||
#: web/templates/admin/layout.gohtml:76 web/templates/admin/home/index.gohtml:6
|
||||
#: web/templates/admin/layout.gohtml:79 web/templates/admin/home/index.gohtml:6
|
||||
msgctxt "title"
|
||||
msgid "Home Page"
|
||||
msgstr "Página de inicio"
|
||||
|
||||
#: web/templates/admin/layout.gohtml:82
|
||||
#: web/templates/admin/layout.gohtml:85
|
||||
#: web/templates/admin/media/index.gohtml:6
|
||||
#: web/templates/admin/media/index.gohtml:12
|
||||
msgctxt "title"
|
||||
|
@ -619,17 +619,17 @@ msgctxt "action"
|
|||
msgid "Upload"
|
||||
msgstr "Subir"
|
||||
|
||||
#: web/templates/admin/media/picker.gohtml:44
|
||||
#: web/templates/admin/media/picker.gohtml:47
|
||||
msgctxt "title"
|
||||
msgid "Choose Existing Media"
|
||||
msgstr "Elección de un medio existente"
|
||||
|
||||
#: web/templates/admin/media/picker.gohtml:55
|
||||
#: web/templates/admin/media/picker.gohtml:58
|
||||
#: web/templates/admin/media/index.gohtml:21
|
||||
msgid "No media uploaded yet."
|
||||
msgstr "No se ha subido ningún medio todavía."
|
||||
|
||||
#: web/templates/admin/media/picker.gohtml:58
|
||||
#: web/templates/admin/media/picker.gohtml:61
|
||||
msgctxt "action"
|
||||
msgid "Cancel"
|
||||
msgstr "Cancelar"
|
||||
|
@ -739,11 +739,11 @@ msgstr "No podéis dejar la imagen de portada en blanco."
|
|||
msgid "Cover image must be an image media type."
|
||||
msgstr "La imagen de portada tiene que ser un medio de tipo imagen."
|
||||
|
||||
#: pkg/campsite/admin.go:218
|
||||
#: pkg/campsite/admin.go:226
|
||||
msgid "Selected campsite type is not valid."
|
||||
msgstr "El tipo de alojamiento escogido no es válido."
|
||||
|
||||
#: pkg/campsite/admin.go:219
|
||||
#: pkg/campsite/admin.go:227
|
||||
msgid "Label can not be empty."
|
||||
msgstr "No podéis dejar la etiqueta en blanco."
|
||||
|
||||
|
|
|
@ -2,6 +2,6 @@
|
|||
|
||||
begin;
|
||||
|
||||
drop function if exists camper.edit_campsite(uuid, integer, text, boolean);
|
||||
drop function if exists camper.edit_campsite(integer, integer, text, boolean);
|
||||
|
||||
commit;
|
||||
|
|
|
@ -11,7 +11,7 @@ select plan(14);
|
|||
|
||||
select has_function('camper', 'add_campsite', array ['integer', 'text']);
|
||||
select function_lang_is('camper', 'add_campsite', array ['integer', 'text'], 'plpgsql');
|
||||
select function_returns('camper', 'add_campsite', array ['integer', 'text'], 'uuid');
|
||||
select function_returns('camper', 'add_campsite', array ['integer', 'text'], 'integer');
|
||||
select isnt_definer('camper', 'add_campsite', array ['integer', 'text']);
|
||||
select volatility_is('camper', 'add_campsite', array ['integer', 'text'], 'volatile');
|
||||
select function_privs_are('camper', 'add_campsite', array ['integer', 'text'], 'guest', array[]::text[]);
|
||||
|
|
|
@ -5,12 +5,13 @@ reset client_min_messages;
|
|||
|
||||
begin;
|
||||
|
||||
select plan(58);
|
||||
select plan(53);
|
||||
|
||||
set search_path to camper, public;
|
||||
|
||||
select has_table('campsite');
|
||||
select has_pk('campsite');
|
||||
select col_is_unique('campsite', array['company_id', 'label']);
|
||||
select table_privs_are('campsite', 'guest', array['SELECT']);
|
||||
select table_privs_are('campsite', 'employee', array['SELECT']);
|
||||
select table_privs_are('campsite', 'admin', array['SELECT', 'INSERT', 'UPDATE', 'DELETE']);
|
||||
|
@ -36,13 +37,6 @@ select col_type_is('campsite', 'company_id', 'integer');
|
|||
select col_not_null('campsite', 'company_id');
|
||||
select col_hasnt_default('campsite', 'company_id');
|
||||
|
||||
select has_column('campsite', 'slug');
|
||||
select col_is_unique('campsite', 'slug');
|
||||
select col_type_is('campsite', 'slug', 'uuid');
|
||||
select col_not_null('campsite', 'slug');
|
||||
select col_has_default('campsite', 'slug');
|
||||
select col_default_is('campsite', 'slug', 'gen_random_uuid()');
|
||||
|
||||
select has_column('campsite', 'campsite_type_id');
|
||||
select col_is_fk('campsite', 'campsite_type_id');
|
||||
select fk_ok('campsite', 'campsite_type_id', 'campsite_type', 'campsite_type_id');
|
||||
|
|
|
@ -9,15 +9,15 @@ set search_path to camper, public;
|
|||
|
||||
select plan(12);
|
||||
|
||||
select has_function('camper', 'edit_campsite', array ['uuid', 'integer', 'text', 'boolean']);
|
||||
select function_lang_is('camper', 'edit_campsite', array ['uuid', 'integer', 'text', 'boolean'], 'sql');
|
||||
select function_returns('camper', 'edit_campsite', array ['uuid', 'integer', 'text', 'boolean'], 'uuid');
|
||||
select isnt_definer('camper', 'edit_campsite', array ['uuid', 'integer', 'text', 'boolean']);
|
||||
select volatility_is('camper', 'edit_campsite', array ['uuid', 'integer', 'text', 'boolean'], 'volatile');
|
||||
select function_privs_are('camper', 'edit_campsite', array ['uuid', 'integer', 'text', 'boolean'], 'guest', array[]::text[]);
|
||||
select function_privs_are('camper', 'edit_campsite', array ['uuid', 'integer', 'text', 'boolean'], 'employee', array[]::text[]);
|
||||
select function_privs_are('camper', 'edit_campsite', array ['uuid', 'integer', 'text', 'boolean'], 'admin', array['EXECUTE']);
|
||||
select function_privs_are('camper', 'edit_campsite', array ['uuid', 'integer', 'text', 'boolean'], 'authenticator', array[]::text[]);
|
||||
select has_function('camper', 'edit_campsite', array ['integer', 'integer', 'text', 'boolean']);
|
||||
select function_lang_is('camper', 'edit_campsite', array ['integer', 'integer', 'text', 'boolean'], 'sql');
|
||||
select function_returns('camper', 'edit_campsite', array ['integer', 'integer', 'text', 'boolean'], 'integer');
|
||||
select isnt_definer('camper', 'edit_campsite', array ['integer', 'integer', 'text', 'boolean']);
|
||||
select volatility_is('camper', 'edit_campsite', array ['integer', 'integer', 'text', 'boolean'], 'volatile');
|
||||
select function_privs_are('camper', 'edit_campsite', array ['integer', 'integer', 'text', 'boolean'], 'guest', array[]::text[]);
|
||||
select function_privs_are('camper', 'edit_campsite', array ['integer', 'integer', 'text', 'boolean'], 'employee', array[]::text[]);
|
||||
select function_privs_are('camper', 'edit_campsite', array ['integer', 'integer', 'text', 'boolean'], 'admin', array['EXECUTE']);
|
||||
select function_privs_are('camper', 'edit_campsite', array ['integer', 'integer', 'text', 'boolean'], 'authenticator', array[]::text[]);
|
||||
|
||||
set client_min_messages to warning;
|
||||
truncate campsite cascade;
|
||||
|
@ -46,25 +46,25 @@ values (11, 1, 3, 'Type A')
|
|||
, (13, 1, 3, 'Type C')
|
||||
;
|
||||
|
||||
insert into campsite (company_id, campsite_type_id, slug, label, active)
|
||||
values (1, 11, '87452b88-b48f-48d3-bb6c-0296de64164e', 'A1', true)
|
||||
, (1, 12, '9b6370f7-f941-46f2-bc6e-de455675bd0a', 'B1', false)
|
||||
insert into campsite (campsite_id, company_id, campsite_type_id, label, active)
|
||||
values (21, 1, 11, 'A1', true)
|
||||
, (22, 1, 12, 'B1', false)
|
||||
;
|
||||
|
||||
select lives_ok(
|
||||
$$ select edit_campsite('87452b88-b48f-48d3-bb6c-0296de64164e', 13, 'C1', false) $$,
|
||||
$$ select edit_campsite(21, 13, 'C1', false) $$,
|
||||
'Should be able to edit the first campsite.'
|
||||
);
|
||||
|
||||
select lives_ok(
|
||||
$$ select edit_campsite('9b6370f7-f941-46f2-bc6e-de455675bd0a', 12, 'B2', true) $$,
|
||||
$$ select edit_campsite(22, 12, 'B2', true) $$,
|
||||
'Should be able to edit the second campsite.'
|
||||
);
|
||||
|
||||
select bag_eq(
|
||||
$$ select slug::text, campsite_type_id, label, active from campsite $$,
|
||||
$$ values ('87452b88-b48f-48d3-bb6c-0296de64164e', 13, 'C1', false)
|
||||
, ('9b6370f7-f941-46f2-bc6e-de455675bd0a', 12, 'B2', true)
|
||||
$$ select campsite_id, campsite_type_id, label, active from campsite $$,
|
||||
$$ values (21, 13, 'C1', false)
|
||||
, (22, 12, 'B2', true)
|
||||
$$,
|
||||
'Should have updated all campsites.'
|
||||
);
|
||||
|
|
|
@ -4,9 +4,8 @@ begin;
|
|||
|
||||
select campsite_id
|
||||
, company_id
|
||||
, slug
|
||||
, campsite_type_id
|
||||
, label
|
||||
, campsite_type_id
|
||||
, active
|
||||
from camper.campsite
|
||||
where false;
|
||||
|
|
|
@ -2,6 +2,6 @@
|
|||
|
||||
begin;
|
||||
|
||||
select has_function_privilege('camper.edit_campsite(uuid, integer, text, boolean)', 'execute');
|
||||
select has_function_privilege('camper.edit_campsite(integer, integer, text, boolean)', 'execute');
|
||||
|
||||
rollback;
|
||||
|
|
|
@ -89,3 +89,11 @@ a.missing-translation {
|
|||
.media-picker footer {
|
||||
bottom: -1em;
|
||||
}
|
||||
|
||||
#campsite-map .guest-only {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#campsite-map a:hover {
|
||||
fill: #ffeeaa;
|
||||
}
|
||||
|
|
|
@ -135,6 +135,22 @@ function camperUploadForm(el) {
|
|||
});
|
||||
}
|
||||
|
||||
export function setupCampsiteMap(map) {
|
||||
if (!map) {
|
||||
return;
|
||||
}
|
||||
for (const lodge of Array.from(map.querySelectorAll('.lodge'))) {
|
||||
const label = lodge.getAttribute('camper:lodge');
|
||||
if (!label) {
|
||||
continue;
|
||||
}
|
||||
const link = document.createElementNS('http://www.w3.org/2000/svg', 'a');
|
||||
link.setAttributeNS('http://www.w3.org/1999/xlink', 'href', '/admin/campsites/' + label);
|
||||
link.append(...lodge.childNodes);
|
||||
lodge.appendChild(link);
|
||||
}
|
||||
}
|
||||
|
||||
htmx.onLoad((target) => {
|
||||
if (target.tagName === 'DIALOG') {
|
||||
target.showModal();
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
-->
|
||||
{{ define "title" -}}
|
||||
{{- /*gotype: dev.tandem.ws/tandem/camper/pkg/campsite.campsiteForm*/ -}}
|
||||
{{ if .Slug}}
|
||||
{{ if .ID }}
|
||||
{{( pgettext "Edit Campsite" "title" )}}
|
||||
{{ else }}
|
||||
{{( pgettext "New Campsite" "title" )}}
|
||||
|
@ -15,14 +15,14 @@
|
|||
{{- /*gotype: dev.tandem.ws/tandem/camper/pkg/campsite.campsiteForm*/ -}}
|
||||
{{ template "settings-tabs" "campsites" }}
|
||||
<form
|
||||
{{ if .Slug }}
|
||||
data-hx-put="/admin/campsites/{{ .Slug }}"
|
||||
{{ if .ID }}
|
||||
data-hx-put="/admin/campsites/{{ .CurrentLabel }}"
|
||||
{{ else }}
|
||||
action="/admin/campsites" method="post"
|
||||
{{ end }}
|
||||
>
|
||||
<h2>
|
||||
{{ if .Slug }}
|
||||
{{ if .ID }}
|
||||
{{( pgettext "Edit Campsite" "title" )}}
|
||||
{{ else }}
|
||||
{{( pgettext "New Campsite" "title" )}}
|
||||
|
@ -30,7 +30,7 @@
|
|||
</h2>
|
||||
{{ CSRFInput }}
|
||||
<fieldset>
|
||||
{{ if .Slug }}
|
||||
{{ if .ID }}
|
||||
{{ with .Active -}}
|
||||
<label>
|
||||
<input type="checkbox" name="{{ .Name }}" {{ if .Checked}}checked{{ end }}
|
||||
|
@ -48,7 +48,7 @@
|
|||
<select name="{{ .Name }}"
|
||||
required
|
||||
{{ template "error-attrs" . }}>
|
||||
{{ if not $.Slug }}
|
||||
{{ if not $.ID }}
|
||||
<option value="">{{( gettext "Select campsite type" )}}</option>
|
||||
{{ end }}
|
||||
{{ template "list-options" . }}
|
||||
|
@ -67,7 +67,7 @@
|
|||
</fieldset>
|
||||
<footer>
|
||||
<button type="submit">
|
||||
{{ if .Slug }}
|
||||
{{ if .ID }}
|
||||
{{( pgettext "Update" "action" )}}
|
||||
{{ else }}
|
||||
{{( pgettext "Add" "action" )}}
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
{{ template "settings-tabs" "campsites" }}
|
||||
<a href="/admin/campsites/new">{{( pgettext "Add Campsite" "action" )}}</a>
|
||||
<h2>{{( pgettext "Campsites" "title" )}}</h2>
|
||||
{{ template "campsite_map.svg" }}
|
||||
{{ if .Campsites -}}
|
||||
<table>
|
||||
<thead>
|
||||
|
@ -23,7 +24,7 @@
|
|||
<tbody>
|
||||
{{ range .Campsites -}}
|
||||
<tr>
|
||||
<td><a href="/admin/campsites/{{ .Slug }}">{{ .Label }}</a></td>
|
||||
<td><a href="/admin/campsites/{{ .Label }}">{{ .Label }}</a></td>
|
||||
<td>{{ .Type }}</td>
|
||||
<td>{{ if .Active }}{{( gettext "Yes" )}}{{ else }}{{( gettext "No" )}}{{ end }}</td>
|
||||
</tr>
|
||||
|
@ -33,4 +34,9 @@
|
|||
{{ else -}}
|
||||
<p>{{( gettext "No campsites added yet." )}}</p>
|
||||
{{- end }}
|
||||
|
||||
<script type="module">
|
||||
import {setupCampsiteMap} from "/static/camper.js";
|
||||
setupCampsiteMap(document.getElementById('campsite-map'));
|
||||
</script>
|
||||
{{- end }}
|
||||
|
|
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 245 KiB |
Loading…
Reference in New Issue