diff --git a/.dockerignore b/.dockerignore index 3d1eb70..4a602da 100644 --- a/.dockerignore +++ b/.dockerignore @@ -2,5 +2,5 @@ .idea/ .dockerignore .gitignore -*.txt +notes.txt *.md diff --git a/.gitignore b/.gitignore index b7df7a1..e1ec23a 100644 --- a/.gitignore +++ b/.gitignore @@ -4,11 +4,10 @@ # Static resources resources/Azias/imgs/*.exe resources/Azias/imgs/*.url -resources/ChartJs/ resources/FontAwesomePro/ resources/GoogleFonts/ -resources/HalfMoon/ # Other folders (Will be removed once the content system is finished !) content/page/ -/files/ +# /files/*/ +files/ diff --git a/about/index.php b/about/index.php index 8f659e0..75ef508 100644 --- a/about/index.php +++ b/about/index.php @@ -3,6 +3,7 @@ set_include_path('../commons/'); include_once 'config.php'; include_once 'langs.php'; ?> + @@ -74,7 +75,6 @@ include_once 'langs.php';
-
@@ -89,17 +89,14 @@ include_once 'langs.php';
-

  TODO

-
-
@@ -114,13 +111,33 @@ include_once 'langs.php';
-

  TODO

- +
+ +
+
+
+
+
+

+    +

+
+
+

@NibblePoker

+
+
+
+
+
+

+   TODO +

+
diff --git a/commons/listing.php b/commons/listing.php new file mode 100644 index 0000000..9f72f05 --- /dev/null +++ b/commons/listing.php @@ -0,0 +1,69 @@ +fileName = $fileName; + $this->fileSize = $fileSize; + $this->absolutePath = $absolutePath; + } +} + +class ListingContainer { + public string $relativePath; + public array $subDirectories; + public array $files; + + function __construct($relativePath) { + $this->relativePath = $relativePath; + $this->subDirectories = array(); + $this->files = array(); + } +} + +// Functions. +function getDirectoryContent(string $dirPath, array $filteringRegexes, int $recursiveBudget, bool $validatePermission): ListingContainer { + $returnedData = new ListingContainer("./"); + + if($recursiveBudget == 0) { + return $returnedData; + } + + if($validatePermission) { + if(!file_exists($dirPath . DIRECTORY_SEPARATOR . ".allow_listing")) { + $returnedData->files[] = new ListingFile( + "Directory listing isn't allowed !", + -1, + realpath($dirPath . DIRECTORY_SEPARATOR . ".allow_listing") + ); + return $returnedData; + } + } + + foreach (scandir($dirPath) as $key => $value) { + $path = realpath($dirPath . DIRECTORY_SEPARATOR . $value); + if(is_file($path)) { + $returnedData->files[] = new ListingFile(basename($path), filesize($path), realpath($path)); + } elseif($value != "." && $value != "..") { + $returnedData->subDirectories[] = getDirectoryContent( + $path, + $filteringRegexes, + $recursiveBudget - 1, + false + ); + } + } + + return $returnedData; +} + +?> diff --git a/commons/sidebar.php b/commons/sidebar.php index 667ffe9..df76bf1 100644 --- a/commons/sidebar.php +++ b/commons/sidebar.php @@ -53,6 +53,11 @@ if(!isset($SIDEBAR_ID)) { + + + + + "> diff --git a/commons/strings.json b/commons/strings.json index 8da0e89..9a06199 100644 --- a/commons/strings.json +++ b/commons/strings.json @@ -16,6 +16,7 @@ "programming.others.title": "Others", "programming.docker.title": "Docker", "programming.apps.title": "Applications", + "programming.downloads.title": "Downloads", "programming.tutorials.title": "Tutorials", "programming.tools.title": "Tools", "electronics.title": "Electronics", @@ -48,6 +49,42 @@ "privacy.complaint.title": "How to contact the appropriate authorities ?", "privacy.complaint.text.1": "Should you wish to report a complaint or if you feel that our privacy policy has not addressed your concern in a satisfactory manner, you may contact your national Data Protection Authority (DPA).", "privacy.complaint.text.2": "More information on this procedure can be found on the following websites:", + + "privacy.v2.data.title": "Data collection", + "privacy.v2.data.intro.1": "This websites only collects data through generic access logs in order to detect and block bad actors from accessing this website.", + "privacy.v2.data.intro.2": "None of the data collected is used for any other purpose,it is never shared with any other third-party and is never use in any sort of analytics.", + "privacy.v2.data.private.1": "Here is the list of private data being collected:", + "privacy.v2.data.private_list.1": "IP address forwarded to us by CloudFlare", + "privacy.v2.data.private_list.2": "Browser's User-Agent", + "privacy.v2.data.non_private.1": "And here is the list of non-private data being collected:", + "privacy.v2.data.non_private_list.1": "Requested resource' URI", + "privacy.v2.data.non_private_list.2": "Date and time", + "privacy.v2.data.end.1": "Once the data has been logged in the access logs, it is automatically retrieved and processed by a locally-hosted application every 30 seconds and then deleted from said logs.", + "privacy.v2.data.end.2": "This application compares this information against a list of known threat sources, targets and behaviours and if a match is found, the private information is anonymized and stored for 7 days pending a manual review.", + "privacy.v2.data.end.3": "Once that 7 day period has elapsed, or once the report has been reviewed, all the relevant data is automatically deleted.", + "privacy.v2.data.end.4": "If your request wasn't flagged as potentially malicious, every data collected from it is thrown out instantly.", + "privacy.v2.data.end.5": "This process should normally never be triggered for regular traffic since most of the triggering actions are ones that should not be possible to accomplish through normal browsing.", + "privacy.v2.data.end.6": "However, this process isn't infallible and there is always an off chance that false positives may happen.", + + "privacy.v2.update.intro.1": "The content of this privacy policy was originally written on the 4th of December 2021 and was last updated on the 18th of March 2022.", + "privacy.v2.update.history.1.date": "2021/12/04", + "privacy.v2.update.history.1.desc.1": "Original version", + "privacy.v2.update.history.2.date": "2022/03/18", + "privacy.v2.update.history.2.desc.1": "Changed section on data collection to reflect new policy.", + "privacy.v2.update.history.2.desc.2": "Added mention about CloudFlare and linked to their privacy policy.", + "privacy.v2.update.history.2.desc.3": "Improved the \"Changes to our privacy policy\" section.", + "privacy.v2.update.end.2": "In the event of a change to our privacy policy, you will be informed explicitly, and a copy of previous versions of the policy will be available through this page.", + + "privacy.v2.third.title": "Third Parties", + "privacy.v2.third.intro.1": "Our websites uses some services provided by CloudFlare in order to prevent bad actors from accessing this website via their \"Web Application Firewall\", as well as for caching purpose in order to improve your browsing experience.", + "privacy.v2.third.intro.2": "None of the data that may be gathered by CloudFlare is ever used.", + "privacy.v2.third.intro.3": "If you'd wish to consult their privacy policy, you can do so on their \"Trust Hub\" at the following URLs:", + + "privacy.v2.cookies.title": "Cookies", + "privacy.v2.cookies.intro.1": "Our websites doesn't use nor store any cookies in your browser.", + "privacy.v2.cookies.intro.2": "In the unlikely event one is present, we recommend you check CloudFlare's privacy policy on their \"Trust Hub\" at the following URLs:", + "privacy.v2.cookies.intro.3": "This can be caused by malicious traffic coming from your network, or when you visit some private and restricted subdomains.", + "error.common.details.title": "Error details", "error.4xx.title": "HTTP Client Error", "error.4xx.text": "${error.4xx.text}", @@ -75,9 +112,15 @@ "content.search.count.multiple": "results", "about.biography.title": "Who am I ?", + "about.philosophy.title": "Projects philosophy", "about.skills.title": "Skills", "about.work.title": "Professional experiences", - "about.education.title": "TODO:SchoolAndEducation" + "about.education.title": "TODO:SchoolAndEducation", + + "downloads.title": "Downloads", + "downloads.description": "$downloads.description", + "downloads.title.header": "Downloads", + "downloads.intro.title": "Directory listing of: /files/" }, "fr": { "home.title.nav": "Accueil", @@ -95,6 +138,7 @@ "programming.others.title": "Autres", "programming.docker.title": "Docker", "programming.apps.title": "Applications", + "programming.downloads.title": "Téléchargements", "programming.tutorials.title": "Tutoriels", "programming.tools.title": "Outils", "electronics.title": "Électronique", @@ -127,6 +171,42 @@ "privacy.complaint.title": "Comment contacter les autorités compétentes ?", "privacy.complaint.text.1": "Dans l'éventualité où vous souhaiteriez déposer une plainte pour une quelconque raison en rapport avec notre politique de confidentialité, veuillez vous adresser à l'autorité nationale de protection des données (DPA).", "privacy.complaint.text.2": "Les informations concernant cette procédure peuvent être trouvées sur les sites internet suivants:", + + "privacy.v2.data.title": "Collecte de données", + "privacy.v2.data.intro.1": "Ce site web collecte des données au travers des journaux d'évènements afin de détecter et bloquer de potentiels acteurs malveillants.", + "privacy.v2.data.intro.2": "Les données collectées ne sont en aucun cas utilisées pour une quelconque autre raison.", + "privacy.v2.data.private.1": "Voici la liste des données personelles collectées:", + "privacy.v2.data.private_list.1": "L'addresse IP source détéctée par CloudFlare", + "privacy.v2.data.private_list.2": "Le \"User-Agent\" de votre navigateur internet", + "privacy.v2.data.non_private.1": "Et voici la liste des données non-personelles collectées:", + "privacy.v2.data.non_private_list.1": "L'URI de la ressource demandée", + "privacy.v2.data.non_private_list.2": "La date et l'heure", + "privacy.v2.data.end.1": "Les données présentes dans les journaux d'évènements sont extraites et retirées pour être traitées par une application qui tourne en local toute les 30 secondes.", + "privacy.v2.data.end.2": "L'application en question utilise et compare ces informations avec une liste d'acteurs malveillants et comportement suspects connus.
Si une correspondance est détectée, les informations privées sont anonymisées et sont stockées pendant 7 jours en attendant qu'un examen manuel soit effectué.", + "privacy.v2.data.end.3": "Après cette période de 7 jours, ou après qu'un examen ait été effectué, les données sont automatiquement supprimées.", + "privacy.v2.data.end.4": "Toute information concernant une requête non suspecte est automatiquement supprimée.", + "privacy.v2.data.end.5": "Ce processus n'est normalement jamais utilisé sur des requêtes provenant d'un trafic légitime dû au fait qu'il isole principalement les actions et requêtes qui ne devraient pas être possible sur ce site.", + "privacy.v2.data.end.6": "Cependant, ce processus n'est pas infaillible et il est toujours possible qu'une requête soit isolée par erreur.", + + "privacy.v2.update.intro.1": "Le contenu de notre politique de confidentialité a été originalement écrit et le 4 décembre 2021 modifié pour la dernière fois le 18 mars 2022.", + "privacy.v2.update.history.1.date": "2021/12/04", + "privacy.v2.update.history.1.desc.1": "Version originale", + "privacy.v2.update.history.2.date": "2022/03/18", + "privacy.v2.update.history.2.desc.1": "Mise-à-jour de la section sur la collection des données.", + "privacy.v2.update.history.2.desc.2": "Ajout d'une mention de CloudFlare et ajout de liens vers leur politique de confidentialité.", + "privacy.v2.update.history.2.desc.3": "Amélioration de la section \"Changements à notre politique de confidentialité\".", + "privacy.v2.update.end.2": "En cas de changement, vous serez clairement informé et une copie des anciennes versions de notre politique sera disponible au travers de cette page.", + + "privacy.v2.third.title": "Organismes tiers", + "privacy.v2.third.intro.1": "Ce site web utilise les services proposés par CloudFlare afin d'empêcher des acteurs malveillants d'y accéder grâce au \"web application Firewall\", ainsi que pour améliorer l'expérience des personnes le visitant grâce à leur CDN.", + "privacy.v2.third.intro.2": "Aucune des données collectées et stockées par CloudFlare n'est utilisé.", + "privacy.v2.third.intro.3": "Si vous souhaitez consulter leur politique de confidentialité, vous pouvez le faire sur leur \"Trust Hub\" en utilisant les liens ci-dessous:", + + "privacy.v2.cookies.title": "Cookies de navigation", + "privacy.v2.cookies.intro.1": "Ce site web n'utilise pas, et ne stocke aucun cookies dans votre navigateur internet.", + "privacy.v2.cookies.intro.2": "Dans l'éventualité où l'un serait présent, nous vous recommandons de consulter le \"Trust Hub\" de CloudFlare via les liens suivants pour plus d'informations:", + "privacy.v2.cookies.intro.3": "Ce genre de situation peut être causée par le fait que du trafic suspect provient de votre navigateur internet, ou lors d'une visite sur un de nos sous-domaines privés.", + "error.common.details.title": "Détails de l'erreur", "error.4xx.title": "Erreur du client HTTP", "error.4xx.text": "${error.4xx.text}", @@ -154,6 +234,7 @@ "content.search.count.multiple": "résultats", "about.biography.title": "Qui suis-je ?", + "about.philosophy.title": "Philosophie des projets", "about.skills.title": "Compétences", "about.work.title": "Parcours professionnel", "about.education.title": "Éducation" diff --git a/index.php b/index.php index da75e61..4fd05f4 100644 --- a/index.php +++ b/index.php @@ -145,8 +145,13 @@ include_once 'langs.php';

- 1st February 2022
- Going the self-hosted route. + 18th March 2022
+ Updated the privacy policy. +

+
+

+ 28th February 2022
+ Dropped OVH as our main web hosting provider, and switched to CloudFlare.

diff --git a/privacy/index.php b/privacy/index.php index 226b65f..5a3a892 100644 --- a/privacy/index.php +++ b/privacy/index.php @@ -58,16 +58,113 @@ include_once 'langs.php';

-    +   

- + +
+ +

+

+
+ +   
+
+ +   
+
+

+

+
+ +   
+
+ +   
+
+

+

+ +

+

+
+ +

+

+ +

+

+
+

+ +
+
+
+

+    +

+
+
+
+

+ +

+

+ +

+

+
+ +
+ https://www.cloudflare.com/trust-hub/gdpr/ + + ()
+ + + https://www.cloudflare.com/fr-fr/trust-hub/gdpr/ + + ()
+

+
+
+ +
+
+
+

+    +

+
+
+
+

+ +

+

+
+ + + https://www.cloudflare.com/trust-hub/gdpr/ + + ()
+ + + https://www.cloudflare.com/fr-fr/trust-hub/gdpr/ + + ()
+

+

+ +

+
+
+
@@ -77,14 +174,47 @@ include_once 'langs.php';
-

- -

- + +

+

+    + +    + + +    + +
+ +   
+
+

+

+    + +    + + +    + +
+ +   
+
+ +   
+
+ +    + +

+

+

+
diff --git a/privacy/privacy_2021-12-04_en.txt b/privacy/privacy_2021-12-04_en.txt new file mode 100644 index 0000000..c6f9c3e --- /dev/null +++ b/privacy/privacy_2021-12-04_en.txt @@ -0,0 +1,29 @@ +# Introduction +This privacy policy is written in accordance with the 12th and 13th articles of the GDPR. + +If you wish to consult it, you can do so on the following websites: +* https://gdpr.eu/ +* https://eur-lex.europa.eu/ + + +# What data do we collect ? +This website, does not collect any personal data, be it through access logs, cookies or any third-party services. + + +# Changes to our privacy policy +The content of this privacy policy was written and last updated on the 4th of December 2021. + +In the event of a change to our privacy policy, you will be informed explicitly, and a copy of previous versions of the policy will be available on this page. + + +# How to contact us ? +If you wish to contact us for more information regarding our privacy policy, please contact us via the form included on the contact page, or at the following email address: +* herwin.bozet@gmail.com + + +# How to contact the appropriate authorities ? +Should you wish to report a complaint or if you feel that our privacy policy has not addressed your concern in a satisfactory manner, you may contact your national Data Protection Authority (DPA). + +More information on this procedure can be found on the following websites: +* https://ec.europa.eu/ (English) +* https://gegevensbeschermingsautoriteit.be/ (French) diff --git a/privacy/privacy_2021-12-04_fr.txt b/privacy/privacy_2021-12-04_fr.txt new file mode 100644 index 0000000..d9d3748 --- /dev/null +++ b/privacy/privacy_2021-12-04_fr.txt @@ -0,0 +1,29 @@ +# Introduction +La politique de confidentialité ci-présente a été écrite en accord avec les articles 12 et 13 de la RGPD. + +Si vous souhaitez consulter le texte officiel en question, vous pouvez le faire sur les sites internet suivants : +* https://gdpr.eu/ +* https://eur-lex.europa.eu/ + + +# Quelles données sont collectées ? +Ce site web ne collecte aucune donnée personnelle, que ce soit au travers des journaux d'évènements sur nos serveurs, des cookies ou via quelconque autre tiers parti. + + +# Changements à notre politique de confidentialité +Le contenu de notre politique de confidentialité a été écrit et modifié pour la dernière fois le 4 décembre 2021. + +En cas de changement, vous serez clairement informé et une copie des anciennes versions de notre politique sera disponible sur cette page. + + +# Comment nous contacter ? +Si vous souhaitez nous contacter afin d'obtenir plus d'informations concernant notre politique de confidentialité, nous vous recommandons d'utiliser le formulaire présent sur la page de contact, ou par courriel à l'adresse suivante: +* herwin.bozet@gmail.com + + +# Comment contacter les autorités compétentes ? +Dans l'éventualité où vous souhaiteriez déposer une plainte pour une quelconque raison en rapport avec notre politique de confidentialité, veuillez vous adresser à l'autorité nationale de protection des données (DPA). + +Les informations concernant cette procédure peuvent être trouvées sur les sites internet suivants: +* https://ec.europa.eu/ (Anglais) +* https://gegevensbeschermingsautoriteit.be/ (Français) diff --git a/privacy/privacy_2022-03-18_en.txt b/privacy/privacy_2022-03-18_en.txt new file mode 100644 index 0000000..b521866 --- /dev/null +++ b/privacy/privacy_2022-03-18_en.txt @@ -0,0 +1,76 @@ +# Introduction +This privacy policy is written in accordance with the 12th and 13th articles of the GDPR. + +If you wish to consult it, you can do so on the following websites: + https://gdpr.eu/ + https://eur-lex.europa.eu/ + + +# Data collection +This websites only collects data through generic access logs in order to detect and block bad actors from accessing this website. +None of the data collected is used for any other purpose,it is never shared with any other third-party and is never use in any sort of analytics. + +Here is the list of private data being collected: +* IP address forwarded to us by CloudFlare +* Browser's User-Agent + +And here is the list of non-private data being collected: +* Requested resource' URI +* Date and time + +Once the data has been logged in the access logs, it is automatically retrieved and processed by a locally-hosted application every 30 seconds and then deleted from said logs. + +This application compares this information against a list of known threat sources, targets and behaviours and if a match is found, the private information is anonymized and stored for 7 days pending a manual review. +Once that 7 day period has elapsed, or once the report has been reviewed, all the relevant data is automatically deleted. + +If your request wasn't flagged as potentially malicious, every data collected from it is thrown out instantly. + +This process should normally never be triggered for regular traffic since most of the triggering actions are ones that should not be possible to accomplish through normal browsing. +However, this process isn't infallible and there is always an off chance that false positives may happen. + + +# Third Parties +Our websites uses some services provided by CloudFlare in order to prevent bad actors from accessing this website via their "Web Application Firewall", as well as for caching purpose in order to improve your browsing experience. + +None of the data that may be gathered by CloudFlare is ever used. + +If you'd wish to consult their privacy policy, you can do so on their "Trust Hub" at the following URLs: + https://www.cloudflare.com/trust-hub/gdpr/ (English) + https://www.cloudflare.com/fr-fr/trust-hub/gdpr/ (French) + + +# Cookies +Our websites doesn't use nor store any cookies in your browser. + +In the unlikely event one is present, we recommend you check CloudFlare's privacy policy on their "Trust Hub" at the following URLs: + https://www.cloudflare.com/trust-hub/gdpr/ (English) + https://www.cloudflare.com/fr-fr/trust-hub/gdpr/ (French) + +This can be caused by malicious traffic coming from your network, or when you visit some private and restricted subdomains. + + +# Changes to our privacy policy +The content of this privacy policy was originally written on the 4th of December 2021 and was last updated on the 18th of March 2022. + +* 2021/12/04 + * Original version + +* 2022/03/18 + * Changed section on data collection to reflect new policy. + * Added mention about CloudFlare and linked to their privacy policy. + * Improved the "Changes to our privacy policy" section. + +In the event of a change to our privacy policy, you will be informed explicitly, and a copy of previous versions of the policy will be available through this page. + + +# How to contact us ? +If you wish to contact us for more information regarding our privacy policy, please contact us via the form included on the contact page, or at the following email address: +* herwin.bozet@gmail.com + + +# How to contact the appropriate authorities ? +Should you wish to report a complaint or if you feel that our privacy policy has not addressed your concern in a satisfactory manner, you may contact your national Data Protection Authority (DPA). + +More information on this procedure can be found on the following websites: +* https://ec.europa.eu/ (English) +* https://gegevensbeschermingsautoriteit.be/ (French) \ No newline at end of file diff --git a/privacy/privacy_2022-03-18_fr.txt b/privacy/privacy_2022-03-18_fr.txt new file mode 100644 index 0000000..ccfd7d1 --- /dev/null +++ b/privacy/privacy_2022-03-18_fr.txt @@ -0,0 +1,77 @@ +# Introduction +La politique de confidentialité ci-présente a été écrite en accord avec les articles 12 et 13 de la RGPD. + +Si vous souhaitez consulter le texte officiel en question, vous pouvez le faire sur les sites internet suivants : +* https://gdpr.eu/ +* https://eur-lex.europa.eu/ + + +# Collecte de données +Ce site web collecte des données au travers des journaux d'évènements afin de détecter et bloquer de potentiels acteurs malveillants. +Les données collectées ne sont en aucun cas utilisées pour une quelconque autre raison. + +Voici la liste des données personelles collectées: +* L'addresse IP source détéctée par CloudFlare +* Le "User-Agent" de votre navigateur internet + +Et voici la liste des données non-personelles collectées: +* L'URI de la ressource demandée +* La date et l'heure + +Les données présentes dans les journaux d'évènements sont extraites et retirées pour être traitées par une application qui tourne en local toute les 30 secondes. + +L'application en question utilise et compare ces informations avec une liste d'acteurs malveillants et comportement suspects connus. +Si une correspondance est détectée, les informations privées sont anonymisées et sont stockées pendant 7 jours en attendant qu'un examen manuel soit effectué. +Après cette période de 7 jours, ou après qu'un examen ait été effectué, les données sont automatiquement supprimées. + +Toute information concernant une requête non suspecte est automatiquement supprimée. + +Ce processus n'est normalement jamais utilisé sur des requêtes provenant d'un trafic légitime dû au fait qu'il isole principalement les actions et requêtes qui ne devraient pas être possible sur ce site. +Cependant, ce processus n'est pas infaillible et il est toujours possible qu'une requête soit isolée par erreur. + + +# Organismes tiers +Ce site web utilise les services proposés par CloudFlare afin d'empêcher des acteurs malveillants d'y accéder grâce au "web application Firewall", ainsi que pour améliorer l'expérience des personnes le visitant grâce à leur CDN. + +Aucune des données collectées et stockées par CloudFlare n'est utilisé. + +Si vous souhaitez consulter leur politique de confidentialité, vous pouvez le faire sur leur "Trust Hub" en utilisant les liens ci-dessous: +* https://www.cloudflare.com/trust-hub/gdpr/ (Anglais) +* https://www.cloudflare.com/fr-fr/trust-hub/gdpr/ (Français) + + +# Cookies de navigation +Ce site web n'utilise pas, et ne stocke aucun cookies dans votre navigateur internet. + +Dans l'éventualité où l'un serait présent, nous vous recommandons de consulter le "Trust Hub" de CloudFlare via les liens suivants pour plus d'informations: +* https://www.cloudflare.com/trust-hub/gdpr/ (Anglais) +* https://www.cloudflare.com/fr-fr/trust-hub/gdpr/ (Français) + +Ce genre de situation peut être causée par le fait que du trafic suspect provient de votre navigateur internet, ou lors d'une visite sur un de nos sous-domaines privés. + + +# Changements à notre politique de confidentialité +Le contenu de notre politique de confidentialité a été originalement écrit et le 4 décembre 2021 modifié pour la dernière fois le 18 mars 2022. + +* 2021/12/04 + * Version originale + +* 2022/03/18 + * Mise-à-jour de la section sur la collection des données. + * Ajout d'une mention de CloudFlare et ajout de liens vers leur politique de confidentialité. + * Amélioration de la section "Changements à notre politique de confidentialité". + +En cas de changement, vous serez clairement informé et une copie des anciennes versions de notre politique sera disponible au travers de cette page. + + +# Comment nous contacter ? +Si vous souhaitez nous contacter afin d'obtenir plus d'informations concernant notre politique de confidentialité, nous vous recommandons d'utiliser le formulaire présent sur la page de contact, ou par courriel à l'adresse suivante: +* herwin.bozet@gmail.com + + +# Comment contacter les autorités compétentes ? +Dans l'éventualité où vous souhaiteriez déposer une plainte pour une quelconque raison en rapport avec notre politique de confidentialité, veuillez vous adresser à l'autorité nationale de protection des données (DPA). + +Les informations concernant cette procédure peuvent être trouvées sur les sites internet suivants: +* https://ec.europa.eu/ (Anglais) +* https://gegevensbeschermingsautoriteit.be/ (Français) \ No newline at end of file diff --git a/readme.md b/readme.md index 291a26c..f734669 100644 --- a/readme.md +++ b/readme.md @@ -28,21 +28,8 @@ These pages can be removed by deleting the folders and removing the appropriate the [.htaccess](.htaccess) file. ## Requirements -These files are not present in this repo since they -would clutter the commits and potentially break some licensing rules. - -### Required -These files are required for the website to work properly !
+These files are required and need to be installed manually for the website to work properly !
* Apache & * PHP 8 or newer * Font Awesome Pro v5.15.3 * `/resources/FontAwesomePro/` -* HalfMoon v1.1.1 - * `/resources/HalfMoon/` - -### Optional -These files are leftovers from previous projects and might be required somewhere. -* ChartJS - * `/resources/ChartJs/` -* Material Icons - * `/resources/GoogleFonts/MaterialIcons/` diff --git a/resources/Azias/css/nibblepoker.lu.css b/resources/Azias/css/nibblepoker.lu.css index f4f5818..5830318 100644 --- a/resources/Azias/css/nibblepoker.lu.css +++ b/resources/Azias/css/nibblepoker.lu.css @@ -43,6 +43,12 @@ div#body-overlay { .ucase { text-transform: uppercase; } +.font-size-8 { + font-size: 0.8rem!important; +} +.font-size-10 { + font-size: 1.0rem!important; +} .font-size-26 { font-size: 2.6rem!important; } @@ -142,6 +148,15 @@ div.content-tag-container a:not(:first-child) { } } +/* Fixes */ +/* TODO: Fix it when it is closed */ +div.last-inner-collapse-border-fix { + border: var(--collapse-content-border-width) solid var(--dm-collapse-content-border-color) !important; + border-top: 0 !important; + border-bottom-left-radius: var(--collapse-content-border-radius) !important; + border-bottom-right-radius: var(--collapse-content-border-radius) !important; +} + /* Trash */ /*.lang-icon { diff --git a/resources/HalfMoon/1.1.1/CONTRIBUTING.md b/resources/HalfMoon/1.1.1/CONTRIBUTING.md new file mode 100644 index 0000000..2aa0774 --- /dev/null +++ b/resources/HalfMoon/1.1.1/CONTRIBUTING.md @@ -0,0 +1,32 @@ +# Contributing to Halfmoon + +Please read this short document if you want to contribute to Halfmoon. + +## Our goal + +Before getting to the issues and pull requests, it is important to understand what the framework is trying to do. + +Halfmoon's stated goal is really simple - create a customizable frontend framework, with a built-in dark mode, that is great for building dashboards and tools. However, our other goals are more implicit: + +- Everything has to be **super functional and snappy**. Ideally, that means no performance issues and just consistently good execution. +- Everything has to **look good** as well, and have a **single, consistent style**. + +The most important thing here is building a **really good (looking) framework that also works very well**, and that should always be the top priority. + +## Issues + +Please keep the following things in mind when raising issues: + +- Feature requests are welcome. However, please make sure that the feature you are requesting falls under the scope of the project. +- **Do not** post personal support questions as issues. For those, use this [tag on Stack Overflow](https://stackoverflow.com/questions/tagged/halfmoon). +- When raising an issue, please be as thorough as possible. For possible bugs, reproducible code is always a great sign. + +## Pull requests + +**Please ask first** before you put in work for a pull request. Things are constantly being worked on, and it is very difficult to share everything publicly in a meaningful way. So asking lets us avoid working on the same thing, or worse, someone putting in a lot of work for a PR that does not fit into the scope of the project. Please do not take this the wrong way; at this stage, the project needs strong leadership to become something special. + +The best way to ask is through email: [hey.halfmoon@gmail.com](mailto:hey.halfmoon@gmail.com). I am always open to proper discussions about the framework, especially when it comes to contributions and pull requests. + +## License + +Any contribution you make will fall under the license being used by the framework: [MIT license](https://www.gethalfmoon.com/license/). diff --git a/resources/HalfMoon/1.1.1/LICENSE b/resources/HalfMoon/1.1.1/LICENSE new file mode 100644 index 0000000..3c54dac --- /dev/null +++ b/resources/HalfMoon/1.1.1/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 Halfmoon UI + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/resources/HalfMoon/1.1.1/README.md b/resources/HalfMoon/1.1.1/README.md new file mode 100644 index 0000000..fc2106f --- /dev/null +++ b/resources/HalfMoon/1.1.1/README.md @@ -0,0 +1,95 @@ +# [Halfmoon](https://www.gethalfmoon.com) + +> Front-end framework with a built-in dark mode and full customizability using CSS variables; great for building dashboards and tools. + +- **Built-in dark mode**—Halfmoon comes with a built-in, toggleable dark mode, which is one of its most important and defining features. +- **Fully customizable using CSS variables**—The framework is built entirely using CSS variables (also known as CSS custom properties). There are close to *1,500 CSS variables*, which means that almost everything can be customized by overriding a property, making it very easy to theme Halfmoon to fit your brand. [Learn more about customization](https://www.gethalfmoon.com/docs/customize/). +- **Great for building dashboards and tools**—The components have a very standard look and feel to them, making them suitable for dashboards and tools. Moreover, a lot of importance is placed on components such as forms, navbars, sidebars, dropdowns, toasts, shortcuts, etc. and there are also *tons of utilities* available. +- **Optional JS library**—Many of the components found in Halfmoon are built to work without JavaScript. However, the framework still comes with a powerful JavaScript library with no extra dependencies, such as jQuery. +- **Bootstrap like classes**—The class names should be instantly familiar to anyone who has used Bootstrap. +- **Cross-browser compatibility**—Fully supports almost all the browsers under the sun, including really old ones like Internet Explorer 11. + +To learn more, go to [the documentation](https://www.gethalfmoon.com/docs/introduction/). + +## Quickstart + +The quickest way to get started with Halfmoon is by using the CDN to include the following files: + +```html + + + + + + +``` + +**Pleast note**, the JS file should be placed at the end of the `` tag. Otherwise, some things may not work as expected. For example, using the `onclick="..."` event to call one of Halfmoon's built-in methods will not work **unless** the JS file is placed at the end of the `` tag. + +## Using npm + +``` +npm install halfmoon +``` + +After installation, the required CSS and JS file can be imported in the following way: + +```javascript +// Include CSS file +require("halfmoon/css/halfmoon-variables.min.css"); +/* + Or, + Include the following (no variables, supports IE11): + require("halfmoon/css/halfmoon.min.css"); +*/ + +// Import JS library +const halfmoon = require("halfmoon"); +``` + +Please note that manual initialization is required for some components, that is, after the DOM is loaded, the following method needs to be called: + +```javascript +// Call this method after the DOM has been loaded +halfmoon.onDOMContentLoaded(); +``` + +This initializes all of the components that require JavaScript, such as dropdowns, custom file inputs, shortcuts, etc. + +In this way, Halfmoon can be used with frameworks that use the virtual DOM, such as React and Vue. For instance, in the case of Vue, the `halfmoon.onDOMContentLoaded()` method would be called inside the `mounted()` hook of your component. + +## Using React + +If you are using React to call the built-in methods, such as `halfmoon.toggleSidebar()`, please make sure the call is made in a way that binds the correct context. There are two ways to do this: + +1. Using an anonymous method: + + ```html + " + content; + } + + // Add the content to the alert element + alertElement.innerHTML = content; + + // Append the alert element to the sticky alerts + this.stickyAlerts.insertBefore(alertElement, this.stickyAlerts.childNodes[0]); + + // Toast the alert + this.toastAlert(alertElement.getAttribute("id"), timeShown); + }, + + /* End code block for handling sticky alerts */ + + // Click handler that can be overridden by users if needed + clickHandler: function(event) {}, + + // Keydown handler that can be overridden by users if needed + keydownHandler: function(event) {}, +} + + +/* Things done once the DOM is loaded */ + +function halfmoonOnDOMContentLoaded() { + // Re-initializing the required elements (to avoid issues with virtual DOM) + if (!halfmoon.pageWrapper) { + halfmoon.pageWrapper = document.getElementsByClassName("page-wrapper")[0]; + } + if (!halfmoon.stickyAlerts) { + halfmoon.stickyAlerts = document.getElementsByClassName("sticky-alerts")[0]; + } + + // Handle the cookie and variable for dark mode + // 1. First preference is given to the cookie if it exists + if (halfmoon.readCookie("halfmoon_preferredMode")) { + if (halfmoon.readCookie("halfmoon_preferredMode") == "dark-mode") { + halfmoon.darkModeOn = true; + } else { + halfmoon.darkModeOn = false; + } + } else { + // 2. If cookie does not exist, next preference is for the dark mode setting + if (window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches) { + halfmoon.darkModeOn = true; + } else { + // 3. If all else fails, re-initialize the dark mode preference depending on the .dark-mode class + if (document.body.classList.contains("dark-mode")) { + halfmoon.darkModeOn = true; + } else { + halfmoon.darkModeOn = false; + } + } + } + + // Automatically set preferred theme + // But only if one of the data-attribute is provided + if (document.body.getAttribute("data-set-preferred-mode-onload") || document.body.getAttribute("data-set-preferred-theme-onload")) { + if (halfmoon.darkModeOn) { + if (!document.body.classList.contains("dark-mode")) { + document.body.classList.add("dark-mode"); + } + } else { + if (document.body.classList.contains("dark-mode")) { + document.body.classList.remove("dark-mode"); + } + } + } + + // Hiding sidebar on first load on small screens (unless data-attribute provided) + // Or on larger screens when sidebar type is overlayed-all + if (document.documentElement.clientWidth <= 768) { + if (halfmoon.pageWrapper) { + if (!halfmoon.pageWrapper.getAttribute("data-show-sidebar-onload-sm-and-down")) { + halfmoon.pageWrapper.setAttribute("data-sidebar-hidden", "hidden"); + } + } + } else { + if (halfmoon.pageWrapper) { + if (halfmoon.pageWrapper.getAttribute("data-sidebar-type") === "overlayed-all") { + halfmoon.pageWrapper.setAttribute("data-sidebar-hidden", "hidden"); + } + } + } + + // Adding the click event listener + document.addEventListener( + "click", + function(event) { + var eventCopy = event; + var target = event.target; + + // Handle clicks on dropdown toggles + if (target.matches("[data-toggle='dropdown']") || target.matches("[data-toggle='dropdown'] *")) { + if (target.matches("[data-toggle='dropdown'] *")) { + target = target.closest("[data-toggle='dropdown']"); + } + if (target.classList.contains("active")) { + target.classList.remove("active"); + target.closest(".dropdown").classList.remove("show"); + } else { + halfmoon.deactivateAllDropdownToggles(); + target.classList.add("active"); + target.closest(".dropdown").classList.add("show"); + } + } else { + if (!target.matches(".dropdown-menu *")) { + halfmoon.deactivateAllDropdownToggles(); + } + } + + // Handle clicks on alert dismiss buttons + if (target.matches(".alert [data-dismiss='alert']") || target.matches(".alert [data-dismiss='alert'] *")) { + if (target.matches(".alert [data-dismiss='alert'] *")) { + target = target.closest(".alert [data-dismiss='alert']"); + } + target.parentNode.classList.add("dispose"); + } + + // Handle clicks on modal toggles + if (target.matches("[data-toggle='modal']") || target.matches("[data-toggle='modal'] *")) { + if (target.matches("[data-toggle='modal'] *")) { + target = target.closest("[data-toggle='modal']"); + } + var targetModal = document.getElementById(target.getAttribute("data-target")); + if (targetModal) { + if (targetModal.classList.contains("modal")) { + halfmoon.toggleModal(target.getAttribute("data-target")); + } + } + } + + // Handle clicks on modal dismiss buttons + if (target.matches(".modal [data-dismiss='modal']") || target.matches(".modal [data-dismiss='modal'] *")) { + if (target.matches(".modal [data-dismiss='modal'] *")) { + target = target.closest(".modal [data-dismiss='modal']"); + } + target.closest(".modal").classList.remove("show"); + } + + // Handle clicks on modal overlays + if (target.matches(".modal-dialog")) { + var parentModal = target.closest(".modal"); + + if (!parentModal.getAttribute("data-overlay-dismissal-disabled")) { + if (parentModal.classList.contains("show")) { + parentModal.classList.remove("show"); + } else { + window.location.hash = "#"; + } + } + } + + // Call the click handler method to handle any logic set by the user in their projects to handle clicks + halfmoon.clickHandler(eventCopy); + }, + false + ); + + // Adding the key down event listener (for shortcuts and accessibility) + document.addEventListener( + "keydown", + function(event) { + var eventCopy = event; + + // Shortcuts are triggered only if no input, textarea, or select has focus, + // If the control key or command key is not pressed down, + // And if the enabling data attribute is present on the DOM's body + if (!(document.querySelector("input:focus") || document.querySelector("textarea:focus") || document.querySelector("select:focus"))) { + event = event || window.event; + + if (!(event.ctrlKey || event.metaKey)) { + // Toggle sidebar when [shift] + [S] keys are pressed + if (document.body.getAttribute("data-sidebar-shortcut-enabled")) { + if (event.shiftKey && event.which == 83) { + // Variable to store whether a modal is open or not + var modalOpen = false; + + // Hash exists, so we check if it belongs to a modal + if (window.location.hash) { + var hash = window.location.hash.substring(1); + var elem = document.getElementById(hash); + if (elem) { + if (elem.classList.contains("modal")) { + modalOpen = true; + } + } + } + // Check for a modal with the .show class + if (document.querySelector(".modal.show")) { + modalOpen = true; + } + + // This shortcut works only if no modal is open + if (!modalOpen) { + halfmoon.toggleSidebar(); + event.preventDefault(); + } + } + } + + // Toggle dark mode when [shift] + [D] keys are pressed + if (document.body.getAttribute("data-dm-shortcut-enabled")) { + if (event.shiftKey && event.which == 68) { + halfmoon.toggleDarkMode(); + event.preventDefault(); + } + } + } + } + + // Handling other keydown events + if (event.which === 27) { + // Close dropdown menu (if one is open) when [esc] key is pressed + if (document.querySelector("[data-toggle='dropdown'].active")) { + var elem = document.querySelector("[data-toggle='dropdown'].active"); + elem.classList.remove("active"); + elem.closest(".dropdown").classList.remove("show"); + event.preventDefault(); + } + // Close modal (if one is open, and if no dropdown menu is open) when [esc] key is pressed + // Conditional on dropdowns so that dropdowns on modals can be closed with the keyboard without closing the modal + else { + // Hash exists, so we check if it belongs to a modal + if (window.location.hash) { + var hash = window.location.hash.substring(1); + var elem = document.getElementById(hash); + if (elem) { + if (elem.classList.contains("modal")) { + if (!elem.getAttribute("data-esc-dismissal-disabled")) { + window.location.hash = "#"; + event.preventDefault(); + } + } + } + } + // Check for a modal with the .show class + if (document.querySelector(".modal.show")) { + var elem = document.querySelector(".modal.show"); + if (!elem.getAttribute("data-esc-dismissal-disabled")) { + elem.classList.remove("show"); + event.preventDefault(); + } + } + } + } + + // Call the keydown handler method to handle any logic set by the user in their projects to handle keydown events + halfmoon.keydownHandler(eventCopy); + } + ); + + // Handling custom file inputs + var halfmoonCustomFileInputs = document.querySelectorAll(".custom-file input"); + for (var i = 0; i < halfmoonCustomFileInputs.length; i++) { + var customFile = halfmoonCustomFileInputs[i]; + // Create file name container element, add the class name, and set default value + // Append it to the custom file element + var fileNamesContainer = document.createElement("div"); + fileNamesContainer.classList.add("file-names"); + var dataDefaultValue = customFile.getAttribute("data-default-value"); + if (dataDefaultValue) { + fileNamesContainer.innerHTML = dataDefaultValue; + } else { + fileNamesContainer.innerHTML = "No file chosen"; + } + customFile.parentNode.appendChild(fileNamesContainer); + + // Add the event listener that will update the contents of the file name container element on change + customFile.addEventListener( + "change", + function(event) { + fileNamesContainer = event.target.parentNode.querySelector(".file-names"); + if (event.target.files.length === 1) { + fileNamesContainer.innerHTML = event.target.files[0].name; + } else if (event.target.files.length > 1) { + fileNamesContainer.innerHTML = event.target.files.length + " files"; + } else { + fileNamesContainer.innerHTML = "No file chosen"; + } + } + ); + } + + // Adding the .with-transitions class to the page-wrapper so that transitions are enabled + // This way, the weird bug on Chrome is avoided, where the transitions run on load + if (halfmoon.pageWrapper) { + halfmoon.pageWrapper.classList.add("with-transitions"); + } +} + +// Add the halfmoonOnDOMContentLoaded to the main halfmoon object +// And export the halfmoon object as a module +halfmoon.onDOMContentLoaded = halfmoonOnDOMContentLoaded; +module.exports = halfmoon; diff --git a/resources/HalfMoon/1.1.1/js/halfmoon.js b/resources/HalfMoon/1.1.1/js/halfmoon.js new file mode 100644 index 0000000..31bdda7 --- /dev/null +++ b/resources/HalfMoon/1.1.1/js/halfmoon.js @@ -0,0 +1,511 @@ +/* +* ----------------------------------------------------------------------------- +* Halfmoon JS +* Version: 1.1.1 +* https://www.gethalfmoon.com +* Copyright, Halfmoon UI +* Licensed under MIT (https://www.gethalfmoon.com/license) +* ----------------------------------------------------------------------------- +* The above notice must be included in its entirety when this file is used. +*/ + +/* Start polyfills */ + +// Polyfill for Element.matches() +if (!Element.prototype.matches) { + Element.prototype.matches = Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector; +} + +// Polyfill for Element.closest() +if (!Element.prototype.closest) { + Element.prototype.closest = function(s) { + var el = this; + do { + if (el.matches(s)) return el; + el = el.parentElement || el.parentNode; + } while (el !== null && el.nodeType === 1); + return null; + }; +} + +// Polyfill for Element.classList (http://purl.eligrey.com/github/classList.js/blob/master/classList.js) +"document"in self&&("classList"in document.createElement("_")&&(!document.createElementNS||"classList"in document.createElementNS("http://www.w3.org/2000/svg","g"))||!function(t){"use strict";if("Element"in t){var e="classList",n="prototype",i=t.Element[n],s=Object,r=String[n].trim||function(){return this.replace(/^\s+|\s+$/g,"")},o=Array[n].indexOf||function(t){for(var e=0,n=this.length;n>e;e++)if(e in this&&this[e]===t)return e;return-1},c=function(t,e){this.name=t,this.code=DOMException[t],this.message=e},a=function(t,e){if(""===e)throw new c("SYNTAX_ERR","The token must not be empty.");if(/\s/.test(e))throw new c("INVALID_CHARACTER_ERR","The token must not contain space characters.");return o.call(t,e)},l=function(t){for(var e=r.call(t.getAttribute("class")||""),n=e?e.split(/\s+/):[],i=0,s=n.length;s>i;i++)this.push(n[i]);this._updateClassName=function(){t.setAttribute("class",this.toString())}},u=l[n]=[],h=function(){return new l(this)};if(c[n]=Error[n],u.item=function(t){return this[t]||null},u.contains=function(t){return~a(this,t+"")},u.add=function(){var t,e=arguments,n=0,i=e.length,s=!1;do t=e[n]+"",~a(this,t)||(this.push(t),s=!0);while(++nn;n++)t=arguments[n],e.call(this,t)}};e("add"),e("remove")}if(t.classList.toggle("c3",!1),t.classList.contains("c3")){var n=DOMTokenList.prototype.toggle;DOMTokenList.prototype.toggle=function(t,e){return 1 in arguments&&!this.contains(t)==!e?e:n.call(this,t)}}"replace"in document.createElement("_").classList||(DOMTokenList.prototype.replace=function(t,e){var n=this.toString().split(" "),i=n.indexOf(t+"");~i&&(n=n.slice(i),this.remove.apply(this,n),this.add(e),this.add.apply(this,n.slice(1)))}),t=null}()); + +/* End polyfills */ + + +/* Halfmoon JS core */ + +var halfmoon = { + // Getting the required elements + // Re-initialized once the DOM is loaded (to avoid issues with virtual DOM) + pageWrapper: document.getElementsByClassName("page-wrapper")[0], + stickyAlerts: document.getElementsByClassName("sticky-alerts")[0], + + darkModeOn: false, // Also re-initialized once the DOM is loaded (see below) + + // Create cookie + createCookie: function(name, value, days) { + var expires; + if (days) { + var date = new Date(); + date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000)); + expires = "; expires=" + date.toGMTString(); + } + else { + expires = ""; + } + document.cookie = name + "=" + value + expires + "; path=/"; + }, + + // Read cookie + readCookie: function(name) { + var nameEQ = name + "="; + var ca = document.cookie.split(";"); + for(var i=0; i < ca.length; i++) { + var c = ca[i]; + while (c.charAt(0) === " ") { + c = c.substring(1, c.length); + } + if (c.indexOf(nameEQ) === 0) { + return c.substring(nameEQ.length,c.length); + } + } + return null; + }, + + // Erase cookie + eraseCookie: function(name) { + this.createCookie(name, "", -1); + }, + + // Toggle light/dark mode + toggleDarkMode: function() { + if (document.body.classList.contains("dark-mode")) { + document.body.classList.remove("dark-mode"); + this.darkModeOn = false; + this.createCookie("halfmoon_preferredMode", "light-mode", 365); + } else { + document.body.classList.add("dark-mode"); + this.darkModeOn = true; + this.createCookie("halfmoon_preferredMode", "dark-mode", 365); + } + }, + + // Get preferred mode + getPreferredMode: function() { + if (this.readCookie("halfmoon_preferredMode")) { + return this.readCookie("halfmoon_preferredMode"); + } else { + return "not-set"; + } + }, + + // Toggles sidebar + toggleSidebar: function() { + if (this.pageWrapper) { + if (this.pageWrapper.getAttribute("data-sidebar-hidden")) { + this.pageWrapper.removeAttribute("data-sidebar-hidden"); + } else { + this.pageWrapper.setAttribute("data-sidebar-hidden", "hidden"); + } + } + }, + + // Deactivate all the dropdown toggles when another one is active + deactivateAllDropdownToggles: function() { + var activeDropdownToggles = document.querySelectorAll("[data-toggle='dropdown'].active"); + for (var i = 0; i < activeDropdownToggles.length; i++) { + activeDropdownToggles[i].classList.remove("active"); + activeDropdownToggles[i].closest(".dropdown").classList.remove("show"); + } + }, + + // Toggle modal (using Javascript) + toggleModal: function(modalId) { + var modal = document.getElementById(modalId); + + if (modal) { + modal.classList.toggle("show"); + } + }, + + /* Code block for handling sticky alerts */ + + // Make an ID for an element + makeId: function(length) { + var result = ""; + var characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + var charactersLength = characters.length; + for ( var i = 0; i < length; i++ ) { + result += characters.charAt(Math.floor(Math.random() * charactersLength)); + } + return result; + }, + + // Toast an alert (show, fade, dispose) + toastAlert: function(alertId, timeShown) { + var alertElement = document.getElementById(alertId); + + // Setting the default timeShown + if (timeShown === undefined) { + timeShown = 5000; + } + + // Alert is only toasted if it does not have the .show class + if (!alertElement.classList.contains("show")) { + // Add .alert-block class if it does not exist + if (!alertElement.classList.contains("alert-block")) { + alertElement.classList.add("alert-block"); + } + + // Show the alert + // The 0.25 seconds delay is for the animation + setTimeout(function() { + alertElement.classList.add("show"); + }, 250); + + // Wait some time (timeShown + 250) and fade out the alert + var timeToFade = timeShown + 250; + setTimeout(function() { + alertElement.classList.add("fade"); + }, timeToFade); + + // Wait some more time (timeToFade + 500) and dispose the alert (by removing the .alert-block class) + // Again, the extra delay is for the animation + // Remove the .show and .fade classes (so the alert can be toasted again) + var timeToDestroy = timeToFade + 500; + setTimeout(function() { + alertElement.classList.remove("alert-block"); + alertElement.classList.remove("show"); + alertElement.classList.remove("fade"); + }, timeToDestroy); + } + }, + + // Create a sticky alert, display it, and then remove it + initStickyAlert: function(param) { + // Setting the variables from the param + var content = ("content" in param) ? param.content: ""; + var title = ("title" in param) ? param.title: ""; + var alertType = ("alertType" in param) ? param.alertType: ""; + var fillType = ("fillType" in param) ? param.fillType: ""; + var hasDismissButton = ("hasDismissButton" in param) ? param.hasDismissButton: true; + var timeShown = ("timeShown" in param) ? param.timeShown: 5000; + + // Create the alert element + var alertElement = document.createElement("div"); + + // Set ID to the alert element + alertElement.setAttribute("id", this.makeId(6)); + + // Add the title + if (title) { + content = "

" + title + "

" + content; + } + + // Add the classes to the alert element + alertElement.classList.add("alert"); + if (alertType) { + alertElement.classList.add(alertType); + } + if (fillType) { + alertElement.classList.add(fillType); + } + + // Add the close button to the content (if required) + if (hasDismissButton) { + content = "" + content; + } + + // Add the content to the alert element + alertElement.innerHTML = content; + + // Append the alert element to the sticky alerts + this.stickyAlerts.insertBefore(alertElement, this.stickyAlerts.childNodes[0]); + + // Toast the alert + this.toastAlert(alertElement.getAttribute("id"), timeShown); + }, + + /* End code block for handling sticky alerts */ + + // Click handler that can be overridden by users if needed + clickHandler: function(event) {}, + + // Keydown handler that can be overridden by users if needed + keydownHandler: function(event) {}, +} + + +/* Things done once the DOM is loaded */ + +function halfmoonOnDOMContentLoaded() { + // Re-initializing the required elements (to avoid issues with virtual DOM) + if (!halfmoon.pageWrapper) { + halfmoon.pageWrapper = document.getElementsByClassName("page-wrapper")[0]; + } + if (!halfmoon.stickyAlerts) { + halfmoon.stickyAlerts = document.getElementsByClassName("sticky-alerts")[0]; + } + + // Handle the cookie and variable for dark mode + // 1. First preference is given to the cookie if it exists + if (halfmoon.readCookie("halfmoon_preferredMode")) { + if (halfmoon.readCookie("halfmoon_preferredMode") == "dark-mode") { + halfmoon.darkModeOn = true; + } else { + halfmoon.darkModeOn = false; + } + } else { + // 2. If cookie does not exist, next preference is for the dark mode setting + if (window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches) { + halfmoon.darkModeOn = true; + } else { + // 3. If all else fails, re-initialize the dark mode preference depending on the .dark-mode class + if (document.body.classList.contains("dark-mode")) { + halfmoon.darkModeOn = true; + } else { + halfmoon.darkModeOn = false; + } + } + } + + // Automatically set preferred theme + // But only if one of the data-attribute is provided + if (document.body.getAttribute("data-set-preferred-mode-onload") || document.body.getAttribute("data-set-preferred-theme-onload")) { + if (halfmoon.darkModeOn) { + if (!document.body.classList.contains("dark-mode")) { + document.body.classList.add("dark-mode"); + } + } else { + if (document.body.classList.contains("dark-mode")) { + document.body.classList.remove("dark-mode"); + } + } + } + + // Hiding sidebar on first load on small screens (unless data-attribute provided) + // Or on larger screens when sidebar type is overlayed-all + if (document.documentElement.clientWidth <= 768) { + if (halfmoon.pageWrapper) { + if (!halfmoon.pageWrapper.getAttribute("data-show-sidebar-onload-sm-and-down")) { + halfmoon.pageWrapper.setAttribute("data-sidebar-hidden", "hidden"); + } + } + } else { + if (halfmoon.pageWrapper) { + if (halfmoon.pageWrapper.getAttribute("data-sidebar-type") === "overlayed-all") { + halfmoon.pageWrapper.setAttribute("data-sidebar-hidden", "hidden"); + } + } + } + + // Adding the click event listener + document.addEventListener( + "click", + function(event) { + var eventCopy = event; + var target = event.target; + + // Handle clicks on dropdown toggles + if (target.matches("[data-toggle='dropdown']") || target.matches("[data-toggle='dropdown'] *")) { + if (target.matches("[data-toggle='dropdown'] *")) { + target = target.closest("[data-toggle='dropdown']"); + } + if (target.classList.contains("active")) { + target.classList.remove("active"); + target.closest(".dropdown").classList.remove("show"); + } else { + halfmoon.deactivateAllDropdownToggles(); + target.classList.add("active"); + target.closest(".dropdown").classList.add("show"); + } + } else { + if (!target.matches(".dropdown-menu *")) { + halfmoon.deactivateAllDropdownToggles(); + } + } + + // Handle clicks on alert dismiss buttons + if (target.matches(".alert [data-dismiss='alert']") || target.matches(".alert [data-dismiss='alert'] *")) { + if (target.matches(".alert [data-dismiss='alert'] *")) { + target = target.closest(".alert [data-dismiss='alert']"); + } + target.parentNode.classList.add("dispose"); + } + + // Handle clicks on modal toggles + if (target.matches("[data-toggle='modal']") || target.matches("[data-toggle='modal'] *")) { + if (target.matches("[data-toggle='modal'] *")) { + target = target.closest("[data-toggle='modal']"); + } + var targetModal = document.getElementById(target.getAttribute("data-target")); + if (targetModal) { + if (targetModal.classList.contains("modal")) { + halfmoon.toggleModal(target.getAttribute("data-target")); + } + } + } + + // Handle clicks on modal dismiss buttons + if (target.matches(".modal [data-dismiss='modal']") || target.matches(".modal [data-dismiss='modal'] *")) { + if (target.matches(".modal [data-dismiss='modal'] *")) { + target = target.closest(".modal [data-dismiss='modal']"); + } + target.closest(".modal").classList.remove("show"); + } + + // Handle clicks on modal overlays + if (target.matches(".modal-dialog")) { + var parentModal = target.closest(".modal"); + + if (!parentModal.getAttribute("data-overlay-dismissal-disabled")) { + if (parentModal.classList.contains("show")) { + parentModal.classList.remove("show"); + } else { + window.location.hash = "#"; + } + } + } + + // Call the click handler method to handle any logic set by the user in their projects to handle clicks + halfmoon.clickHandler(eventCopy); + }, + false + ); + + // Adding the key down event listener (for shortcuts and accessibility) + document.addEventListener( + "keydown", + function(event) { + var eventCopy = event; + + // Shortcuts are triggered only if no input, textarea, or select has focus, + // If the control key or command key is not pressed down, + // And if the enabling data attribute is present on the DOM's body + if (!(document.querySelector("input:focus") || document.querySelector("textarea:focus") || document.querySelector("select:focus"))) { + event = event || window.event; + + if (!(event.ctrlKey || event.metaKey)) { + // Toggle sidebar when [shift] + [S] keys are pressed + if (document.body.getAttribute("data-sidebar-shortcut-enabled")) { + if (event.shiftKey && event.which == 83) { + // Variable to store whether a modal is open or not + var modalOpen = false; + + // Hash exists, so we check if it belongs to a modal + if (window.location.hash) { + var hash = window.location.hash.substring(1); + var elem = document.getElementById(hash); + if (elem) { + if (elem.classList.contains("modal")) { + modalOpen = true; + } + } + } + // Check for a modal with the .show class + if (document.querySelector(".modal.show")) { + modalOpen = true; + } + + // This shortcut works only if no modal is open + if (!modalOpen) { + halfmoon.toggleSidebar(); + event.preventDefault(); + } + } + } + + // Toggle dark mode when [shift] + [D] keys are pressed + if (document.body.getAttribute("data-dm-shortcut-enabled")) { + if (event.shiftKey && event.which == 68) { + halfmoon.toggleDarkMode(); + event.preventDefault(); + } + } + } + } + + // Handling other keydown events + if (event.which === 27) { + // Close dropdown menu (if one is open) when [esc] key is pressed + if (document.querySelector("[data-toggle='dropdown'].active")) { + var elem = document.querySelector("[data-toggle='dropdown'].active"); + elem.classList.remove("active"); + elem.closest(".dropdown").classList.remove("show"); + event.preventDefault(); + } + // Close modal (if one is open, and if no dropdown menu is open) when [esc] key is pressed + // Conditional on dropdowns so that dropdowns on modals can be closed with the keyboard without closing the modal + else { + // Hash exists, so we check if it belongs to a modal + if (window.location.hash) { + var hash = window.location.hash.substring(1); + var elem = document.getElementById(hash); + if (elem) { + if (elem.classList.contains("modal")) { + if (!elem.getAttribute("data-esc-dismissal-disabled")) { + window.location.hash = "#"; + event.preventDefault(); + } + } + } + } + // Check for a modal with the .show class + if (document.querySelector(".modal.show")) { + var elem = document.querySelector(".modal.show"); + if (!elem.getAttribute("data-esc-dismissal-disabled")) { + elem.classList.remove("show"); + event.preventDefault(); + } + } + } + } + + // Call the keydown handler method to handle any logic set by the user in their projects to handle keydown events + halfmoon.keydownHandler(eventCopy); + } + ); + + // Handling custom file inputs + var halfmoonCustomFileInputs = document.querySelectorAll(".custom-file input"); + for (var i = 0; i < halfmoonCustomFileInputs.length; i++) { + var customFile = halfmoonCustomFileInputs[i]; + // Create file name container element, add the class name, and set default value + // Append it to the custom file element + var fileNamesContainer = document.createElement("div"); + fileNamesContainer.classList.add("file-names"); + var dataDefaultValue = customFile.getAttribute("data-default-value"); + if (dataDefaultValue) { + fileNamesContainer.innerHTML = dataDefaultValue; + } else { + fileNamesContainer.innerHTML = "No file chosen"; + } + customFile.parentNode.appendChild(fileNamesContainer); + + // Add the event listener that will update the contents of the file name container element on change + customFile.addEventListener( + "change", + function(event) { + fileNamesContainer = event.target.parentNode.querySelector(".file-names"); + if (event.target.files.length === 1) { + fileNamesContainer.innerHTML = event.target.files[0].name; + } else if (event.target.files.length > 1) { + fileNamesContainer.innerHTML = event.target.files.length + " files"; + } else { + fileNamesContainer.innerHTML = "No file chosen"; + } + } + ); + } + + // Adding the .with-transitions class to the page-wrapper so that transitions are enabled + // This way, the weird bug on Chrome is avoided, where the transitions run on load + if (halfmoon.pageWrapper) { + halfmoon.pageWrapper.classList.add("with-transitions"); + } +} + +// Call the function when the DOM is loaded +document.addEventListener("DOMContentLoaded", halfmoonOnDOMContentLoaded); diff --git a/resources/HalfMoon/1.1.1/js/halfmoon.min.js b/resources/HalfMoon/1.1.1/js/halfmoon.min.js new file mode 100644 index 0000000..102ccec --- /dev/null +++ b/resources/HalfMoon/1.1.1/js/halfmoon.min.js @@ -0,0 +1,11 @@ +/* +* ----------------------------------------------------------------------------- +* Halfmoon JS +* Version: 1.1.1 +* https://www.gethalfmoon.com +* Copyright, Halfmoon UI +* Licensed under MIT (https://www.gethalfmoon.com/license) +* ----------------------------------------------------------------------------- +* The above notice must be included in its entirety when this file is used. +*/ +Element.prototype.matches||(Element.prototype.matches=Element.prototype.msMatchesSelector||Element.prototype.webkitMatchesSelector),Element.prototype.closest||(Element.prototype.closest=function(e){var t=this;do{if(t.matches(e))return t;t=t.parentElement||t.parentNode}while(null!==t&&1===t.nodeType);return null}),"document"in self&&("classList"in document.createElement("_")&&(!document.createElementNS||"classList"in document.createElementNS("http://www.w3.org/2000/svg","g"))||function(e){"use strict";if("Element"in e){var t="classList",o="prototype",a=e.Element[o],s=Object,n=String[o].trim||function(){return this.replace(/^\s+|\s+$/g,"")},i=Array[o].indexOf||function(e){for(var t=0,o=this.length;t"+o+""+t),r.classList.add("alert"),a&&r.classList.add(a),s&&r.classList.add(s),n&&(t=""+t),r.innerHTML=t,this.stickyAlerts.insertBefore(r,this.stickyAlerts.childNodes[0]),this.toastAlert(r.getAttribute("id"),i)},clickHandler:function(e){},keydownHandler:function(e){}};function halfmoonOnDOMContentLoaded(){halfmoon.pageWrapper||(halfmoon.pageWrapper=document.getElementsByClassName("page-wrapper")[0]),halfmoon.stickyAlerts||(halfmoon.stickyAlerts=document.getElementsByClassName("sticky-alerts")[0]),halfmoon.readCookie("halfmoon_preferredMode")?"dark-mode"==halfmoon.readCookie("halfmoon_preferredMode")?halfmoon.darkModeOn=!0:halfmoon.darkModeOn=!1:window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").matches||document.body.classList.contains("dark-mode")?halfmoon.darkModeOn=!0:halfmoon.darkModeOn=!1,(document.body.getAttribute("data-set-preferred-mode-onload")||document.body.getAttribute("data-set-preferred-theme-onload"))&&(halfmoon.darkModeOn?document.body.classList.contains("dark-mode")||document.body.classList.add("dark-mode"):document.body.classList.contains("dark-mode")&&document.body.classList.remove("dark-mode")),document.documentElement.clientWidth<=768?halfmoon.pageWrapper&&(halfmoon.pageWrapper.getAttribute("data-show-sidebar-onload-sm-and-down")||halfmoon.pageWrapper.setAttribute("data-sidebar-hidden","hidden")):halfmoon.pageWrapper&&"overlayed-all"===halfmoon.pageWrapper.getAttribute("data-sidebar-type")&&halfmoon.pageWrapper.setAttribute("data-sidebar-hidden","hidden"),document.addEventListener("click",function(e){var t,o,a=e,s=e.target;s.matches("[data-toggle='dropdown']")||s.matches("[data-toggle='dropdown'] *")?(s.matches("[data-toggle='dropdown'] *")&&(s=s.closest("[data-toggle='dropdown']")),s.classList.contains("active")?(s.classList.remove("active"),s.closest(".dropdown").classList.remove("show")):(halfmoon.deactivateAllDropdownToggles(),s.classList.add("active"),s.closest(".dropdown").classList.add("show"))):s.matches(".dropdown-menu *")||halfmoon.deactivateAllDropdownToggles(),(s.matches(".alert [data-dismiss='alert']")||s.matches(".alert [data-dismiss='alert'] *"))&&(s.matches(".alert [data-dismiss='alert'] *")&&(s=s.closest(".alert [data-dismiss='alert']")),s.parentNode.classList.add("dispose")),(s.matches("[data-toggle='modal']")||s.matches("[data-toggle='modal'] *"))&&(s.matches("[data-toggle='modal'] *")&&(s=s.closest("[data-toggle='modal']")),(t=document.getElementById(s.getAttribute("data-target")))&&t.classList.contains("modal")&&halfmoon.toggleModal(s.getAttribute("data-target"))),(s.matches(".modal [data-dismiss='modal']")||s.matches(".modal [data-dismiss='modal'] *"))&&(s.matches(".modal [data-dismiss='modal'] *")&&(s=s.closest(".modal [data-dismiss='modal']")),s.closest(".modal").classList.remove("show")),s.matches(".modal-dialog")&&((o=s.closest(".modal")).getAttribute("data-overlay-dismissal-disabled")||(o.classList.contains("show")?o.classList.remove("show"):window.location.hash="#")),halfmoon.clickHandler(a)},!1),document.addEventListener("keydown",function(e){var t,o,a,s=e;document.querySelector("input:focus")||document.querySelector("textarea:focus")||document.querySelector("select:focus")||(e=e||window.event).ctrlKey||e.metaKey||(document.body.getAttribute("data-sidebar-shortcut-enabled")&&e.shiftKey&&83==e.which&&(t=!1,window.location.hash&&(o=window.location.hash.substring(1),(a=document.getElementById(o))&&a.classList.contains("modal")&&(t=!0)),document.querySelector(".modal.show")&&(t=!0),t||(halfmoon.toggleSidebar(),e.preventDefault())),document.body.getAttribute("data-dm-shortcut-enabled")&&e.shiftKey&&68==e.which&&(halfmoon.toggleDarkMode(),e.preventDefault())),27===e.which&&(document.querySelector("[data-toggle='dropdown'].active")?((a=document.querySelector("[data-toggle='dropdown'].active")).classList.remove("active"),a.closest(".dropdown").classList.remove("show"),e.preventDefault()):(window.location.hash&&(o=window.location.hash.substring(1),(a=document.getElementById(o))&&a.classList.contains("modal")&&(a.getAttribute("data-esc-dismissal-disabled")||(window.location.hash="#",e.preventDefault()))),document.querySelector(".modal.show")&&((a=document.querySelector(".modal.show")).getAttribute("data-esc-dismissal-disabled")||(a.classList.remove("show"),e.preventDefault())))),halfmoon.keydownHandler(s)});for(var e=document.querySelectorAll(".custom-file input"),t=0;t + + + + + + + + + + + Starter template - Halfmoon + + + + + + + + + + +
+ + + +
+ + + + + + + + + + + + + +
+ +
+
+

Halfmoon starter template

+ + + + +
+ Toggles: + + +
+
+
+
+ + + + + +
+ + + + + + \ No newline at end of file diff --git a/resources/Quantum/readme.md b/resources/Quantum/readme.md index 34fc69a..b667563 100644 --- a/resources/Quantum/readme.md +++ b/resources/Quantum/readme.md @@ -1,2 +1,2 @@ # Quantum Font -100% font made by [sesohq](https://www.sesohq.com/) over at [sesohq.sellfy.store](https://sesohq.sellfy.store/p/3enu/). +100% free font made by [sesohq](https://www.sesohq.com/) over at [sesohq.sellfy.store](https://sesohq.sellfy.store/p/3enu/). diff --git a/robots.txt b/robots.txt index accc53f..286bf58 100644 --- a/robots.txt +++ b/robots.txt @@ -1,4 +1,4 @@ User-agent: * Allow: / -Sitemap: https://nibblepoker.lu/sitemap.xml +Sitemap: https://nibblepoker.lu/sitemap.txt