diff --git a/bin/check-content b/bin/check-content index d294481f..718f8bbf 100755 --- a/bin/check-content +++ b/bin/check-content @@ -17,6 +17,7 @@ import pathlib import re import struct import sys +import tomllib import yaml @@ -553,6 +554,43 @@ SECURITY_TXT = ROOT / "static" / ".well-known" / "security.txt" SECURITY_TXT_NOTICE_DAYS = 30 +CONFIG = ROOT / "config.toml" + +# The keys of [params.association] that only the Management Board can fill, +# and what each one is for. See the comment in config.toml. +ASSOCIATION_KEYS = { + "address": "the registered address, which LSSI-CE article 10 requires the " + "legal notice to publish", + "registry": "the entry in the Registre d'Associacions de la Generalitat " + "de Catalunya, which LSSI-CE article 10 requires too", +} + + +def check_association(): + """The legal notice reads who the association is from config.toml. + + Two of those facts are not a volunteer's to write: the registered address + and the entry in the register of associations. Should either be emptied, + this says so on every run rather than letting the legal notice go out + with a gap in the one section the law asks for. + + A warning and not an error: the site builds and serves fine without them, + and an error would turn every pull request red for a reason no + contributor can fix. The page that needs them is the gate. + """ + try: + with open(CONFIG, "rb") as handle: + config = tomllib.load(handle) + except (OSError, tomllib.TOMLDecodeError) as problem: + error(CONFIG, f"cannot be read: {problem}") + return + association = (config.get("params") or {}).get("association") or {} + for key, what in sorted(ASSOCIATION_KEYS.items()): + if not str(association.get(key, "")).strip(): + warn(CONFIG, f"params.association.{key} is empty. It is {what}. " + f"Only the Management Board can fill it.") + + def check_security_txt(): """Report a security.txt that has expired, or is about to. @@ -596,6 +634,7 @@ def main(): check_agenda() check_orphans(people, listed_people) check_security_txt() + check_association() for line in warnings: print(f"WARNING {line}") diff --git a/config.toml b/config.toml index 482bf2ca..6e801699 100644 --- a/config.toml +++ b/config.toml @@ -69,6 +69,30 @@ unsafe=true short_name = "PyBCN" extended_name = "The Barcelona Python Association" + # Who the association is in law. Spanish law 34/2002 (LSSI-CE) article 10 + # requires a site run by an association to publish its name, its address, + # an email, its entry in the register it is recorded in, and its tax + # number. The legal notice page is what shows them, and reads them from + # here rather than holding them in its own text, so that the association + # can correct a fact without a volunteer editing a page of legal prose. + # + # The values match the association's entry in the Registre d'Entitats de + # la Generalitat de Catalunya, which is public open data: + # https://analisi.transparenciacatalunya.cat/d/y6fz-g3ff + # Only the Management Board changes address, registry or registered_on: + # they describe the association as the register records it, not as + # volunteers know it. The register names the register itself, not only + # the number, because article 10 asks for the entry in the register and a + # bare number names no register. bin/check-content reports an empty + # address or registry as a warning. The legal notice page cannot be + # published while either is empty: the page is the one place the law + # asks for them, and a page that leaves them out does not do its job. + [params.association] + legal_name = "Associació Python Barcelona" + tax_id = "G67254045" + address = "Carrer de Concepció Arenal, 165, 08027 Barcelona" + registry = "Registre d'Associacions de la Generalitat de Catalunya, núm. 64158" + main_contact_name_pyladies = "PyLadiesBCN Organizers" main_contact_email_pyladies = "pyladies-bcn@googlegroups.com" diff --git a/content/pybcn_association/legal-notice.md b/content/pybcn_association/legal-notice.md new file mode 100644 index 00000000..952f9100 --- /dev/null +++ b/content/pybcn_association/legal-notice.md @@ -0,0 +1,57 @@ +--- +title: "Legal notice" +description: "Who runs pybcn.org, how to reach us, and the terms of use" +menu: + main: + parent: 'The association' +weight: 6 +aliases: +- /legal-notice + +layout: single +heroBackground: /images/photos/reg-desk-pyday-2019.jpg + +--- + +This website, [pybcn.org](https://pybcn.org), is run by **Associació Python Barcelona** (PyBCN), a non-profit association of volunteers who organise Python meetups and events in Barcelona. + +## Who we are + +{{< association-identity >}} + +The Management Board is responsible for this website. You can see who sits on it on the [Information](/pybcn_association/information/) page. + +## What this site is + +This is an informational site. It describes the association, its events, the people who organise them and speak at them, and how to join, propose a talk, or sponsor us. Nothing is sold through this site. The membership fee is paid on PayPal's own site, not here. Some pages embed a Google Form or a Google Calendar; those are served by Google. + +The site is a set of static pages, published from a public repository on GitHub and served by GitHub Pages. We keep no server of our own and we run no analytics. The [Privacy policy](/pybcn_association/privacy-policy/) says what personal data this involves. + +## Using the content + +- The text on this site is written by volunteers and belongs to the association. You can quote it with a link to the page. Ask us before you reuse more than that. +- The photographs and biographies on the people pages belong to the people shown. Do not reuse them without their permission. +- The logos of sponsors and partner organisations belong to their owners. +- The site code is in a [public repository](https://github.com/pybcn/pybcn.github.io) on GitHub. The theme is free software under the MIT licence. + +## Links to other sites + +We link to Meetup, YouTube, GitHub, LinkedIn, Google Docs, and to the sites of speakers and sponsors. We do not control those sites and we are not responsible for what they publish or how they treat your data. + +## Accuracy + +Volunteers maintain this site in their free time. We try to keep it correct and we fix errors when someone tells us. Event details can change after they are published: the Meetup event page is the one to trust for date, time, and venue. We cannot promise that the site is always available or free of errors. + +## Code of Conduct + +Our [Code of Conduct](/pybcn_association/coc/) applies to every space the association runs, online and in person. + +## Changes to this notice + +We may update this notice. Every change is visible in the [history of this page](https://github.com/pybcn/pybcn.github.io/commits/edition/content/pybcn_association/legal-notice.md) on GitHub. + +## Applicable law + +Spanish law applies to this notice and to the use of this site. Any dispute goes to the courts of Barcelona, unless the law gives you the right to the courts of your own domicile. + +Last updated: 2026-10-07 diff --git a/content/pybcn_association/privacy-policy.md b/content/pybcn_association/privacy-policy.md new file mode 100644 index 00000000..ba013441 --- /dev/null +++ b/content/pybcn_association/privacy-policy.md @@ -0,0 +1,97 @@ +--- +title: "Privacy policy" +description: "What personal data this site involves, why, and how to ask us to change or remove it" +menu: + main: + parent: 'The association' +weight: 7 +aliases: +- /privacy-policy + +layout: single +heroBackground: /images/photos/people-pyday-2019.jpg + +--- + +PyBCN is a volunteer association. This page says what personal data this website involves, why we have it, who else sees it, and how to ask us to change or remove it. We wrote it to be read, so it is short. If something is not covered here, ask us. + +## Who is responsible + +**Associació Python Barcelona** (CIF G67254045) is the data controller. + +- **Email**: [pybcn@googlegroups.com](mailto:pybcn@googlegroups.com) +- **Registered address**: *pending. The association must add its registered address here before this page is published.* + +The Management Board handles requests about personal data. We have no data protection officer: the law does not require one for an association of our size and activity. + +## What data this site involves, and why + +### People pages + +The site has pages for the people who organise our events, speak at them, mentor at workshops, or collaborate with the association. Each page shows a name, a photograph, a short biography, the role in PyBCN or at an event, and links to the person's own profiles (GitHub, LinkedIn, Twitter, personal site). + +- **Where it comes from**: the person. Each one sent the photograph and wrote or approved the text for publication here. Someone who did not want a photograph did not send one, and the page shows a silhouette instead. +- **Why we have it**: with the person's consent (GDPR article 6.1.a). You can withdraw it at any time, and we remove the page. Withdrawing consent does not affect what was published before. +- **How long we keep it**: until the person asks us to remove it, or until we take the page down ourselves because it is out of date. +- **One thing to know**: the source of this site is a public Git repository on GitHub. When we remove a page, it disappears from the site and from the current version of the repository. The old text remains in the repository history, as with any Git project. Tell us if you also want it gone from there and we will work it out with you. Copies kept by search engines and web archives are outside our control. + +### Forms + +A few pages link to or embed a Google Form: + +- the **membership form**, to become a member of the association; +- the **propose a talk** form, for a talk at a PyBCN meetup; +- the **PyLadies BCN call for proposals** form; +- the **call for proposals** of each PyDay BCN edition (workshops and lightning talks), and the speaker, mentor, and attendee forms of some workshops. + +Each form asks for what it needs to handle your request: usually your name, an email address to answer you, and the content of your proposal or your membership details. + +- **Where it goes**: into a Google Forms spreadsheet in a Google account run by the association's organizers. Google stores it under its own [privacy policy](https://policies.google.com/privacy). +- **Why we have it**: to do what you asked for, which is the membership agreement or the steps you take to propose a talk or join a workshop (GDPR article 6.1.b). +- **Who sees it**: the organizers of that event or working group. +- **How long we keep it**: responses to an event form are needed until the event is over and its programme is published. We have no automatic deletion after that. Ask us and we delete your response. Membership data stays in the member register for as long as you are a member; the law requires associations to keep that register and the related accounting records for some years after. + +### Membership payments + +The membership fee is paid on [PayPal](https://www.paypal.com)'s site through a Subscribe button. PayPal tells us your name, your email address, and the amount paid. We never see your card or bank details. PayPal is a separate controller under its own [privacy statement](https://www.paypal.com/es/legalhub/privacy-full). We keep the payment record because the accounting and tax rules require it. + +### Email + +Our contact addresses, such as pybcn@googlegroups.com and pyladies-bcn@googlegroups.com, are Google Groups. A message you send there is stored in the group and read by the organizers who are members of that group. We use it to answer you and to follow up on what you asked (GDPR article 6.1.b and 6.1.f). The thread stays in the group archive; ask us and we delete it. + +### Embedded Google content + +A few pages embed a Google Form or a Google Calendar in a frame. The frame is served by Google: when the page loads, Google sees your IP address and browser details, and may set its own cookies inside the frame. Google's [privacy policy](https://policies.google.com/privacy) applies to that. + +### Cookies + +This site sets no cookies of its own, and runs no analytics or tracking scripts. Your browser also loads a few images from unsplash.com (page headers) and paypalobjects.com (the PayPal button). Like any image host, those servers see your IP address and browser details. + +### Hosting + +The site is served by [GitHub Pages](https://pages.github.com). GitHub may log the IP address and request details of each visit for security and operation, under the [GitHub privacy statement](https://docs.github.com/en/site-policy/privacy-policies/github-general-privacy-statement). We do not see or receive those logs. + +## Who else sees your data + +Nobody buys or receives your data from us. The companies named above see it because we use their services: Google (forms, calendar, mailing lists, documents), PayPal (payments), and GitHub (hosting and the source repository). All three are based in the USA. Each publishes the safeguards it applies to data from the EU, and we rely on those. + +## Your rights + +You can ask us to: + +- see the data we hold about you (access); +- correct it (rectification); +- delete it (erasure), including a whole people page; +- limit how we use it (restriction), or object to a use (objection); +- give it to you in a usable format (portability); +- withdraw your consent, for a people page or anything else. + +To do so, write to [pybcn@googlegroups.com](mailto:pybcn@googlegroups.com). Say what you want and which page or form it concerns. For a people page, write from the email address or one of the profiles linked on the page, so we know it is you. The law gives us one month to answer. We do it by hand, as volunteers, so a few days is normal. + +If you think we handle your data wrongly, you can complain to the Spanish data protection authority, the [Agencia Española de Protección de Datos](https://www.aepd.es). + +## Changes to this policy + +We may update this policy. Every change is visible in the [history of this page](https://github.com/pybcn/pybcn.github.io/commits/edition/content/pybcn_association/privacy-policy.md) on GitHub. + +Last updated: 2026-10-07 diff --git a/layouts/shortcodes/association-identity.html b/layouts/shortcodes/association-identity.html new file mode 100644 index 00000000..70db41d9 --- /dev/null +++ b/layouts/shortcodes/association-identity.html @@ -0,0 +1,29 @@ +{{- /* + Who the association is in law, as a list, for the legal notice. + + Takes no argument. Everything comes from [params.association] in + config.toml and from the main contact email beside it. + + Spanish law 34/2002, LSSI-CE article 10, asks a site run by an + association for its name, its address, an email, its entry in the + register it is recorded in, and its tax number. They are read from the + configuration and not written into the page, so the association can + correct one of them without a volunteer editing a page of legal prose. + The registration date is not asked for; it goes on the registry line + when it is set, because it is what the register itself prints. + See the comment on [params.association] for the rest of the reasoning. + + A value that is empty prints as a line that says so, in the page, rather + than as a missing bullet. A missing bullet reads as a page that never + claimed to carry the fact; a line that says the fact is missing is the + page admitting it does not yet do its job. bin/check-content warns about + the same two keys on every run. +*/ -}} +{{- $a := site.Params.association -}} + diff --git a/themes/pybcn_theme/README.md b/themes/pybcn_theme/README.md index 82ee70f3..4a6a874f 100644 --- a/themes/pybcn_theme/README.md +++ b/themes/pybcn_theme/README.md @@ -11,7 +11,6 @@ Based on https://github.com/alanorth/hugo-theme-bootstrap4-blog - Supports Google, Bing, and Yandex site verification via meta tags - Supports Google Analytics (async version), see [Hugo docs](https://gohugo.io/extras/analytics/) - Supports Disqus comments, see [Hugo docs](https://gohugo.io/extras/comments/) -- Can show a message about cookie usage to the user, see [`exampleSite/config.toml`](https://github.com/alanorth/hugo-theme-bootstrap4-blog/blob/master/exampleSite/config.toml) - Allow addition of custom `` code in site's `layouts/partials/head-custom.html` (see [#17](https://github.com/alanorth/hugo-theme-bootstrap4-blog/pull/17)) - Configurable display of summaries of content in list templates. - Configurable keywords for every post diff --git a/themes/pybcn_theme/assets/css/cookieconsent.min.css b/themes/pybcn_theme/assets/css/cookieconsent.min.css deleted file mode 100644 index d4d43902..00000000 --- a/themes/pybcn_theme/assets/css/cookieconsent.min.css +++ /dev/null @@ -1,6 +0,0 @@ -.cc-window{opacity:1;-webkit-transition:opacity 1s ease;transition:opacity 1s ease}.cc-window.cc-invisible{opacity:0}.cc-animate.cc-revoke{-webkit-transition:transform 1s ease;-webkit-transition:-webkit-transform 1s ease;transition:-webkit-transform 1s ease;transition:transform 1s ease;transition:transform 1s ease,-webkit-transform 1s ease}.cc-animate.cc-revoke.cc-top{-webkit-transform:translateY(-2em);transform:translateY(-2em)}.cc-animate.cc-revoke.cc-bottom{-webkit-transform:translateY(2em);transform:translateY(2em)}.cc-animate.cc-revoke.cc-active.cc-top{-webkit-transform:translateY(0);transform:translateY(0)}.cc-animate.cc-revoke.cc-active.cc-bottom{-webkit-transform:translateY(0);transform:translateY(0)}.cc-revoke:hover{-webkit-transform:translateY(0);transform:translateY(0)}.cc-grower{max-height:0;overflow:hidden;-webkit-transition:max-height 1s;transition:max-height 1s} -.cc-revoke,.cc-window{position:fixed;overflow:hidden;-webkit-box-sizing:border-box;box-sizing:border-box;font-family:Helvetica,Calibri,Arial,sans-serif;font-size:16px;line-height:1.5em;display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:nowrap;flex-wrap:nowrap;z-index:9999}.cc-window.cc-static{position:static}.cc-window.cc-floating{padding:2em;max-width:24em;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.cc-window.cc-banner{padding:1em 1.8em;width:100%;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.cc-revoke{padding:.5em}.cc-revoke:hover{text-decoration:underline}.cc-header{font-size:18px;font-weight:700}.cc-btn,.cc-close,.cc-link,.cc-revoke{cursor:pointer}.cc-link{opacity:.8;display:inline-block;padding:.2em;text-decoration:underline}.cc-link:hover{opacity:1}.cc-link:active,.cc-link:visited{color:initial}.cc-btn{display:block;padding:.4em .8em;font-size:.9em;font-weight:700;border-width:2px;border-style:solid;text-align:center;white-space:nowrap}.cc-highlight .cc-btn:first-child{background-color:transparent;border-color:transparent}.cc-highlight .cc-btn:first-child:focus,.cc-highlight .cc-btn:first-child:hover{background-color:transparent;text-decoration:underline}.cc-close{display:block;position:absolute;top:.5em;right:.5em;font-size:1.6em;opacity:.9;line-height:.75}.cc-close:focus,.cc-close:hover{opacity:1} -.cc-revoke.cc-top{top:0;left:3em;border-bottom-left-radius:.5em;border-bottom-right-radius:.5em}.cc-revoke.cc-bottom{bottom:0;left:3em;border-top-left-radius:.5em;border-top-right-radius:.5em}.cc-revoke.cc-left{left:3em;right:unset}.cc-revoke.cc-right{right:3em;left:unset}.cc-top{top:1em}.cc-left{left:1em}.cc-right{right:1em}.cc-bottom{bottom:1em}.cc-floating>.cc-link{margin-bottom:1em}.cc-floating .cc-message{display:block;margin-bottom:1em}.cc-window.cc-floating .cc-compliance{-webkit-box-flex:1;-ms-flex:1 0 auto;flex:1 0 auto}.cc-window.cc-banner{-webkit-box-align:center;-ms-flex-align:center;align-items:center}.cc-banner.cc-top{left:0;right:0;top:0}.cc-banner.cc-bottom{left:0;right:0;bottom:0}.cc-banner .cc-message{display:block;-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;max-width:100%;margin-right:1em}.cc-compliance{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-ms-flex-line-pack:justify;align-content:space-between}.cc-floating .cc-compliance>.cc-btn{-webkit-box-flex:1;-ms-flex:1;flex:1}.cc-btn+.cc-btn{margin-left:.5em} -@media print{.cc-revoke,.cc-window{display:none}}@media screen and (max-width:900px){.cc-btn{white-space:normal}}@media screen and (max-width:414px) and (orientation:portrait),screen and (max-width:736px) and (orientation:landscape){.cc-window.cc-top{top:0}.cc-window.cc-bottom{bottom:0}.cc-window.cc-banner,.cc-window.cc-floating,.cc-window.cc-left,.cc-window.cc-right{left:0;right:0}.cc-window.cc-banner{-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.cc-window.cc-banner .cc-compliance{-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto}.cc-window.cc-floating{max-width:none}.cc-window .cc-message{margin-bottom:1em}.cc-window.cc-banner{-webkit-box-align:unset;-ms-flex-align:unset;align-items:unset}.cc-window.cc-banner .cc-message{margin-right:0}} -.cc-floating.cc-theme-classic{padding:1.2em;border-radius:5px}.cc-floating.cc-type-info.cc-theme-classic .cc-compliance{text-align:center;display:inline;-webkit-box-flex:0;-ms-flex:none;flex:none}.cc-theme-classic .cc-btn{border-radius:5px}.cc-theme-classic .cc-btn:last-child{min-width:140px}.cc-floating.cc-type-info.cc-theme-classic .cc-btn{display:inline-block} -.cc-theme-edgeless.cc-window{padding:0}.cc-floating.cc-theme-edgeless .cc-message{margin:2em;margin-bottom:1.5em}.cc-banner.cc-theme-edgeless .cc-btn{margin:0;padding:.8em 1.8em;height:100%}.cc-banner.cc-theme-edgeless .cc-message{margin-left:1em}.cc-floating.cc-theme-edgeless .cc-btn+.cc-btn{margin-left:0} \ No newline at end of file diff --git a/themes/pybcn_theme/assets/js/cookieconsent.min.js b/themes/pybcn_theme/assets/js/cookieconsent.min.js deleted file mode 100644 index 1e3dccf1..00000000 --- a/themes/pybcn_theme/assets/js/cookieconsent.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(e){if(!e.hasInitialised){var t={escapeRegExp:function(e){return e.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&")},hasClass:function(e,t){var i=" ";return 1===e.nodeType&&(i+e.className+i).replace(/[\n\t]/g,i).indexOf(i+t+i)>=0},addClass:function(e,t){e.className+=" "+t},removeClass:function(e,t){var i=new RegExp("\\b"+this.escapeRegExp(t)+"\\b");e.className=e.className.replace(i,"")},interpolateString:function(e,t){return e.replace(/{{([a-z][a-z0-9\-_]*)}}/gi,function(e){return t(arguments[1])||""})},getCookie:function(e){var t=("; "+document.cookie).split("; "+e+"=");return t.length<2?void 0:t.pop().split(";").shift()},setCookie:function(e,t,i,n,o,s){var r=new Date;r.setHours(r.getHours()+24*(i||365));var a=[e+"="+t,"expires="+r.toUTCString(),"path="+(o||"/")];n&&a.push("domain="+n),s&&a.push("secure"),document.cookie=a.join(";")},deepExtend:function(e,t){for(var i in t)t.hasOwnProperty(i)&&(i in e&&this.isPlainObject(e[i])&&this.isPlainObject(t[i])?this.deepExtend(e[i],t[i]):e[i]=t[i]);return e},throttle:function(e,t){var i=!1;return function(){i||(e.apply(this,arguments),i=!0,setTimeout(function(){i=!1},t))}},hash:function(e){var t,i,n=0;if(0===e.length)return n;for(t=0,i=e.length;t=128?"#000":"#fff"},getLuminance:function(e){var t=parseInt(this.normaliseHex(e),16),i=38+(t>>16),n=38+(t>>8&255),o=38+(255&t);return"#"+(16777216+65536*(i<255?i<1?0:i:255)+256*(n<255?n<1?0:n:255)+(o<255?o<1?0:o:255)).toString(16).slice(1)},isMobile:function(){return/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)},isPlainObject:function(e){return"object"==typeof e&&null!==e&&e.constructor==Object},traverseDOMPath:function(e,i){return e&&e.parentNode?t.hasClass(e,i)?e:this.traverseDOMPath(e.parentNode,i):null}};e.status={deny:"deny",allow:"allow",dismiss:"dismiss"},e.transitionEnd=function(){var e=document.createElement("div"),t={t:"transitionend",OT:"oTransitionEnd",msT:"MSTransitionEnd",MozT:"transitionend",WebkitT:"webkitTransitionEnd"};for(var i in t)if(t.hasOwnProperty(i)&&void 0!==e.style[i+"ransition"])return t[i];return""}(),e.hasTransition=!!e.transitionEnd;var i=Object.keys(e.status).map(t.escapeRegExp);e.customStyles={},e.Popup=function(){var n={enabled:!0,container:null,cookie:{name:"cookieconsent_status",path:"/",domain:"",expiryDays:365,secure:!1},onPopupOpen:function(){},onPopupClose:function(){},onInitialise:function(e){},onStatusChange:function(e,t){},onRevokeChoice:function(){},onNoCookieLaw:function(e,t){},content:{header:"Cookies used on the website!",message:"This website uses cookies to ensure you get the best experience on our website.",dismiss:"Got it!",allow:"Allow cookies",deny:"Decline",link:"Learn more",href:"https://www.cookiesandyou.com",close:"❌",target:"_blank",policy:"Cookie Policy"},elements:{header:'{{header}} ',message:'{{message}}',messagelink:'{{message}} {{link}}',dismiss:'{{dismiss}}',allow:'{{allow}}',deny:'{{deny}}',link:'{{link}}',close:'{{close}}'},window:'',revokeBtn:'
{{policy}}
',compliance:{info:'
{{dismiss}}
',"opt-in":'
{{deny}}{{allow}}
',"opt-out":'
{{deny}}{{allow}}
'},type:"info",layouts:{basic:"{{messagelink}}{{compliance}}","basic-close":"{{messagelink}}{{compliance}}{{close}}","basic-header":"{{header}}{{message}}{{link}}{{compliance}}"},layout:"basic",position:"bottom",theme:"block",static:!1,palette:null,revokable:!1,animateRevokable:!0,showLink:!0,dismissOnScroll:!1,dismissOnTimeout:!1,dismissOnWindowClick:!1,ignoreClicksFrom:["cc-revoke","cc-btn"],autoOpen:!0,autoAttach:!0,whitelistPage:[],blacklistPage:[],overrideHTML:null};function o(){this.initialise.apply(this,arguments)}function s(e){this.openingTimeout=null,t.removeClass(e,"cc-invisible")}function r(t){t.style.display="none",t.removeEventListener(e.transitionEnd,this.afterTransition),this.afterTransition=null}function a(){var e=this.options.position.split("-"),t=[];return e.forEach(function(e){t.push("cc-"+e)}),t}function c(n){var o=this.options,s=document.createElement("div"),r=o.container&&1===o.container.nodeType?o.container:document.body;s.innerHTML=n;var a=s.children[0];return a.style.display="none",t.hasClass(a,"cc-window")&&e.hasTransition&&t.addClass(a,"cc-invisible"),this.onButtonClick=function(n){var o=t.traverseDOMPath(n.target,"cc-btn")||n.target;if(t.hasClass(o,"cc-btn")){var s=o.className.match(new RegExp("\\bcc-("+i.join("|")+")\\b")),r=s&&s[1]||!1;r&&(this.setStatus(r),this.close(!0))}t.hasClass(o,"cc-close")&&(this.setStatus(e.status.dismiss),this.close(!0));t.hasClass(o,"cc-revoke")&&this.revokeChoice()}.bind(this),a.addEventListener("click",this.onButtonClick),o.autoAttach&&(r.firstChild?r.insertBefore(a,r.firstChild):r.appendChild(a)),a}function l(e){return"000000"==(e=t.normaliseHex(e))?"#222":t.getLuminance(e)}function u(e,t){for(var i=0,n=e.length;i=0;o&&t(n);return o}.call(this)&&(this.options.enabled=!1),u(this.options.blacklistPage,location.pathname)&&(this.options.enabled=!1),u(this.options.whitelistPage,location.pathname)&&(this.options.enabled=!0);var o=this.options.window.replace("{{classes}}",function(){var i=this.options,n="top"==i.position||"bottom"==i.position?"banner":"floating";t.isMobile()&&(n="floating");var o=["cc-"+n,"cc-type-"+i.type,"cc-theme-"+i.theme];i.static&&o.push("cc-static");o.push.apply(o,a.call(this));(function(i){var n=t.hash(JSON.stringify(i)),o="cc-color-override-"+n,s=t.isPlainObject(i);this.customStyleSelector=s?o:null,s&&function(i,n,o){if(e.customStyles[i])return void++e.customStyles[i].references;var s={},r=n.popup,a=n.button,c=n.highlight;r&&(r.text=r.text?r.text:t.getContrast(r.background),r.link=r.link?r.link:r.text,s[o+".cc-window"]=["color: "+r.text,"background-color: "+r.background],s[o+".cc-revoke"]=["color: "+r.text,"background-color: "+r.background],s[o+" .cc-link,"+o+" .cc-link:active,"+o+" .cc-link:visited"]=["color: "+r.link],a&&(a.text=a.text?a.text:t.getContrast(a.background),a.border=a.border?a.border:"transparent",s[o+" .cc-btn"]=["color: "+a.text,"border-color: "+a.border,"background-color: "+a.background],a.padding&&s[o+" .cc-btn"].push("padding: "+a.padding),"transparent"!=a.background&&(s[o+" .cc-btn:hover, "+o+" .cc-btn:focus"]=["background-color: "+(a.hover||l(a.background))]),c?(c.text=c.text?c.text:t.getContrast(c.background),c.border=c.border?c.border:"transparent",s[o+" .cc-highlight .cc-btn:first-child"]=["color: "+c.text,"border-color: "+c.border,"background-color: "+c.background]):s[o+" .cc-highlight .cc-btn:first-child"]=["color: "+r.text]));var u=document.createElement("style");document.head.appendChild(u),e.customStyles[i]={references:1,element:u.sheet};var h=-1;for(var p in s)s.hasOwnProperty(p)&&u.sheet.insertRule(p+"{"+s[p].join(";")+"}",++h)}(n,i,"."+o);return s}).call(this,this.options.palette);this.customStyleSelector&&o.push(this.customStyleSelector);return o}.call(this).join(" ")).replace("{{children}}",function(){var e={},i=this.options;i.showLink||(i.elements.link="",i.elements.messagelink=i.elements.message);Object.keys(i.elements).forEach(function(n){e[n]=t.interpolateString(i.elements[n],function(e){var t=i.content[e];return e&&"string"==typeof t&&t.length?t:""})});var n=i.compliance[i.type];n||(n=i.compliance.info);e.compliance=t.interpolateString(n,function(t){return e[t]});var o=i.layouts[i.layout];o||(o=i.layouts.basic);return t.interpolateString(o,function(t){return e[t]})}.call(this)),s=this.options.overrideHTML;if("string"==typeof s&&s.length&&(o=s),this.options.static){var r=c.call(this,'
'+o+"
");r.style.display="",this.element=r.firstChild,this.element.style.display="none",t.addClass(this.element,"cc-invisible")}else this.element=c.call(this,o);(function(){var i=this.setStatus.bind(this),n=this.close.bind(this),o=this.options.dismissOnTimeout;"number"==typeof o&&o>=0&&(this.dismissTimeout=window.setTimeout(function(){i(e.status.dismiss),n(!0)},Math.floor(o)));var s=this.options.dismissOnScroll;if("number"==typeof s&&s>=0){var r=function(t){window.pageYOffset>Math.floor(s)&&(i(e.status.dismiss),n(!0),window.removeEventListener("scroll",r),this.onWindowScroll=null)};this.options.enabled&&(this.onWindowScroll=r,window.addEventListener("scroll",r))}var a=this.options.dismissOnWindowClick,c=this.options.ignoreClicksFrom;if(a){var l=function(o){for(var s=!1,r=o.path.length,a=c.length,u=0;uo&&(i=!0),i?t.hasClass(n,"cc-active")||t.addClass(n,"cc-active"):t.hasClass(n,"cc-active")&&t.removeClass(n,"cc-active")},200);this.onMouseMove=o,window.addEventListener("mousemove",o)}}}.call(this),this.options.autoOpen&&this.autoOpen()},o.prototype.destroy=function(){this.onButtonClick&&this.element&&(this.element.removeEventListener("click",this.onButtonClick),this.onButtonClick=null),this.dismissTimeout&&(clearTimeout(this.dismissTimeout),this.dismissTimeout=null),this.onWindowScroll&&(window.removeEventListener("scroll",this.onWindowScroll),this.onWindowScroll=null),this.onWindowClick&&(window.removeEventListener("click",this.onWindowClick),this.onWindowClick=null),this.onMouseMove&&(window.removeEventListener("mousemove",this.onMouseMove),this.onMouseMove=null),this.element&&this.element.parentNode&&this.element.parentNode.removeChild(this.element),this.element=null,this.revokeBtn&&this.revokeBtn.parentNode&&this.revokeBtn.parentNode.removeChild(this.revokeBtn),this.revokeBtn=null,function(i){if(t.isPlainObject(i)){var n=t.hash(JSON.stringify(i)),o=e.customStyles[n];if(o&&!--o.references){var s=o.element.ownerNode;s&&s.parentNode&&s.parentNode.removeChild(s),e.customStyles[n]=null}}}(this.options.palette),this.options=null},o.prototype.open=function(t){if(this.element)return this.isOpen()||(e.hasTransition?this.fadeIn():this.element.style.display="",this.options.revokable&&this.toggleRevokeButton(),this.options.onPopupOpen.call(this)),this},o.prototype.close=function(t){if(this.element)return this.isOpen()&&(e.hasTransition?this.fadeOut():this.element.style.display="none",t&&this.options.revokable&&this.toggleRevokeButton(!0),this.options.onPopupClose.call(this)),this},o.prototype.fadeIn=function(){var i=this.element;if(e.hasTransition&&i&&(this.afterTransition&&r.call(this,i),t.hasClass(i,"cc-invisible"))){if(i.style.display="",this.options.static){var n=this.element.clientHeight;this.element.parentNode.style.maxHeight=n+"px"}this.openingTimeout=setTimeout(s.bind(this,i),20)}},o.prototype.fadeOut=function(){var i=this.element;e.hasTransition&&i&&(this.openingTimeout&&(clearTimeout(this.openingTimeout),s.bind(this,i)),t.hasClass(i,"cc-invisible")||(this.options.static&&(this.element.parentNode.style.maxHeight=""),this.afterTransition=r.bind(this,i),i.addEventListener(e.transitionEnd,this.afterTransition),t.addClass(i,"cc-invisible")))},o.prototype.isOpen=function(){return this.element&&""==this.element.style.display&&(!e.hasTransition||!t.hasClass(this.element,"cc-invisible"))},o.prototype.toggleRevokeButton=function(e){this.revokeBtn&&(this.revokeBtn.style.display=e?"":"none")},o.prototype.revokeChoice=function(e){this.options.enabled=!0,this.clearStatus(),this.options.onRevokeChoice.call(this),e||this.autoOpen()},o.prototype.hasAnswered=function(t){return Object.keys(e.status).indexOf(this.getStatus())>=0},o.prototype.hasConsented=function(t){var i=this.getStatus();return i==e.status.allow||i==e.status.dismiss},o.prototype.autoOpen=function(e){!this.hasAnswered()&&this.options.enabled?this.open():this.hasAnswered()&&this.options.revokable&&this.toggleRevokeButton(!0)},o.prototype.setStatus=function(i){var n=this.options.cookie,o=t.getCookie(n.name),s=Object.keys(e.status).indexOf(o)>=0;Object.keys(e.status).indexOf(i)>=0?(t.setCookie(n.name,i,n.expiryDays,n.domain,n.path,n.secure),this.options.onStatusChange.call(this,i,s)):this.clearStatus()},o.prototype.getStatus=function(){return t.getCookie(this.options.cookie.name)},o.prototype.clearStatus=function(){var e=this.options.cookie;t.setCookie(e.name,"",-1,e.domain,e.path)},o}(),e.Location=function(){var e={timeout:5e3,services:["ipinfo"],serviceDefinitions:{ipinfo:function(){return{url:"//ipinfo.io",headers:["Accept: application/json"],callback:function(e,t){try{var i=JSON.parse(t);return i.error?s(i):{code:i.country}}catch(e){return s({error:"Invalid response ("+e+")"})}}}},ipinfodb:function(e){return{url:"//api.ipinfodb.com/v3/ip-country/?key={api_key}&format=json&callback={callback}",isScript:!0,callback:function(e,t){try{var i=JSON.parse(t);return"ERROR"==i.statusCode?s({error:i.statusMessage}):{code:i.countryCode}}catch(e){return s({error:"Invalid response ("+e+")"})}}}},maxmind:function(){return{url:"//js.maxmind.com/js/apis/geoip2/v2.1/geoip2.js",isScript:!0,callback:function(e){window.geoip2?geoip2.country(function(t){try{e({code:t.country.iso_code})}catch(t){e(s(t))}},function(t){e(s(t))}):e(new Error("Unexpected response format. The downloaded script should have exported `geoip2` to the global scope"))}}}}};function i(i){t.deepExtend(this.options={},e),t.isPlainObject(i)&&t.deepExtend(this.options,i),this.currentServiceIndex=-1}function n(e,t,i){var n,o=document.createElement("script");o.type="text/"+(e.type||"javascript"),o.src=e.src||e,o.async=!1,o.onreadystatechange=o.onload=function(){var e=o.readyState;clearTimeout(n),t.done||e&&!/loaded|complete/.test(e)||(t.done=!0,t(),o.onreadystatechange=o.onload=null)},document.body.appendChild(o),n=setTimeout(function(){t.done=!0,t(),o.onreadystatechange=o.onload=null},i)}function o(e,t,i,n,o){var s=new(window.XMLHttpRequest||window.ActiveXObject)("MSXML2.XMLHTTP.3.0");if(s.open(n?"POST":"GET",e,1),s.setRequestHeader("Content-type","application/x-www-form-urlencoded"),Array.isArray(o))for(var r=0,a=o.length;r3&&t(s)}),s.send(n)}function s(e){return new Error("Error ["+(e.code||"UNKNOWN")+"]: "+e.error)}return i.prototype.getNextService=function(){var e;do{e=this.getServiceByIdx(++this.currentServiceIndex)}while(this.currentServiceIndex=0,revokable:t.revokable.indexOf(e)>=0,explicitAction:t.explicitAction.indexOf(e)>=0}},i.prototype.applyLaw=function(e,t){var i=this.get(t);return i.hasLaw||(e.enabled=!1,"function"==typeof e.onNoCookieLaw&&e.onNoCookieLaw(t,i)),this.options.regionalLaw&&(i.revokable&&(e.revokable=!0),i.explicitAction&&(e.dismissOnScroll=!1,e.dismissOnTimeout=!1)),e},i}(),e.initialise=function(i,n,o){var s=new e.Law(i.law);n||(n=function(){}),o||(o=function(){});var r=Object.keys(e.status),a=t.getCookie("cookieconsent_status");r.indexOf(a)>=0?n(new e.Popup(i)):e.getCountryCode(i,function(t){delete i.law,delete i.location,t.code&&(i=s.applyLaw(i,t.code)),n(new e.Popup(i))},function(t){delete i.law,delete i.location,o(t,new e.Popup(i))})},e.getCountryCode=function(t,i,n){t.law&&t.law.countryCode?i({code:t.law.countryCode}):t.location?new e.Location(t.location).locate(function(e){i(e||{})},n):i({})},e.utils=t,e.hasInitialised=!0,window.cookieconsent=e}}(window.cookieconsent||{}); \ No newline at end of file diff --git a/themes/pybcn_theme/assets/scss/footer.scss b/themes/pybcn_theme/assets/scss/footer.scss index efd3b77e..f891013a 100644 --- a/themes/pybcn_theme/assets/scss/footer.scss +++ b/themes/pybcn_theme/assets/scss/footer.scss @@ -4,6 +4,16 @@ footer { color: white; margin-top: 30px; + .legal_links { + margin-top: 10px; + text-align: center; + + a { + color: inherit; + text-decoration: underline; + } + } + img.logo_icon { width: 30px; height: auto; diff --git a/themes/pybcn_theme/layouts/partials/cookie-consent.html b/themes/pybcn_theme/layouts/partials/cookie-consent.html deleted file mode 100644 index 6fed6bd4..00000000 --- a/themes/pybcn_theme/layouts/partials/cookie-consent.html +++ /dev/null @@ -1,28 +0,0 @@ -{{ $cookieConsentStyle := resources.Get "css/cookieconsent.min.css" | resources.Fingerprint }} - -{{ $cookieConsentScript := resources.Get "js/cookieconsent.min.js" | resources.Fingerprint }} - - - - -{{- /* vim: set ts=2 sw=2 et: */}} diff --git a/themes/pybcn_theme/layouts/partials/footer.html b/themes/pybcn_theme/layouts/partials/footer.html index 8cff3caa..654941cb 100644 --- a/themes/pybcn_theme/layouts/partials/footer.html +++ b/themes/pybcn_theme/layouts/partials/footer.html @@ -23,6 +23,15 @@ + {{/* The legal pages are resolved through site.GetPage, so a moved or + renamed page fails the build instead of leaving a dead link. */}} +
+ +
{{ end }} \ No newline at end of file diff --git a/themes/pybcn_theme/layouts/partials/head.html b/themes/pybcn_theme/layouts/partials/head.html index 1fa4c79a..f349765c 100644 --- a/themes/pybcn_theme/layouts/partials/head.html +++ b/themes/pybcn_theme/layouts/partials/head.html @@ -37,6 +37,3 @@ {{ end -}} - {{ if .Site.Params.cookie_consent_info_url }} - {{ partial "cookie-consent.html" . }} - {{ end }}