camper/web/templates/public/home.gohtml

105 lines
4.6 KiB
Plaintext
Raw Normal View History

<!--
SPDX-FileCopyrightText: 2023 jordi fita mas <jordi@tandem.blog>
SPDX-License-Identifier: AGPL-3.0-only
-->
{{ define "title" -}}
Split templates and handlers into admin and public I need to check that the user is an employee (or admin) in administration handlers, but i do not want to do it for each handler, because i am bound to forget it. Thus, i added the /admin sub-path for these resources. The public-facing web is the rest of the resources outside /admin, but for now there is only home, to test whether it works as expected or not. The public-facing web can not relay on the user’s language settings, as the guest user has no way to set that. I would be happy to just use the Accept-Language header for that, but apparently Google does not use that header[0], and they give four alternatives: a country-specific domain, a subdomain with a generic top-level domain (gTLD), subdirectories with a gTLD, or URL parameters (e.g., site.com?loc=de). Of the four, Google does not recommend URL parameters, and the customer is already using subdirectories with the current site, therefor that’s what i have chosen. Google also tells me that it is a very good idea to have links between localized version of the same resources, either with <link> elements, Link HTTP response headers, or a sitemap file[1]; they are all equivalent in the eyes of Google. I have choosen the Link response headers way, because for that i can simply “augment” ResponseHeader to automatically add these headers when the response status is 2xx, otherwise i would need to pass down the original URL path until it reaches the template. Even though Camper is supposed to be a “generic”, multi-company application, i think i will stick to the easiest route and write the templates for just the “first” customer. [0]: https://developers.google.com/search/docs/specialty/international/managing-multi-regional-sites [1]: https://developers.google.com/search/docs/specialty/international/localized-versions
2023-08-05 01:42:37 +00:00
{{( pgettext "Home" "title" )}}
{{- end }}
{{ define "head" -}}
<link rel="stylesheet" media="screen" href="/static/slick@1.8.1.css">
{{- end }}
{{ define "content" -}}
Add cover media to campsite types This is the image that is shown at the home page, and maybe other pages in the future. We can not use a static file because this image can be changed by the customer, not us; just like name and description. I decided to keep the actual media content in the database, but to copy this file out to the file system the first time it is accessed. This is because we are going to replicate the database to a public instance that must show exactly the same image, but the customer will update the image from the private instance, behind a firewall. We could also synchronize the folder where they upload the images, the same way we will replicate, but i thought that i would make the whole thing a little more brittle: this way if it can replicate the update of the media, it is impossible to not have its contents; dumping it to a file is to improve subsequent requests to the same media. I use the hex representation of the media’s hash as the URL to the resource, because PostgreSQL’s base64 is not URL save (i.e., it uses RFC2045’s charset that includes the forward slash[0]), and i did not feel necessary write a new function just to slightly reduce the URLs’ length. Before checking if the file exists, i make sure that the given hash is an hex string, like i do for UUID, otherwise any other check is going to fail for sure. I moved out hex.Valid function from UUID to check for valid hex values, but the actual hash check is inside app/media because i doubt it will be used outside that module. [0]: https://datatracker.ietf.org/doc/html/rfc2045#section-6.8
2023-09-10 01:04:18 +00:00
{{- /*gotype: dev.tandem.ws/tandem/camper/pkg/app.homePage*/ -}}
<section class="nature">
<div style="--background-image:url('/static/images/todd-trapani-5LHzBpiTuzQ-unsplash.jpg')">
<h2>{{ (gettext "The pleasure of camping in the middle of nature…")}}</h2>
<a href="/{{ currentLocale }}/booking">{{( pgettext "Booking" "link" )}} <span>→</span></a>
</div>
Add cover media to campsite types This is the image that is shown at the home page, and maybe other pages in the future. We can not use a static file because this image can be changed by the customer, not us; just like name and description. I decided to keep the actual media content in the database, but to copy this file out to the file system the first time it is accessed. This is because we are going to replicate the database to a public instance that must show exactly the same image, but the customer will update the image from the private instance, behind a firewall. We could also synchronize the folder where they upload the images, the same way we will replicate, but i thought that i would make the whole thing a little more brittle: this way if it can replicate the update of the media, it is impossible to not have its contents; dumping it to a file is to improve subsequent requests to the same media. I use the hex representation of the media’s hash as the URL to the resource, because PostgreSQL’s base64 is not URL save (i.e., it uses RFC2045’s charset that includes the forward slash[0]), and i did not feel necessary write a new function just to slightly reduce the URLs’ length. Before checking if the file exists, i make sure that the given hash is an hex string, like i do for UUID, otherwise any other check is going to fail for sure. I moved out hex.Valid function from UUID to check for valid hex values, but the actual hash check is inside app/media because i doubt it will be used outside that module. [0]: https://datatracker.ietf.org/doc/html/rfc2045#section-6.8
2023-09-10 01:04:18 +00:00
{{ with .CampsiteTypes -}}
<div>
{{ range . -}}
Add cover media to campsite types This is the image that is shown at the home page, and maybe other pages in the future. We can not use a static file because this image can be changed by the customer, not us; just like name and description. I decided to keep the actual media content in the database, but to copy this file out to the file system the first time it is accessed. This is because we are going to replicate the database to a public instance that must show exactly the same image, but the customer will update the image from the private instance, behind a firewall. We could also synchronize the folder where they upload the images, the same way we will replicate, but i thought that i would make the whole thing a little more brittle: this way if it can replicate the update of the media, it is impossible to not have its contents; dumping it to a file is to improve subsequent requests to the same media. I use the hex representation of the media’s hash as the URL to the resource, because PostgreSQL’s base64 is not URL save (i.e., it uses RFC2045’s charset that includes the forward slash[0]), and i did not feel necessary write a new function just to slightly reduce the URLs’ length. Before checking if the file exists, i make sure that the given hash is an hex string, like i do for UUID, otherwise any other check is going to fail for sure. I moved out hex.Valid function from UUID to check for valid hex values, but the actual hash check is inside app/media because i doubt it will be used outside that module. [0]: https://datatracker.ietf.org/doc/html/rfc2045#section-6.8
2023-09-10 01:04:18 +00:00
<section style="--background-image:url('{{ .Media }}')">
<h3><a href="{{ .HRef }}"><span>{{ .Label }}</span></a></h3>
</section>
{{- end }}
</div>
{{- end }}
</section>
<section class="services">
<h2><a href="/{{ currentLocale }}/services">{{( gettext "Our services")}} <span>→</span></a></h2>
</section>
<section class="surroundings">
<h2 class="sr-only">{{ (gettext "Surroundings")}}</h2>
<div>
<div class="spiel">
<p>{{(gettext "Located in <strong>Alta Garrotxa</strong>, between the <strong>Pyrenees</strong> and the <strong>Costa Brava</strong>.") | raw}}</p>
<p>{{(gettext "Nearby there are the <strong>gorges of Sadernes</strong>, <strong>volcanoes</strong>, <strong>La Fageda den Jordà</strong>, the Jewish quarter of <strong>Besalú</strong>, the basaltic cliff of <strong>Castellfollit de la Roca</strong>… much to see and much to do.") | raw}}</p>
<p>{{(gettext "Less than an hour from <strong>Girona</strong>, one from <strong>La Bisbal dEmpordà</strong>, and two from <strong>Barcelona</strong>.") | raw}}</p>
<p><a href="/{{currentLocale}}/surroundings">{{( gettext "Discover the surroundings" )}} <span>→</span></a></p>
</div>
<figure>
<img src="/static/images/Volca_de_Santa_Margarida.jpg" alt=""/>
<figcaption>{{( gettext "Legend" )}}</figcaption>
</figure>
<figure>
<img src="/static/images/Gorga_fosca_Sadernes.jpg" alt=""/>
<figcaption>{{( gettext "Legend" )}}</figcaption>
</figure>
<figure>
<img src="/static/images/castellfolit_de_la_roca.jpg" alt=""/>
<figcaption>{{( gettext "Legend" )}}</figcaption>
</figure>
<figure>
<img src="/static/images/besalu.jpg" alt=""/>
<figcaption>{{( gettext "Legend" )}}</figcaption>
</figure>
<figure>
<img src="/static/images/santa_pau.jpg" alt=""/>
<figcaption>{{( gettext "Legend" )}}</figcaption>
</figure>
<figure>
<img src="/static/images/banyoles.jpg" alt=""/>
<figcaption>{{( gettext "Legend" )}}</figcaption>
</figure>
<figure>
<img src="/static/images/girn-a.jpg" alt=""/>
<figcaption>{{( gettext "Legend" )}}</figcaption>
</figure>
<figure>
<img src="/static/images/costa_brava.jpg" alt=""/>
<figcaption>{{( gettext "Legend" )}}</figcaption>
</figure>
<figure>
<img src="/static/images/barcelona-1.jpg" alt=""/>
<figcaption>{{( gettext "Legend" )}}</figcaption>
</figure>
</div>
</section>
<p class="enjoy">{{( gettext "Come and enjoy!")}}</p>
<script src="/static/jquery@3.7.1.min.js"></script>
<script src="/static/slick@1.8.1.min.js"></script>
<script>
jQuery(function () {
jQuery('.surroundings > div').slick({
slidesToShow: 2,
slidesToScroll: 1,
infinite: false,
arrows: true,
prevArrow: '<button type="button" class="slick-prev">←</button>',
nextArrow: '<button type="button" class="slick-next">→</button>',
responsive: [
{
breakpoint: 768,
settings: {
slidesToShow: 1,
}
},
]
});
});
</script>
{{- end }}