Compare commits

..

202 Commits

Author SHA1 Message Date
leosw
bef4998a64 tmp folder to public 2026-02-02 21:51:13 +01:00
leosw
d4f0f62a9a tmp folder to public 2026-02-02 21:50:12 +01:00
leosw
632dc3c0d6 Stats report in public folder 2026-02-02 21:48:27 +01:00
leosw
80c728ef5a Fix nginx config : POST requests redirected as POSTs 2026-02-02 21:44:50 +01:00
leosw
2b15b50b4b Add nginx config 2026-01-24 20:41:51 +01:00
27cd0b0d4d Merge pull request #17 from LeOSW42/copilot/recomment-css-html-files
Recomment all CSS and HTML templates
2026-01-24 19:41:07 +01:00
copilot-swe-agent[bot]
3159b34e70 Recomment CSS and HTML templates
Co-authored-by: LeOSW42 <673670+LeOSW42@users.noreply.github.com>
2026-01-24 18:35:07 +00:00
dd3fdd35a1 Merge pull request #18 from LeOSW42/copilot/update-link-access-method
Normalize routing base to drop /public from URLs
2026-01-24 19:23:29 +01:00
copilot-swe-agent[bot]
287fdf422d Remove public prefix in URLs
Co-authored-by: LeOSW42 <673670+LeOSW42@users.noreply.github.com>
2026-01-24 18:22:06 +00:00
copilot-swe-agent[bot]
99936d0baa Initial plan 2026-01-24 17:59:28 +00:00
copilot-swe-agent[bot]
8dd9897ca4 Initial plan 2026-01-24 17:57:57 +00:00
477880bdae Merge pull request #13 from LeOSW42/copilot/update-root-url-access
Serve Kabano from site root instead of /public
2026-01-24 17:45:06 +01:00
9ec3610e88 Merge pull request #12 from LeOSW42/copilot/comment-code-base
Document templates and styles with file headers
2026-01-24 17:44:16 +01:00
copilot-swe-agent[bot]
ce32d1b651 Serve Kabano from site root instead of /public
Co-authored-by: LeOSW42 <673670+LeOSW42@users.noreply.github.com>
2026-01-24 15:25:31 +00:00
copilot-swe-agent[bot]
41625ac443 Add header comments to HTML and CSS
Co-authored-by: LeOSW42 <673670+LeOSW42@users.noreply.github.com>
2026-01-24 15:18:15 +00:00
copilot-swe-agent[bot]
795ce6fc4e Initial plan 2026-01-24 15:11:57 +00:00
copilot-swe-agent[bot]
7f0143604c Add comments to PHP and JS files
Co-authored-by: LeOSW42 <673670+LeOSW42@users.noreply.github.com>
2026-01-24 15:11:48 +00:00
copilot-swe-agent[bot]
bb8e2d9746 Initial plan 2026-01-24 14:48:16 +00:00
2cec4bed5b Merge pull request #10 from LeOSW42/copilot/improve-project-structure
Restructure MVC layout into public/src with Core/Thirds/Controllers/Models
2026-01-24 15:47:18 +01:00
leosw
fe29b10a4c Merge remote-tracking branch 'github-mirror/master' into copilot/improve-project-structure 2026-01-24 15:45:28 +01:00
leosw
ad529d51bc Ressources to root 2026-01-24 15:42:25 +01:00
copilot-swe-agent[bot]
10aa54fd57 Rename MVC folders for consistency
Co-authored-by: LeOSW42 <673670+LeOSW42@users.noreply.github.com>
2026-01-24 14:29:09 +00:00
copilot-swe-agent[bot]
fd84530759 Refine config path resolution
Co-authored-by: LeOSW42 <673670+LeOSW42@users.noreply.github.com>
2026-01-24 14:05:09 +00:00
copilot-swe-agent[bot]
f617ecb350 Restructure MVC into public/src layout
Co-authored-by: LeOSW42 <673670+LeOSW42@users.noreply.github.com>
2026-01-24 14:00:58 +00:00
0f2a906d73 Merge pull request #9 from LeOSW42/copilot/improve-view-readability-again
Improve readability of POI, blog, and wiki views
2026-01-24 14:45:30 +01:00
copilot-swe-agent[bot]
1be6b7ff0c Initial plan 2026-01-24 13:42:37 +00:00
copilot-swe-agent[bot]
87d4889b96 Improve view readability in templates
Co-authored-by: LeOSW42 <673670+LeOSW42@users.noreply.github.com>
2026-01-24 13:41:18 +00:00
2947f03a0b Merge pull request #8 from LeOSW42/copilot/optimize-css-files
Consolidate shared CSS rules to reduce duplication
2026-01-24 14:40:53 +01:00
fd8958db9f Merge pull request #6 from LeOSW42/copilot/optimise-models-controllers
Renforce la sécurité des contrôleurs et modèles
2026-01-24 14:39:53 +01:00
copilot-swe-agent[bot]
f674f82658 Consolidate shared CSS rules
Co-authored-by: LeOSW42 <673670+LeOSW42@users.noreply.github.com>
2026-01-24 13:23:51 +00:00
copilot-swe-agent[bot]
c84ee486f3 Guard admin deletes against missing files
Co-authored-by: LeOSW42 <673670+LeOSW42@users.noreply.github.com>
2026-01-24 13:19:20 +00:00
copilot-swe-agent[bot]
0ef2679808 Harden controllers and password randomness
Co-authored-by: LeOSW42 <673670+LeOSW42@users.noreply.github.com>
2026-01-24 13:18:35 +00:00
copilot-swe-agent[bot]
0586a1b00d Initial plan 2026-01-24 13:05:45 +00:00
3886412382 Merge pull request #3 from LeOSW42/copilot/create-database-file-connection
Centralize PostgreSQL connection setup across models
2026-01-24 14:03:54 +01:00
copilot-swe-agent[bot]
dd4b945f5f Initial plan 2026-01-24 13:03:22 +00:00
copilot-swe-agent[bot]
fd29d07911 Initial plan 2026-01-24 13:02:37 +00:00
copilot-swe-agent[bot]
6051cf57d1 Simplify database connection helper
Co-authored-by: LeOSW42 <673670+LeOSW42@users.noreply.github.com>
2026-01-24 13:01:39 +00:00
d4c9d9ec5a Merge pull request #4 from LeOSW42/copilot/refactor-populate-function
Harden model population for safer data hydration
2026-01-24 14:00:58 +01:00
f2a7f863e0 Merge branch 'master' into copilot/refactor-populate-function 2026-01-24 14:00:36 +01:00
copilot-swe-agent[bot]
e925e6424a Refine SQL helper escaping
Co-authored-by: LeOSW42 <673670+LeOSW42@users.noreply.github.com>
2026-01-24 12:58:37 +00:00
copilot-swe-agent[bot]
894a107f4f Fix wiki comment typo
Co-authored-by: LeOSW42 <673670+LeOSW42@users.noreply.github.com>
2026-01-24 12:58:04 +00:00
copilot-swe-agent[bot]
89a41d52ae Harden model populate methods
Co-authored-by: LeOSW42 <673670+LeOSW42@users.noreply.github.com>
2026-01-24 12:57:05 +00:00
copilot-swe-agent[bot]
d2562a25df Restore safe connection quoting
Co-authored-by: LeOSW42 <673670+LeOSW42@users.noreply.github.com>
2026-01-24 12:54:31 +00:00
copilot-swe-agent[bot]
57a81bbed0 Use pg_escape_string for connection
Co-authored-by: LeOSW42 <673670+LeOSW42@users.noreply.github.com>
2026-01-24 12:52:12 +00:00
1e8c3c5869 Merge branch 'master' into copilot/create-database-file-connection 2026-01-24 13:52:01 +01:00
copilot-swe-agent[bot]
419d95eb4c Refine SQL connection escaping
Co-authored-by: LeOSW42 <673670+LeOSW42@users.noreply.github.com>
2026-01-24 12:50:40 +00:00
copilot-swe-agent[bot]
f744aaaed1 Harden database helper
Co-authored-by: LeOSW42 <673670+LeOSW42@users.noreply.github.com>
2026-01-24 12:49:21 +00:00
cb3d786806 Remove ?> 2026-01-24 13:48:33 +01:00
copilot-swe-agent[bot]
92555ea2bf Centralize SQL connections
Co-authored-by: LeOSW42 <673670+LeOSW42@users.noreply.github.com>
2026-01-24 12:48:16 +00:00
cc908e7c06 Merge pull request #5 from LeOSW42/copilot/replace-short-tags-to-php
Copilot/replace short tags to php
2026-01-24 13:47:53 +01:00
leosw
0a3ad91db9 Merge branch 'master' into copilot/replace-short-tags-to-php 2026-01-24 13:47:40 +01:00
leosw
3642288a5b Merge pull request #2 from LeOSW42/copilot/remove-end-file-php-tags
Remove trailing PHP closing tags
2026-01-24 13:43:41 +01:00
copilot-swe-agent[bot]
9728aefc07 Replace PHP short tags
Co-authored-by: LeOSW42 <673670+LeOSW42@users.noreply.github.com>
2026-01-24 12:42:17 +00:00
copilot-swe-agent[bot]
a4082524d4 Remove PHP closing tags from app files
Co-authored-by: LeOSW42 <673670+LeOSW42@users.noreply.github.com>
2026-01-24 12:39:54 +00:00
copilot-swe-agent[bot]
2f58db6643 Initial plan 2026-01-24 12:39:41 +00:00
copilot-swe-agent[bot]
811d5d47f3 Remove PHP closing tags from includes
Co-authored-by: LeOSW42 <673670+LeOSW42@users.noreply.github.com>
2026-01-24 12:39:27 +00:00
copilot-swe-agent[bot]
041e77246f Initial plan 2026-01-24 12:36:51 +00:00
copilot-swe-agent[bot]
3bdf66f832 Initial plan 2026-01-24 12:35:57 +00:00
copilot-swe-agent[bot]
ff8516665c Initial plan 2026-01-24 12:28:39 +00:00
ba230d192f Update index.php file 2026-01-24 13:26:50 +01:00
leosw
aa285952b6 Bug de l'altitude nulle 2026-01-20 22:09:38 +01:00
leosw
012ead1ff9 Champ nouveau commentaire 2026-01-20 21:57:31 +01:00
leosw
4eef5c1028 Commentaires obligés sur les POIs 2026-01-20 21:53:09 +01:00
leosw
c96aca2bf4 Points cachés affichés aux premiums sur la carte 2026-01-20 20:22:02 +01:00
leosw
5f07c557f5 Correction des erreurs dans l'édition des booléens 2026-01-20 20:15:50 +01:00
leosw
04ecae8211 Premier jet de la carte des POIs 2026-01-19 20:38:02 +01:00
leosw
e1aa647fce Commentaires d'un POI et correction booléens 2026-01-19 20:16:54 +01:00
leosw
f8662f69bd Fix elevation proxy call 2026-01-19 19:04:42 +01:00
leosw
77e3c02da8 Fix l'icone dans la page d'edition 2026-01-19 19:01:56 +01:00
leosw
454ccb7a65 La mise à jour d'un POI est cassée, le proxy élévation est cassé 2026-01-18 20:07:49 +01:00
leosw
0f502d6536 View of a POI is working fine 2026-01-18 19:40:59 +01:00
leosw
d2b4f38f0b View d'un poi qui fonctionne pour les infos principales 2026-01-18 18:37:39 +01:00
leosw
9f3bb76276 Mise en forme du titre d'un poi 2026-01-18 18:19:42 +01:00
leosw
58b180a740 Première version de la vue d'un POI 2026-01-18 17:55:43 +01:00
leosw
a6c0e06d78 Getion des commentaires dans un modèle spécial 2026-01-18 15:51:59 +01:00
leosw
9657093edd Formulaire d'ajout de POI qui fonctionne 2026-01-18 15:21:44 +01:00
leosw
60ae51429b Modele SQL avec tables pré-remplies 2026-01-18 15:21:19 +01:00
leosw
69ab7ce1fb Deuxième jet POI avec cohérence globale mais formulaire pas vraiment envoyé 2026-01-18 15:09:42 +01:00
leosw
397f8b770a Petites sécurités blgo & wiki 2026-01-18 15:09:09 +01:00
leosw
25fa59cddf Premier jet insert POI 2026-01-18 14:42:59 +01:00
leosw
7bfdabcd28 Fix erreur dans le chainage SQL des IDs du blog contributors 2026-01-18 14:42:28 +01:00
leosw
dcece39af4 Modif SQL 2026-01-18 14:29:57 +01:00
leosw
f4490af929 Simplification du modèle squelette 2026-01-18 14:21:43 +01:00
leosw
9acbea54e6 Modif BDD pour sous-type poi 2026-01-18 13:25:50 +01:00
leosw
dd333fc2aa Correction de la modif de l'attribut "is_commentable" dans le blog 2026-01-18 13:10:57 +01:00
leosw
0ee127ca3f Erreurs PHP sur variables dynamiques 2026-01-18 12:53:38 +01:00
leosw
7d39b5295a Changement du modèle SQL : le contenu de content_version est désormais en json (pour pouvoir recevoir les POI), et on a créé la base pour la géométrie à venir des POIs 2026-01-18 12:10:39 +01:00
leosw
49e83aef49 La mise à jour affichera les erreurs 2025-12-28 12:26:18 +01:00
leosw
3996b79cf9 revert test 2025-12-26 14:57:24 +01:00
leosw
587572297d test 2025-12-26 14:55:30 +01:00
leosw
5c34318982 Fix stats command 2025-12-26 14:50:50 +01:00
leosw
8c66a92e39 Changement lien facebook 2025-09-20 12:37:08 +02:00
leosw
20c2c24988 Style hérité du wiki dans le blog 2025-08-30 18:18:47 +02:00
leosw
991fff087e Sauvegarde des fichiers medias 2025-08-30 17:45:56 +02:00
leosw
029635e509 Fix gitignore 2025-08-30 13:44:57 +02:00
leosw
be0bd0195a Sauvegarde SQL 2025-08-30 13:43:03 +02:00
leosw
5c228c9533 Fix all stats 2025-08-30 12:52:22 +02:00
leosw
723b81aebd debug 2025-08-30 12:50:46 +02:00
leosw
1e5d1a7cc9 debug 2025-08-30 12:49:31 +02:00
leosw
16ca71e399 debug 2025-08-30 12:39:24 +02:00
leosw
df2e08f54a debug 2025-08-30 12:38:20 +02:00
leosw
114c971184 debug 2025-08-30 12:36:23 +02:00
leosw
d3c2987c9b remove debug 2025-08-30 12:33:41 +02:00
leosw
c7aa53b1f0 debug 2025-08-30 12:31:42 +02:00
leosw
159f21d5b2 debug 2025-08-30 12:17:55 +02:00
leosw
5080425824 debug 2025-08-30 12:10:42 +02:00
leosw
e4983112db debug 2025-08-30 12:08:50 +02:00
leosw
f4325d3a5a debug 2025-08-30 12:08:14 +02:00
leosw
6bdbcec947 Nouvel essai avec un glob 2025-08-30 12:05:22 +02:00
leosw
79a33031d6 debug 2025-08-30 11:57:28 +02:00
leosw
6aad02ce2d Stats: correction nom fichier 2025-08-30 11:50:25 +02:00
leosw
810207ef9b Stats : meilleure gestion de l'affichage 2025-08-30 11:49:29 +02:00
leosw
363df1ab75 Stats : Commande plus robuste pour récupérer l'affichage 2025-08-30 11:48:41 +02:00
leosw
b866cc890e Pas de ncurse dans goaccess 2025-08-30 11:46:17 +02:00
leosw
6b3edaed02 revert debug 2025-08-30 11:43:16 +02:00
leosw
a8bc3e7ef7 debug 2025-08-30 11:41:21 +02:00
leosw
bd8786daed debug 2025-08-30 11:40:30 +02:00
leosw
f284c1883c Revert droit d'admin 2025-08-30 11:37:11 +02:00
leosw
c4c91315ec Générer les stats comme sudo 2025-08-30 11:32:50 +02:00
leosw
f845eb3ef4 Gestion d'erreur sur les stats 2025-08-30 11:29:17 +02:00
leosw
06bf74ea21 Page statistiques 2025-08-30 11:24:04 +02:00
leosw
10a72dcdb9 Changement lieu fab dans mail 2025-08-18 20:00:54 +02:00
leosw
86fad21898 Point qui traine 2025-08-18 19:49:28 +02:00
leosw
83df17669d Ajout d'un avertissement sur la page carte 2025-08-18 18:56:59 +02:00
leosw
54226e3cbd Correction sur les formulaires sur mobile 2025-08-18 18:48:05 +02:00
leosw
fd76affce9 Ajout CGV 2025-08-18 18:36:46 +02:00
leosw
4eb8f685c5 Correction du pied de page sur la page carte 2025-08-18 18:14:11 +02:00
leosw
2801ddf144 Correction du footer sur la page carte 2025-08-18 17:54:41 +02:00
leosw
d75de36d61 Dernière version du menu corrigé 2025-08-18 17:38:36 +02:00
leosw
208e3132ad Test sur le menu 2025-08-18 17:24:23 +02:00
leosw
d744317283 Ajout d'un menu responsive 2025-08-18 17:15:58 +02:00
leosw
e3de743bb8 Fix la nav sur mobile 2025-08-17 22:45:00 +02:00
leosw
acfb15d5e3 Ajout d'une lightbox pour les portfolio 2025-08-17 22:08:51 +02:00
leosw
4e1f6a9083 Style pour les images dans le wiki 2025-08-03 22:15:21 +02:00
leosw
bb365942ab Log les uploads 2025-08-02 15:06:11 +02:00
leosw
42a3aa08f5 Ajout d'un formulaire d'envoi de fichiers 2025-08-02 15:00:19 +02:00
leosw
d9963bf64b Limiter la supressions aux admins 2025-08-02 14:09:36 +02:00
leosw
6137f6a027 Ajout du logging des fichiers effacés 2025-08-02 14:05:07 +02:00
leosw
f874f6b17e Amélioration de la cliquabilité 2025-08-02 14:00:38 +02:00
leosw
f9f6debe65 Ajout de la fonctionnalité de suppression de fichiers 2025-08-02 13:57:28 +02:00
leosw
ca25bccbec Fixe 2025-08-02 13:40:54 +02:00
leosw
74b3a8721a Mise en forme du tableau 2025-08-02 13:31:38 +02:00
leosw
23f8123718 Ajout d'un système de listing des fichiers de dossier /medias/wiki 2025-08-02 13:16:50 +02:00
leosw
98103c096e Le contenu spécial de la page d'accueil est déplacé dans le wiki (y compris le CSS) 2025-08-02 11:03:39 +02:00
leosw
6340175e44 Typo 2025-08-02 10:45:36 +02:00
leosw
92e21aa959 L'accueil est géré en markdown 2025-07-16 19:53:24 +02:00
leosw
c77b9e524d Mise à jour des headers 2025-07-16 19:46:35 +02:00
leosw
f1ae1d174e ajout téléphone 2025-07-13 18:37:50 +02:00
leosw
ceda4b4d22 typo 2025-07-13 18:24:37 +02:00
leosw
d2b556dec7 Typo 2025-07-13 18:23:51 +02:00
leosw
67b1b3c9e5 Fix map 2025-07-13 18:05:46 +02:00
leosw
391cfc1273 Suppression vieilles images 2025-07-13 17:58:08 +02:00
leosw
a53ddf22ff Ajout de la page d'accueil et typos 2025-07-13 17:57:45 +02:00
leosw
238eebc00b La page d'accueil est désormais fournie par une page du wiki spécifique 2025-07-13 16:10:30 +02:00
leosw
bc44a41106 Fix blanc après footer 2025-07-13 15:48:38 +02:00
leosw
4ab51c9687 Ajout lien fb en pied de page 2025-07-13 15:46:45 +02:00
leosw
613776264c Changement du menu pour mes nouvelles activités 2025-07-13 15:10:56 +02:00
leosw
687de1ed71 Ajout des logos carrés et d'un meilleur support du redimentionnement d'images 2025-07-13 14:27:10 +02:00
leosw
36be8018b4 ajout du support pout php 8.2 en supprimant la création de propriétés dynamiques 2025-07-13 14:14:16 +02:00
Léo Serre
8490877990 Fix HTML in blog comments 2022-02-02 11:01:41 +00:00
leosw
662f72a006 Fix dates in php < 8.0.0 2022-02-01 22:39:26 +01:00
leosw
f60cf54bab User can change his timezone 2022-02-01 22:35:08 +01:00
leosw
507bf492a0 First support for timezones on date displays 2022-02-01 22:25:52 +01:00
leosw
af4103c31c Change date to relative : can now be yesterday or today 2022-02-01 21:36:29 +01:00
leosw
36a42bb4f6 Upgrades SQL skeleton 2022-02-01 21:13:54 +01:00
leosw
7ec61dbc63 Add support for user defined locale and timezone in date/time prints, remove deprecated PHP strftime 2022-02-01 21:13:27 +01:00
leosw
3a497bbb64 Fix round background for radio buttons 2021-08-19 18:57:36 +02:00
leosw
fbdc2485aa Add static placeholder in poi permalink field 2021-08-19 18:36:06 +02:00
leosw
dfa4dccd6c Add static placeholder in blog permalink field 2021-08-19 18:24:52 +02:00
leosw
da27362fd5 Fix permalink processing for pois 2021-06-04 21:36:10 +02:00
leosw
f0b82ddb3d Add permalink field in poi new form 2021-06-04 20:56:48 +02:00
leosw
5c2f9dda2a Small fix 2021-06-04 20:51:53 +02:00
leosw
aeebd5999d Fix in community portal height 2021-06-04 20:44:35 +02:00
leosw
9a6a453351 Add map legend 2021-06-04 20:40:00 +02:00
leosw
62dd5d4c5e Add required options in new poi form 2021-06-04 20:16:25 +02:00
leosw
896a022fce Revert small cosmetic issue 2021-06-02 21:22:49 +02:00
leosw
403947a6e4 Fix issue in header input forms dropdown down suggestion: applies hover selector 2021-06-02 21:10:12 +02:00
leosw
b776e4f41c Fix #2: Change opacity of not public articles in list 2021-05-28 22:37:05 +02:00
leosw
9b9654745f Minor change 2021-05-28 22:29:38 +02:00
leosw
4fd3b12f90 Add alert in case the form is edited and the type changes before submitting 2021-05-28 22:26:14 +02:00
leosw
5b8dbc0797 Changes input fields to correct HTML5 types 2021-05-28 21:13:34 +02:00
leosw
59303dc737 Changes input fields to correct HTML5 types 2021-05-28 21:11:07 +02:00
leosw
072ef1d43e Add support for all types in new poi form 2021-05-28 20:58:22 +02:00
leosw
0f8259fe43 Add first support for booleans in specific poi form section 2021-05-25 22:53:22 +02:00
leosw
26ddc99766 Change order in poi edit: coordinates before type selector 2021-05-25 19:54:52 +02:00
leosw
35281f4e30 Adding SQL's "parameters" field skeleton in POI model file 2021-05-25 19:46:23 +02:00
leosw
8397c032ef Fix blog articles rights 2021-05-24 00:01:11 +02:00
leosw
5bf22fe9cc Fix RSS date 2021-05-23 23:55:35 +02:00
leosw
eef50bc37f Enable log viewer 2021-05-23 23:37:53 +02:00
leosw
320d7dfa7e Remove not ready links in nav bar 2021-05-23 23:21:04 +02:00
leosw
1c2e1b6fcb Hide insignificant trailing zeros in coordinates 2021-05-19 23:11:53 +02:00
leosw
4816d14faa Display elevation APi button only if coordinates are valids 2021-05-19 23:09:01 +02:00
leosw
1c90c9ddab Adding the elevation API in poi edit form 2021-05-19 22:44:52 +02:00
leosw
428ce900f0 Limits the coordinate precision to 6 digits: ~ 0.1 meter max 2021-05-19 20:34:02 +02:00
leosw
82f334143f Fix, replace IGN map by ortophoto 2021-03-29 23:48:13 +02:00
leosw
861131b98f Fix, replace IGN map by plan 2021-03-29 23:42:20 +02:00
leosw
8a37b9f902 Add IGN base layer 2021-03-29 23:33:49 +02:00
leosw
b16469cf34 Fix tilesize for maptiler tiles 2021-03-29 23:26:15 +02:00
leosw
a088d1f3ca Upgrade leaflet from 1.3.4 to 1.7.1 2021-03-29 23:19:49 +02:00
leosw
592d7852f8 test git hook 2021-03-28 22:44:22 +02:00
leosw
082ae890a0 Fix typo in map credits 2021-03-27 18:41:16 +01:00
leosw
a3a125f18f Add TMS world server 2021-03-27 18:39:39 +01:00
162 changed files with 5862 additions and 3815 deletions

11
.gitignore vendored
View File

@@ -1,7 +1,8 @@
/includes/config.php /src/Core/config.php
/medias/* /public/medias/*
/_maps /public/_maps
_ressources/dump.sql /public/_ressources/dump.sql
*.sublime-project *.sublime-project
*.sublime-workspace *.sublime-workspace
*.log *.log
/tmp/*

9
.htaccess Executable file → Normal file
View File

@@ -1,11 +1,6 @@
AddDefaultCharset UTF-8
RewriteEngine On RewriteEngine On
# Everything uses the routing system RewriteRule ^public(/.*)?$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l RewriteRule ^(.*)$ public/$1 [L]
RewriteRule . ./index.php [L]
php_value short_open_tag 1

View File

@@ -1 +1,12 @@
[Kabano website](https://kabano.org/) [Kabano website](https://kabano.org/)
## Arborescence
- `public/` : assets frontend et point d'entrée web (`index.php`, `views/`, `_ressources/`)
- `src/` : code backend commun
- `Core/` : configuration et utilitaires communs (ancien `includes/`)
- `Controllers/` : contrôleurs MVC backend (ancien `controllers/`)
- `Models/` : modèles MVC backend (ancien `models/`)
- `Thirds/` : dépendances tierces backend (ancien `third/`)
Note: configure the web server at the repository root; requests to `/` are routed to `public/` via `.htaccess`, and URLs are generated from the app root.

View File

@@ -1,116 +0,0 @@
# Database structure for kabano.org open-source project
# This file is designed to be imported in quickdatabasediagrams.com
locales
-
name PK varchar(32)
display_name UNIQUE varchar(255)
flag_name UNIQUE NULL varchar(32)
users
-
id PK int4
name UNIQUE varchar(255) # The unique constraint is done with version
version UNIQUE int4 # The unique constraint is done with name
email UNIQUE varchar(255)
password varchar(255)
website NULL varchar(255)
is_avatar_present boolean
is_archive INDEX boolean
rank user_rank_enum # blocked; registered; premium; moderator; admin
locale varchar(32) FK >- locales.name
timezone varchar(8)
visit_date timestamp
register_date INDEX timestamp
pois
-
id PK int4
permalink UNIQUE varchar(255) # The unique constraint is done with version
version UNIQUE int4 # The unique constraint is done with permalink
creation_date timestamp
update_date timestamp
author int4 FK >- users.id
is_public INDEX boolean
is_archive INDEX boolean
type INDEX poi_type_enum # basic_hut; wilderness_hut; alpine_hut; halt; bivouac; campsite
is_destroyed INDEX boolean
name varchar(255)
alt_names NULL varchar(255)
source NULL varchar(3) FK >- poi_sources.id
source_id NULL varchar(255)
position geometry # Contains elevation data
parameters NULL jsonb
poi_localised
-
id PK int4
poi UNIQUE int4 FK >- pois.id # The unique constraint is done with locale, key
locale UNIQUE varchar(32) FK >- locales.name # The unique constraint is done with poi, key
key UNIQUE poi_key_enum # description; access # The unique constraint is done with poi, locale
value text
poi_sources
-
id PK varchar(3)
display_name UNIQUE varchar(255)
icon_name NULL varchar(255)
website NULL varchar(255)
license_name NULL varchar(255)
license_url NULL varchar(255)
poi_contributors
-
id PK int4
poi UNIQUE int4 FK >- pois.id # The unique constraint is done with contributor
contributor UNIQUE int4 FK >- users.id # The unique constraint is done with poi
poi_comments
-
id PK int4
permalink UNIQUE varchar(255) # The unique constraint is done with version
version UNIQUE int4 # The unique constraint is done with permalink
creation_date timestamp
update_date timestamp
author int4 FK >- users.id
is_public INDEX boolean
is_archive INDEX boolean
poi int4 FK >- pois.id
comment text
locale varchar(32) FK >- locales.name
contents
-
id PK int4
permalink UNIQUE varchar(255) # The unique constraint is done with version and locale
version UNIQUE int4 # The unique constraint is done with permalink and locale
locale UNIQUE varchar(32) FK >- locales.name # The unique constraint is done with permalink and version
creation_date timestamp
update_date timestamp
author int4 FK >- users.id
is_public INDEX boolean
is_archive INDEX boolean
is_commentable boolean
type INDEX content_type_enum # wiki, blog, forum
name varchar(255)
content text
content_contributors
-
id PK int4
content UNIQUE int4 FK >- contents.id # The unique constraint is done with contributor
contributor UNIQUE int4 FK >- users.id # The unique constraint is done with content
content_comments
-
id PK int4
permalink UNIQUE varchar(255) # The unique constraint is done with version
version UNIQUE int4 # The unique constraint is done with permalink
creation_date timestamp
update_date timestamp
author int4 FK >- users.id
is_public INDEX boolean
is_archive INDEX boolean
content int4 FK >- contents.id
comment text
locale varchar(32) FK >- locales.name

View File

@@ -1,882 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
CAUTION: Do not modify this file unless you know what you are doing.
Unexpected results may occur if the code is changed deliberately.
-->
<dbmodel pgmodeler-ver="0.9.2-alpha1" last-position="0,998" last-zoom="0.9" max-obj-count="24"
default-owner="postgres">
<role name="kabano"
inherit="true"
login="true"
encrypted="true"
password="********">
</role>
<database name="kabano" encoding="UTF8" lc-collate="fr_FR.UTF-8" lc-ctype="fr_FR.UTF-8" is-template="false" allow-conns="true">
<role name="kabano"/>
<tablespace name="pg_default"/>
</database>
<schema name="public" layer="0" rect-visible="true" fill-color="#e1e1e1" sql-disabled="true">
</schema>
<schema name="topology" layer="0" rect-visible="true" fill-color="#c8e6ff">
<role name="kabano"/>
<comment><![CDATA[PostGIS Topology schema]]></comment>
</schema>
<extension name="postgis" cur-version="2.5.1">
<schema name="public"/>
<comment><![CDATA[PostGIS geometry, geography, and raster spatial types and functions]]></comment>
</extension>
<extension name="postgis_topology" cur-version="2.5.1">
<schema name="topology"/>
<comment><![CDATA[PostGIS topology spatial types and functions]]></comment>
</extension>
<usertype name="content_type_enum" configuration="enumeration">
<schema name="public"/>
<role name="kabano"/>
<enumeration values="wiki,blog,forum"/>
</usertype>
<usertype name="poi_type_enum" configuration="enumeration">
<schema name="public"/>
<role name="kabano"/>
<enumeration values="basic_hut,wilderness_hut,alpine_hut,halt,bivouac,campsite"/>
</usertype>
<usertype name="user_rank_enum" configuration="enumeration">
<schema name="public"/>
<role name="kabano"/>
<enumeration values="blocked,registered,premium,moderator,administrator,visitor"/>
</usertype>
<sequence name="content_comments_sequence" cycle="false" start="1" increment="1" min-value="1" max-value="9223372036854775807" cache="1">
<schema name="public"/>
<role name="kabano"/>
</sequence>
<table name="content_comments" layer="0" collapse-mode="2" max-obj-count="12">
<schema name="public"/>
<role name="kabano"/>
<position x="540" y="340"/>
<column name="id" not-null="true" sequence="public.content_comments_sequence">
<type name="integer" length="0"/>
</column>
<column name="version">
<type name="integer" length="0"/>
</column>
<column name="creation_date">
<type name="timestamp" length="0"/>
</column>
<column name="update_date">
<type name="timestamp" length="0"/>
</column>
<column name="author">
<type name="integer" length="0"/>
</column>
<column name="is_public">
<type name="boolean" length="0"/>
</column>
<column name="is_archive">
<type name="boolean" length="0"/>
</column>
<column name="content">
<type name="integer" length="0"/>
</column>
<column name="comment">
<type name="text" length="0"/>
</column>
<column name="locale">
<type name="character varying" length="32"/>
</column>
<constraint name="content_comments_pkey" type="pk-constr" table="public.content_comments">
<columns names="id" ref-type="src-columns"/>
</constraint>
</table>
<sequence name="content_contributors_sequence" cycle="false" start="1" increment="1" min-value="1" max-value="9223372036854775807" cache="1">
<schema name="public"/>
<role name="kabano"/>
</sequence>
<table name="content_contributors" layer="0" collapse-mode="2" max-obj-count="4">
<schema name="public"/>
<role name="kabano"/>
<position x="1460" y="300"/>
<column name="id" not-null="true" sequence="public.content_contributors_sequence">
<type name="integer" length="0"/>
</column>
<column name="content">
<type name="integer" length="0"/>
</column>
<column name="contributor">
<type name="integer" length="0"/>
</column>
<constraint name="content_contributors_pkey" type="pk-constr" table="public.content_contributors">
<columns names="id" ref-type="src-columns"/>
</constraint>
<constraint name="content_contributors_unique" type="uq-constr" table="public.content_contributors">
<columns names="content,contributor" ref-type="src-columns"/>
</constraint>
</table>
<sequence name="contents_sequence" cycle="false" start="1" increment="1" min-value="1" max-value="9223372036854775807" cache="1">
<schema name="public"/>
<role name="kabano"/>
</sequence>
<table name="contents" layer="0" collapse-mode="2" max-obj-count="7">
<schema name="public"/>
<role name="kabano"/>
<position x="540" y="60"/>
<column name="id" not-null="true" sequence="public.contents_sequence">
<type name="integer" length="0"/>
</column>
<column name="permalink" not-null="true">
<type name="character varying" length="255"/>
</column>
<column name="creation_date" not-null="true">
<type name="timestamp" length="0"/>
</column>
<column name="is_public" not-null="true" default-value="true">
<type name="boolean" length="0"/>
</column>
<column name="is_commentable" not-null="true" default-value="true">
<type name="boolean" length="0"/>
</column>
<column name="type" not-null="true">
<type name="public.content_type_enum" length="0"/>
</column>
<constraint name="contents_pkey" type="pk-constr" table="public.contents">
<columns names="id" ref-type="src-columns"/>
</constraint>
<constraint name="contents_permalink_type_key" type="uq-constr" table="public.contents">
<columns names="permalink,type" ref-type="src-columns"/>
</constraint>
</table>
<table name="locales" layer="0" collapse-mode="2" max-obj-count="3">
<schema name="public"/>
<role name="kabano"/>
<position x="700" y="800"/>
<column name="name" not-null="true">
<type name="character varying" length="32"/>
</column>
<column name="display_name" not-null="true">
<type name="character varying" length="255"/>
</column>
<column name="flag_name">
<type name="character varying" length="32"/>
</column>
<constraint name="locales_display_name_unique" type="uq-constr" table="public.locales">
<columns names="display_name" ref-type="src-columns"/>
</constraint>
<constraint name="locales_flag_name_unique" type="uq-constr" table="public.locales">
<columns names="flag_name" ref-type="src-columns"/>
</constraint>
<constraint name="locales_pkey" type="pk-constr" table="public.locales">
<columns names="name" ref-type="src-columns"/>
</constraint>
</table>
<sequence name="poi_comments_sequence" cycle="false" start="1" increment="1" min-value="1" max-value="9223372036854775807" cache="1">
<schema name="public"/>
<role name="kabano"/>
</sequence>
<table name="poi_comments" layer="0" collapse-mode="2" max-obj-count="13">
<schema name="public"/>
<role name="kabano"/>
<position x="1100" y="980"/>
<column name="id" not-null="true" sequence="public.poi_comments_sequence">
<type name="integer" length="0"/>
</column>
<column name="permalink">
<type name="character varying" length="255"/>
</column>
<column name="version">
<type name="integer" length="0"/>
</column>
<column name="creation_date">
<type name="timestamp" length="0"/>
</column>
<column name="update_date">
<type name="timestamp" length="0"/>
</column>
<column name="author">
<type name="integer" length="0"/>
</column>
<column name="is_public">
<type name="boolean" length="0"/>
</column>
<column name="is_archive">
<type name="boolean" length="0"/>
</column>
<column name="poi">
<type name="integer" length="0"/>
</column>
<column name="comment">
<type name="text" length="0"/>
</column>
<column name="locale">
<type name="character varying" length="32"/>
</column>
<constraint name="poi_comments_permalink_version_key" type="uq-constr" table="public.poi_comments">
<columns names="permalink,version" ref-type="src-columns"/>
</constraint>
<constraint name="poi_comments_pkey" type="pk-constr" table="public.poi_comments">
<columns names="id" ref-type="src-columns"/>
</constraint>
</table>
<sequence name="poi_contributors_sequence" cycle="false" start="1" increment="1" min-value="1" max-value="9223372036854775807" cache="1">
<schema name="public"/>
<role name="kabano"/>
</sequence>
<table name="poi_contributors" layer="0" collapse-mode="2" max-obj-count="4">
<schema name="public"/>
<role name="kabano"/>
<position x="1560" y="820"/>
<column name="id" not-null="true" sequence="public.poi_contributors_sequence">
<type name="integer" length="0"/>
</column>
<column name="poi">
<type name="integer" length="0"/>
</column>
<column name="contributor">
<type name="integer" length="0"/>
</column>
<constraint name="poi_contributors_pkey" type="pk-constr" table="public.poi_contributors">
<columns names="id" ref-type="src-columns"/>
</constraint>
<constraint name="poi_contributors_unique" type="uq-constr" table="public.poi_contributors">
<columns names="poi,contributor" ref-type="src-columns"/>
</constraint>
</table>
<sequence name="poi_locales_sequence" cycle="false" start="1" increment="1" min-value="1" max-value="9223372036854775807" cache="1">
<schema name="public"/>
<role name="kabano"/>
</sequence>
<table name="poi_locales" layer="0" collapse-mode="2" max-obj-count="4">
<schema name="public"/>
<role name="kabano"/>
<position x="720" y="1340"/>
<column name="id" not-null="true" default-value="nextval('poi_locales_sequence'::regclass)">
<type name="integer" length="0"/>
</column>
<column name="locale" not-null="true">
<type name="character varying" length="32"/>
</column>
<column name="poi_id" not-null="true">
<type name="integer" length="0"/>
</column>
<constraint name="poi_localised_pkey" type="pk-constr" table="public.poi_locales">
<columns names="id" ref-type="src-columns"/>
</constraint>
<constraint name="poi_localised_unique" type="uq-constr" table="public.poi_locales">
<columns names="locale,poi_id" ref-type="src-columns"/>
</constraint>
</table>
<table name="sources" layer="0" collapse-mode="2" max-obj-count="7">
<schema name="public"/>
<role name="kabano"/>
<position x="1160" y="1660"/>
<column name="id" not-null="true">
<type name="character varying" length="3"/>
</column>
<column name="display_name" not-null="true">
<type name="character varying" length="255"/>
</column>
<column name="icon_name">
<type name="character varying" length="255"/>
</column>
<column name="website">
<type name="character varying" length="255"/>
</column>
<column name="license_name">
<type name="character varying" length="255"/>
</column>
<column name="license_url">
<type name="character varying" length="255"/>
</column>
<constraint name="sources_display_name_unique" type="uq-constr" table="public.sources">
<columns names="display_name" ref-type="src-columns"/>
</constraint>
<constraint name="sources_pkey" type="pk-constr" table="public.sources">
<columns names="id" ref-type="src-columns"/>
</constraint>
</table>
<sequence name="poi_versions_sequence" cycle="false" start="1" increment="1" min-value="1" max-value="9223372036854775807" cache="1">
<schema name="public"/>
<role name="kabano"/>
</sequence>
<sequence name="pois_sequence" cycle="false" start="1" increment="1" min-value="1" max-value="9223372036854775807" cache="1">
<schema name="public"/>
<role name="kabano"/>
</sequence>
<sequence name="users_id_sequence" cycle="false" start="1" increment="1" min-value="1" max-value="9223372036854775807" cache="1">
<schema name="public"/>
<role name="kabano"/>
</sequence>
<table name="users" layer="0" collapse-mode="2" max-obj-count="15">
<schema name="public"/>
<role name="kabano"/>
<position x="1140" y="540"/>
<column name="id" not-null="true" sequence="public.users_id_sequence">
<type name="integer" length="0"/>
</column>
<column name="name" not-null="true">
<type name="character varying" length="255"/>
</column>
<column name="version" not-null="true" default-value="0">
<type name="integer" length="0"/>
</column>
<column name="email" not-null="true">
<type name="character varying" length="255"/>
</column>
<column name="password" not-null="true">
<type name="character varying" length="255"/>
</column>
<column name="website">
<type name="character varying" length="255"/>
</column>
<column name="is_avatar_present" not-null="true">
<type name="boolean" length="0"/>
</column>
<column name="is_archive" not-null="true">
<type name="boolean" length="0"/>
</column>
<column name="rank" not-null="true">
<type name="public.user_rank_enum" length="0"/>
</column>
<column name="locale" not-null="true">
<type name="character varying" length="32"/>
</column>
<column name="timezone" not-null="true">
<type name="character varying" length="8"/>
</column>
<column name="visit_date" not-null="true">
<type name="timestamp" length="0"/>
</column>
<column name="register_date" not-null="true">
<type name="timestamp" length="0"/>
</column>
<constraint name="users_email_unique" type="uq-constr" table="public.users">
<columns names="email" ref-type="src-columns"/>
</constraint>
<constraint name="users_name_unique" type="uq-constr" table="public.users">
<columns names="name,version" ref-type="src-columns"/>
</constraint>
<constraint name="users_pkey" type="pk-constr" table="public.users">
<columns names="id" ref-type="src-columns"/>
</constraint>
</table>
<index name="content_comments_is_archive_index" table="public.content_comments"
concurrent="false" unique="false" fast-update="false" buffering="false"
index-type="btree" factor="90">
<idxelement use-sorting="false">
<column name="is_archive"/>
</idxelement>
</index>
<index name="content_comments_is_public_index" table="public.content_comments"
concurrent="false" unique="false" fast-update="false" buffering="false"
index-type="btree" factor="90">
<idxelement use-sorting="false">
<column name="is_public"/>
</idxelement>
</index>
<index name="contents_is_public_index" table="public.contents"
concurrent="false" unique="false" fast-update="false" buffering="false"
index-type="btree" factor="90">
<idxelement use-sorting="false">
<column name="is_public"/>
</idxelement>
</index>
<index name="poi_comments_is_archive_index" table="public.poi_comments"
concurrent="false" unique="false" fast-update="false" buffering="false"
index-type="btree" factor="90">
<idxelement use-sorting="false">
<column name="is_archive"/>
</idxelement>
</index>
<index name="poi_comments_is_public_index" table="public.poi_comments"
concurrent="false" unique="false" fast-update="false" buffering="false"
index-type="btree" factor="90">
<idxelement use-sorting="false">
<column name="is_public"/>
</idxelement>
</index>
<index name="users_is_archive_index" table="public.users"
concurrent="false" unique="false" fast-update="false" buffering="false"
index-type="btree" factor="90">
<idxelement use-sorting="false">
<column name="is_archive"/>
</idxelement>
</index>
<index name="users_register_date_index" table="public.users"
concurrent="false" unique="false" fast-update="false" buffering="false"
index-type="btree" factor="90">
<idxelement use-sorting="false">
<column name="register_date"/>
</idxelement>
</index>
<sequence name="content_locales_sequence" cycle="false" start="1" increment="1" min-value="1" max-value="9223372036854775807" cache="1">
<schema name="public"/>
<role name="kabano"/>
</sequence>
<sequence name="content_versions_sequence" cycle="false" start="1" increment="1" min-value="1" max-value="9223372036854775807" cache="1">
<schema name="public"/>
<role name="kabano"/>
</sequence>
<index name="fki_content_contributors_contributor_fkey" table="public.content_contributors"
concurrent="false" unique="false" fast-update="false" buffering="false"
index-type="btree" factor="90">
<idxelement use-sorting="false">
<column name="contributor"/>
</idxelement>
</index>
<index name="fki_content_contributors_content_fkey" table="public.content_contributors"
concurrent="false" unique="false" fast-update="false" buffering="false"
index-type="btree" factor="90">
<idxelement use-sorting="false">
<column name="content"/>
</idxelement>
</index>
<table name="content_locales" layer="0" collapse-mode="2" max-obj-count="6">
<schema name="public"/>
<role name="kabano"/>
<position x="1020" y="60"/>
<column name="id" not-null="true" sequence="public.content_locales_sequence">
<type name="integer" length="0"/>
</column>
<column name="content_id" not-null="true">
<type name="integer" length="0"/>
</column>
<column name="locale" not-null="true">
<type name="character varying" length="32"/>
</column>
<column name="author" not-null="true">
<type name="integer" length="0"/>
</column>
<constraint name="content_locales_pkey" type="pk-constr" table="public.content_locales">
<columns names="id" ref-type="src-columns"/>
</constraint>
<constraint name="content_locales_unique" type="uq-constr" table="public.content_locales">
<columns names="content_id,locale" ref-type="src-columns"/>
</constraint>
</table>
<table name="content_versions" layer="0" collapse-mode="2" max-obj-count="8">
<schema name="public"/>
<role name="kabano"/>
<position x="1500" y="40"/>
<column name="id" not-null="true" sequence="public.content_versions_sequence">
<type name="integer" length="0"/>
</column>
<column name="version" not-null="true" default-value="0">
<type name="integer" length="0"/>
</column>
<column name="update_date" not-null="true">
<type name="timestamp" length="0"/>
</column>
<column name="is_archive" not-null="true" default-value="false">
<type name="boolean" length="0"/>
</column>
<column name="name">
<type name="character varying" length="255"/>
</column>
<column name="content">
<type name="text" length="0"/>
</column>
<column name="locale_id" not-null="true">
<type name="integer" length="0"/>
</column>
<constraint name="content_versions_pkey" type="pk-constr" table="public.content_versions">
<columns names="id" ref-type="src-columns"/>
</constraint>
<constraint name="content_versions_version_locale_key" type="uq-constr" table="public.content_versions">
<columns names="version,locale_id" ref-type="src-columns"/>
</constraint>
</table>
<table name="pois" layer="0" collapse-mode="2" max-obj-count="8">
<schema name="public"/>
<role name="kabano"/>
<position x="300" y="1340"/>
<column name="id" not-null="true" sequence="public.poi_versions_sequence">
<type name="integer" length="0"/>
</column>
<column name="is_public" not-null="true" default-value="true">
<type name="boolean" length="0"/>
</column>
<column name="permalink" not-null="true">
<type name="character varying" length="255"/>
</column>
<column name="creation_date" not-null="true">
<type name="timestamp" length="0"/>
</column>
<column name="name" not-null="true">
<type name="character varying" length="255"/>
</column>
<column name="position" not-null="true">
<type name="geometry" length="0"/>
</column>
<column name="type" not-null="true">
<type name="public.poi_type_enum" length="0"/>
</column>
<constraint name="pois_pkey" type="pk-constr" table="public.pois">
<columns names="id" ref-type="src-columns"/>
</constraint>
<constraint name="pois_permalink_key" type="uq-constr" table="public.pois">
<columns names="permalink" ref-type="src-columns"/>
</constraint>
<constraint name="pois_position_type_key" type="uq-constr" table="public.pois">
<columns names="position,type" ref-type="src-columns"/>
</constraint>
</table>
<table name="poi_versions" layer="0" collapse-mode="2" max-obj-count="12">
<schema name="public"/>
<role name="kabano"/>
<position x="1620" y="1260"/>
<column name="id" not-null="true" sequence="public.pois_sequence">
<type name="integer" length="0"/>
</column>
<column name="version" not-null="true" default-value="0">
<type name="integer" length="0"/>
</column>
<column name="update_date" not-null="true">
<type name="timestamp" length="0"/>
</column>
<column name="is_archive" not-null="true" default-value="false">
<type name="boolean" length="0"/>
</column>
<column name="alt_type" not-null="true">
<type name="public.poi_type_enum" length="0"/>
</column>
<column name="is_destroyed" not-null="true" default-value="false">
<type name="boolean" length="0"/>
</column>
<column name="alt_name">
<type name="character varying" length="255"/>
</column>
<column name="alt_position" not-null="true">
<type name="geometry" length="0"/>
</column>
<column name="parameters">
<type name="jsonb" length="0"/>
</column>
<column name="source_id" not-null="true">
<type name="integer" length="0"/>
</column>
<constraint name="poi_versions_pkey" type="pk-constr" table="public.poi_versions">
<columns names="id" ref-type="src-columns"/>
</constraint>
<constraint name="poi_versions_version_source_key" type="uq-constr" table="public.poi_versions">
<columns names="version,source_id" ref-type="src-columns"/>
</constraint>
</table>
<index name="poi_versions_is_archive_index" table="public.poi_versions"
concurrent="false" unique="false" fast-update="false" buffering="false"
index-type="btree" factor="90">
<idxelement use-sorting="false">
<column name="is_archive"/>
</idxelement>
</index>
<index name="poi_versions_is_destroyed_index" table="public.poi_versions"
concurrent="false" unique="false" fast-update="false" buffering="false"
index-type="btree" factor="90">
<idxelement use-sorting="false">
<column name="is_destroyed"/>
</idxelement>
</index>
<index name="poi_versions_type_index" table="public.poi_versions"
concurrent="false" unique="false" fast-update="false" buffering="false"
index-type="btree" factor="90">
<idxelement use-sorting="false">
<column name="alt_type"/>
</idxelement>
</index>
<sequence name="poi_sources_sequence" cycle="false" start="1" increment="1" min-value="1" max-value="9223372036854775807" cache="1">
<schema name="public"/>
<role name="kabano"/>
</sequence>
<table name="poi_sources" layer="0" collapse-mode="2" max-obj-count="6">
<schema name="public"/>
<role name="kabano"/>
<position x="1160" y="1400"/>
<column name="id" not-null="true" sequence="public.poi_sources_sequence">
<type name="integer" length="0"/>
</column>
<column name="source">
<type name="character varying" length="3"/>
</column>
<column name="remote_source_id">
<type name="character varying" length="255"/>
</column>
<column name="author" not-null="true">
<type name="integer" length="0"/>
</column>
<column name="locale_id" not-null="true">
<type name="integer" length="0"/>
</column>
<constraint name="poi_sources_pkey" type="pk-constr" table="public.poi_sources">
<columns names="id" ref-type="src-columns"/>
</constraint>
<constraint name="poi_sources_source_key" type="uq-constr" table="public.poi_sources">
<columns names="source,remote_source_id" ref-type="src-columns"/>
</constraint>
<constraint name="poi_sources_locale_key" type="uq-constr" table="public.poi_sources">
<columns names="locale_id,source" ref-type="src-columns"/>
</constraint>
</table>
<constraint name="content_comments_author_fkey" type="fk-constr" comparison-type="MATCH SIMPLE"
upd-action="NO ACTION" del-action="NO ACTION" ref-table="public.users" table="public.content_comments">
<columns names="author" ref-type="src-columns"/>
<columns names="id" ref-type="dst-columns"/>
</constraint>
<constraint name="content_comments_content_fkey" type="fk-constr" comparison-type="MATCH SIMPLE"
upd-action="NO ACTION" del-action="NO ACTION" ref-table="public.contents" table="public.content_comments">
<columns names="content" ref-type="src-columns"/>
<columns names="id" ref-type="dst-columns"/>
</constraint>
<constraint name="content_comments_locale_fkey" type="fk-constr" comparison-type="MATCH SIMPLE"
upd-action="NO ACTION" del-action="NO ACTION" ref-table="public.locales" table="public.content_comments">
<columns names="locale" ref-type="src-columns"/>
<columns names="name" ref-type="dst-columns"/>
</constraint>
<constraint name="content_contributors_contributor_fkey" type="fk-constr" comparison-type="MATCH SIMPLE"
upd-action="NO ACTION" del-action="NO ACTION" ref-table="public.users" table="public.content_contributors">
<columns names="contributor" ref-type="src-columns"/>
<columns names="id" ref-type="dst-columns"/>
</constraint>
<constraint name="content_contributors_content_fkey" type="fk-constr" comparison-type="MATCH SIMPLE"
upd-action="NO ACTION" del-action="NO ACTION" ref-table="public.content_locales" table="public.content_contributors">
<columns names="content" ref-type="src-columns"/>
<columns names="id" ref-type="dst-columns"/>
</constraint>
<constraint name="poi_comments_author_fkey" type="fk-constr" comparison-type="MATCH SIMPLE"
upd-action="NO ACTION" del-action="NO ACTION" ref-table="public.users" table="public.poi_comments">
<columns names="author" ref-type="src-columns"/>
<columns names="id" ref-type="dst-columns"/>
</constraint>
<constraint name="poi_comments_locale_fkey" type="fk-constr" comparison-type="MATCH SIMPLE"
upd-action="NO ACTION" del-action="NO ACTION" ref-table="public.locales" table="public.poi_comments">
<columns names="locale" ref-type="src-columns"/>
<columns names="name" ref-type="dst-columns"/>
</constraint>
<constraint name="poi_comments_poi_fkey" type="fk-constr" comparison-type="MATCH SIMPLE"
upd-action="NO ACTION" del-action="NO ACTION" ref-table="public.poi_sources" table="public.poi_comments">
<columns names="poi" ref-type="src-columns"/>
<columns names="id" ref-type="dst-columns"/>
</constraint>
<constraint name="poi_contributors_contributor_fkey" type="fk-constr" comparison-type="MATCH SIMPLE"
upd-action="NO ACTION" del-action="NO ACTION" ref-table="public.users" table="public.poi_contributors">
<columns names="contributor" ref-type="src-columns"/>
<columns names="id" ref-type="dst-columns"/>
</constraint>
<constraint name="poi_contributors_poi_fkey" type="fk-constr" comparison-type="MATCH SIMPLE"
upd-action="NO ACTION" del-action="NO ACTION" ref-table="public.poi_sources" table="public.poi_contributors">
<columns names="poi" ref-type="src-columns"/>
<columns names="id" ref-type="dst-columns"/>
</constraint>
<constraint name="poi_localised_locale_fkey" type="fk-constr" comparison-type="MATCH SIMPLE"
upd-action="NO ACTION" del-action="NO ACTION" ref-table="public.locales" table="public.poi_locales">
<columns names="locale" ref-type="src-columns"/>
<columns names="name" ref-type="dst-columns"/>
</constraint>
<constraint name="poi_locales_poi_fkey" type="fk-constr" comparison-type="MATCH FULL"
upd-action="NO ACTION" del-action="NO ACTION" ref-table="public.pois" table="public.poi_locales">
<columns names="poi_id" ref-type="src-columns"/>
<columns names="id" ref-type="dst-columns"/>
</constraint>
<constraint name="users_locale_fkey" type="fk-constr" comparison-type="MATCH SIMPLE"
upd-action="NO ACTION" del-action="NO ACTION" ref-table="public.locales" table="public.users">
<columns names="locale" ref-type="src-columns"/>
<columns names="name" ref-type="dst-columns"/>
</constraint>
<constraint name="content_locales_locale" type="fk-constr" comparison-type="MATCH SIMPLE"
upd-action="NO ACTION" del-action="NO ACTION" ref-table="public.locales" table="public.content_locales">
<columns names="locale" ref-type="src-columns"/>
<columns names="name" ref-type="dst-columns"/>
</constraint>
<constraint name="content_locales_content" type="fk-constr" comparison-type="MATCH SIMPLE"
upd-action="NO ACTION" del-action="NO ACTION" ref-table="public.contents" table="public.content_locales">
<columns names="content_id" ref-type="src-columns"/>
<columns names="id" ref-type="dst-columns"/>
</constraint>
<constraint name="content_locales_author" type="fk-constr" comparison-type="MATCH SIMPLE"
upd-action="NO ACTION" del-action="NO ACTION" ref-table="public.users" table="public.content_locales">
<columns names="author" ref-type="src-columns"/>
<columns names="id" ref-type="dst-columns"/>
</constraint>
<constraint name="content_versions_locale" type="fk-constr" comparison-type="MATCH SIMPLE"
upd-action="NO ACTION" del-action="NO ACTION" ref-table="public.content_locales" table="public.content_versions">
<columns names="locale_id" ref-type="src-columns"/>
<columns names="id" ref-type="dst-columns"/>
</constraint>
<constraint name="poi_versions_source_fkey" type="fk-constr" comparison-type="MATCH SIMPLE"
upd-action="NO ACTION" del-action="NO ACTION" ref-table="public.poi_sources" table="public.poi_versions">
<columns names="source_id" ref-type="src-columns"/>
<columns names="id" ref-type="dst-columns"/>
</constraint>
<constraint name="poi_sources_locale_fkey" type="fk-constr" comparison-type="MATCH FULL"
upd-action="NO ACTION" del-action="NO ACTION" ref-table="public.sources" table="public.poi_sources">
<columns names="source" ref-type="src-columns"/>
<columns names="id" ref-type="dst-columns"/>
</constraint>
<constraint name="poi_sources_poi_locale_fkey" type="fk-constr" comparison-type="MATCH FULL"
upd-action="NO ACTION" del-action="NO ACTION" ref-table="public.poi_locales" table="public.poi_sources">
<columns names="locale_id" ref-type="src-columns"/>
<columns names="id" ref-type="dst-columns"/>
</constraint>
<relationship name="rel_content_comments_users" type="relfk" layer="0"
src-table="public.content_comments"
dst-table="public.users" reference-fk="content_comments_author_fkey"
src-required="false" dst-required="false"/>
<relationship name="rel_content_comments_contents" type="relfk" layer="0"
src-table="public.content_comments"
dst-table="public.contents" reference-fk="content_comments_content_fkey"
src-required="false" dst-required="false"/>
<relationship name="rel_content_comments_locales" type="relfk" layer="0"
src-table="public.content_comments"
dst-table="public.locales" reference-fk="content_comments_locale_fkey"
src-required="false" dst-required="false"/>
<relationship name="rel_content_contributors_users" type="relfk" layer="0"
src-table="public.content_contributors"
dst-table="public.users" reference-fk="content_contributors_contributor_fkey"
src-required="false" dst-required="false"/>
<relationship name="rel_content_contributors_content_locales" type="relfk" layer="0"
src-table="public.content_contributors"
dst-table="public.content_locales" reference-fk="content_contributors_content_fkey"
src-required="false" dst-required="false"/>
<relationship name="rel_poi_comments_users" type="relfk" layer="0"
src-table="public.poi_comments"
dst-table="public.users" reference-fk="poi_comments_author_fkey"
src-required="false" dst-required="false"/>
<relationship name="rel_poi_comments_locales" type="relfk" layer="0"
src-table="public.poi_comments"
dst-table="public.locales" reference-fk="poi_comments_locale_fkey"
src-required="false" dst-required="false"/>
<relationship name="rel_poi_comments_poi_sources" type="relfk" layer="0"
src-table="public.poi_comments"
dst-table="public.poi_sources" reference-fk="poi_comments_poi_fkey"
src-required="false" dst-required="false"/>
<relationship name="rel_poi_contributors_users" type="relfk" layer="0"
src-table="public.poi_contributors"
dst-table="public.users" reference-fk="poi_contributors_contributor_fkey"
src-required="false" dst-required="false"/>
<relationship name="rel_poi_contributors_poi_sources" type="relfk" layer="0"
src-table="public.poi_contributors"
dst-table="public.poi_sources" reference-fk="poi_contributors_poi_fkey"
src-required="false" dst-required="false"/>
<relationship name="rel_poi_locales_locales" type="relfk" layer="0"
src-table="public.poi_locales"
dst-table="public.locales" reference-fk="poi_localised_locale_fkey"
src-required="false" dst-required="false"/>
<relationship name="rel_users_locales" type="relfk" layer="0"
src-table="public.users"
dst-table="public.locales" reference-fk="users_locale_fkey"
src-required="false" dst-required="false"/>
<relationship name="rel_content_locales_locales" type="relfk" layer="0"
src-table="public.content_locales"
dst-table="public.locales" reference-fk="content_locales_locale"
src-required="false" dst-required="false"/>
<relationship name="rel_content_locales_contents" type="relfk" layer="0"
src-table="public.content_locales"
dst-table="public.contents" reference-fk="content_locales_content"
src-required="false" dst-required="false"/>
<relationship name="rel_content_locales_users" type="relfk" layer="0"
src-table="public.content_locales"
dst-table="public.users" reference-fk="content_locales_author"
src-required="false" dst-required="false"/>
<relationship name="rel_content_versions_content_locales" type="relfk" layer="0"
src-table="public.content_versions"
dst-table="public.content_locales" reference-fk="content_versions_locale"
src-required="false" dst-required="false"/>
<relationship name="rel_poi_versions_poi_sources" type="relfk" layer="0"
src-table="public.poi_versions"
dst-table="public.poi_sources" reference-fk="poi_versions_source_fkey"
src-required="false" dst-required="false"/>
<relationship name="rel_poi_sources_sources" type="relfk" layer="0"
src-table="public.poi_sources"
dst-table="public.sources" reference-fk="poi_sources_locale_fkey"
src-required="false" dst-required="false"/>
<relationship name="rel_poi_sources_poi_locales" type="relfk" layer="0"
src-table="public.poi_sources"
dst-table="public.poi_locales" reference-fk="poi_sources_poi_locale_fkey"
src-required="false" dst-required="false"/>
<relationship name="rel_poi_locales_pois" type="relfk" layer="0"
src-table="public.poi_locales"
dst-table="public.pois" reference-fk="poi_locales_poi_fkey"
src-required="false" dst-required="false"/>
</dbmodel>

BIN
_ressources/logo_carre.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -0,0 +1,85 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="44"
height="44"
viewBox="0 0 44 44"
id="svg2"
version="1.1"
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
sodipodi:docname="logo_carre.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="3.959798"
inkscape:cx="17.172593"
inkscape:cy="21.465742"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:window-width="1366"
inkscape:window-height="702"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:showpageshadow="2"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Calque 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(2.2888184e-7,-1008.3622)">
<g
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
id="text4136"
transform="matrix(1.1379801,0,0,1.1379801,3.1581138e-8,-151.20504)" />
<g
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
id="text4136-1"
transform="matrix(1.1379801,0,0,1.1379801,-348.56109,665.85293)">
<path
d="m 327.11423,334.16668 -10.09786,-27.23536 -10.34214,27.23536 z m -18.81955,-1.26818 5.88391,-15.54965 4.87414,-1.40926 6.40569,16.95891 z"
style="font-style:normal;font-variant:normal;font-weight:200;font-stretch:normal;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans Ultra-Light';fill:#000000;fill-opacity:1"
id="path4159"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccccc" />
<path
d="m 344.58688,334.12116 -0.008,-1.22266 h -1.36672 l -8.73903,-23.79476 0.83839,-1.55306 -0.73436,-0.62958 -0.82296,1.22506 -0.69448,-1.17371 -0.71601,0.66008 0.84437,1.49829 -9.42882,23.76768 h -1.23813 l 0.0188,1.26818 z m -17.50259,-1.22266 6.57828,-15.42426 6.1435,15.42426 z"
style="font-style:normal;font-variant:normal;font-weight:200;font-stretch:normal;font-size:40px;line-height:125%;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans Ultra-Light';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
id="path4159-4"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccccccccccccc" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

14
_ressources/nginx.conf Normal file
View File

@@ -0,0 +1,14 @@
# Déclare une variable pour extraire `$kabano_q` sans slash initial
if ($uri ~ ^/(.*)) {
set $kabano_q $1;
}
# Gère les fichiers statiques si disponibles sous /public/
location / {
root /var/www/my_webapp__3/www/public;
# Tente de servir des fichiers physiques existants dans /public/
try_files $uri /index.php?q=$kabano_q&$args;
# Par défaut, les fichiers inexistants sont redirigés vers /index.php
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,58 +0,0 @@
<?
if(isset($controller->splitted_url[1]) && $user->rankIsHigher("moderator")) {
switch ($controller->splitted_url[1]) {
case '': case 'admin':
$head['title'] = "Administration";
include ($config['views_folder']."d.admin.html");
break;
case 'git-pull':
if ($user->rankIsHigher("administrator")) {
$head['title'] = "Mise à jour";
$output = array();
chdir($config['abs_root_folder']);
exec("git pull", $output);
include ($config['views_folder']."d.admin.git-pull.html");
}
else {
$notfound = 1;
}
break;
case 'logs':
if ($user->rankIsHigher("moderator")) {
$head['title'] = "Logs";
$files_list = scandir($config['logs_folder']);
if (isset($controller->splitted_url[2]) && is_numeric($controller->splitted_url[2]) && intval($controller->splitted_url[2]) < count($files_list)-2) {
$filenb = $controller->splitted_url[2];
}
else {
$filenb = 0;
}
chdir($config['logs_folder']);
//exec("tail -n 200 ".$files_list[$filenb+2]." | tac", $output);
include ($config['views_folder']."d.admin.logs.html");
}
else {
$notfound = 1;
}
break;
default:
$notfound = 1;
break;
}
}
else if($user->rankIsHigher("moderator")) {
$head['title'] = "Administration";
include ($config['views_folder']."d.admin.html");
}
else {
$notfound = 1;
}
?>

View File

@@ -1,152 +0,0 @@
<?
require_once($config['models_folder']."d.poi.php");
require_once($config['models_folder']."d.users.php");
$head['css'] = "d.index.css;d.poi.css";
$poi = new Kabano\Poi();
switch ($controller->splitted_url[1]) {
case "new":
if($user->rankIsHigher("registered")) {
if(isset($_POST['submit'])) {
$poi->name = $_POST['name'];
$poi->locale = $_POST['locale'];
$poi->poi_type = $_POST['poi_type'];
$poi->lat = $_POST['lat'];
$poi->lon = $_POST['lon'];
$poi->alt = $_POST['alt'];
$poi->author = $user->id;
if(!$blogArticle->checkPermalink($_POST['permalink'],1)) {
$blogArticle->permalink = $_POST['permalink'];
$blogArticle->insert();
header('Location: '.$config['rel_root_folder']."blog/".$blogArticle->permalink);
}
else {
$head['title'] = $blogArticle->name;
$error = "permalink";
}
}
else {
$head['title'] = "Nouvel hébergement";
}
$locales = new Kabano\Locales();
$locales->getAll();
$head['third'] = "leaflet/leaflet.js;leaflet-fullscreen/Leaflet.fullscreen.min.js;leaflet-easybutton/easy-button.js";
$head['css'] .= ";../third/leaflet/leaflet.css;../third/leaflet-fullscreen/leaflet.fullscreen.css;../third/leaflet-easybutton/easy-button.css";
$head['js'] = "d.poi_map.js";
$poi->lat = ""; $poi->lon = ""; $poi->alt = "";
$new = 1;
include ($config['views_folder']."d.poi.edit.html");
break;
}
else {
$notfound = 1;
}
default:
// // If the page exists
// if ($blogArticle->checkPermalink($controller->splitted_url[1],$user->rankIsHigher("premium"))) {
// if (isset($controller->splitted_url[2]) && $controller->splitted_url[2] == "delete" && $user->rankIsHigher("moderator")) {
// $blogArticle->delete();
// header('Location: '.$config['rel_root_folder']."blog/".$blogArticle->permalink);
// }
// else if (isset($controller->splitted_url[2]) && $controller->splitted_url[2] == "restore" && $user->rankIsHigher("moderator")) {
// $blogArticle->restore();
// header('Location: '.$config['rel_root_folder']."blog/".$blogArticle->permalink);
// }
// else if (isset($controller->splitted_url[2]) && $controller->splitted_url[2] == "edit" && $user->rankIsHigher("moderator")) {
// if(isset($_POST['submit'])) {
// $blogArticle->content = $_POST['content'];
// $blogArticle->locale = $_POST['locale'];
// $blogArticle->name = $_POST['name'];
// $blogArticle->is_commentable = isset($_POST['is_commentable'])?'t':'f';
// $blogArticle->author = $user->id;
// $blogArticle->update();
// header('Location: '.$config['rel_root_folder']."blog/".$blogArticle->permalink);
// }
// else {
// $locales = new Kabano\Locales();
// $locales->getAll();
// $head['title'] = $blogArticle->name;
// include ($config['views_folder']."d.blog.edit.html");
// }
// }
// else {
// // Manage history of an article
// if($user->rankIsHigher("premium")) {
// $blogHistory = new Kabano\BlogArticles();
// $blogHistory->getHistory($controller->splitted_url[1]);
// }
// if (isset($controller->splitted_url[2]) && is_numeric($controller->splitted_url[2]))
// $blogArticle->checkPermalink($controller->splitted_url[1],$user->rankIsHigher("premium"),$controller->splitted_url[2]);
// // Manage comment creation
// if (isset($controller->splitted_url[2]) && $controller->splitted_url[2]=="new_comment") {
// if (isset($_POST['submit']) && $user->rankIsHigher("registered")) {
// $blogComment = new Kabano\BlogComment();
// $blogComment->locale = $user->locale;
// $blogComment->author = $user->id;
// $blogComment->content = $blogArticle->content_id;
// $blogComment->comment = $_POST['comment'];
// $blogComment->insert();
// }
// }
// // Manage comment deletion
// if (isset($controller->splitted_url[2]) && $controller->splitted_url[2]=="delete_comment") {
// if (isset($controller->splitted_url[3]) && is_numeric($controller->splitted_url[3])) {
// $blogComment = new Kabano\BlogComment();
// if($blogComment->checkId($controller->splitted_url[3]))
// if ($user->rankIsHigher("moderator") || $user->id == $blogComment->author)
// $blogComment->delete();
// }
// }
// // Manage comment restoration
// if (isset($controller->splitted_url[2]) && $controller->splitted_url[2]=="restore_comment") {
// if (isset($controller->splitted_url[3]) && is_numeric($controller->splitted_url[3])) {
// $blogComment = new Kabano\BlogComment();
// if($blogComment->checkId($controller->splitted_url[3]))
// if ($user->rankIsHigher("moderator") || $user->id == $blogComment->author)
// $blogComment->restore();
// }
// }
// $blogArticle->md2html();
// // Manage comments
// if ($blogArticle->is_commentable == "t") {
// $blogArticles_comments = new Kabano\BlogComments();
// $blogArticles_comments->listComments($blogArticle->content_id, ($user->rankIsHigher("premium")));
// $i = 0;
// foreach ($blogArticles_comments->objs as $comment) {
// $comment->md2html();
// $comment->author_obj = new Kabano\User();
// $comment->author_obj->checkId($comment->author);
// }
// }
// $tempUser = new Kabano\User();
// $tempUser->checkId($blogArticle->author);
// $blogArticle->author_name = $tempUser->name;
// unset($tempUser);
// $head['title'] = $blogArticle->name;
// include ($config['views_folder']."d.blog.view.html");
// }
// }
// else {
// $notfound = 1;
// }
// break;
}
?>

View File

@@ -1,50 +0,0 @@
<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
/*****
** Management of folder names
*****/
// It is the include folder name
$config['include_folder']=basename(__DIR__);
// This is the absolute folder to the root of the website
$config['abs_root_folder']=str_replace($config['include_folder'],"",__DIR__);
// This is the relative folder to the root of the website from the DocumentRoot (can also be called subfolder)
$config['rel_root_folder']=str_replace($_SERVER['DOCUMENT_ROOT'],"",$config['abs_root_folder']);
$config['web_root_folder']="kabano.test/";
if($config['rel_root_folder']=="") $config['rel_root_folder']="/";
// Here all the absolute paths to specific folders
$config['views_folder'] = $config['abs_root_folder']."views/";
$config['controllers_folder'] = $config['abs_root_folder']."controllers/";
$config['models_folder'] = $config['abs_root_folder']."models/";
$config['medias_folder'] = $config['abs_root_folder']."medias/";
$config['includes_folder'] = $config['abs_root_folder']."includes/";
$config['third_folder'] = $config['abs_root_folder']."third/";
$config['logs_folder'] = $config['abs_root_folder']."logs/";
// Here all the relative url to specific folders
$config['views_url'] = $config['rel_root_folder']."views/";
/*****
** SQL Database configuration
*****/
$config['SQL_host'] = "localhost";
$config['SQL_user'] = "kabano";
$config['SQL_pass'] = "PASSWORD";
$config['SQL_db'] = "postgres";
/*****
** Mail configuration
*****/
$config['admin_mail'] = "leo@lstronic.com";
$config['bot_mail'] = "robot@kabano.com";
?>

View File

@@ -1,22 +0,0 @@
<?
require_once($config['models_folder']."d.users.php");
ini_set("session.cookie_lifetime",60*60*24*30);
session_start();
$user = new Kabano\User();
$user->rank = "visitor"; // All users are visitors
if(isset($_SESSION['userid'])) {
$user->checkID($_SESSION['userid']);
if ($user->checkID($_SESSION['userid'])) {
$user->updateLoginDate();
//setlocale(LC_ALL, $config['locales'][$user->locale][4]);
}
else {
session_destroy();
}
}
?>

7
index.php Executable file → Normal file
View File

@@ -1,6 +1,3 @@
<? <?php
require_once('includes/config.php'); require __DIR__ . '/public/index.php';
require_once('includes/routes.php');
?>

View File

@@ -1,183 +0,0 @@
<?
namespace Kabano;
/**********************************************************
***********************************************************
**
** This class is to manage a poi object
**
***********************************************************
**********************************************************/
require_once($config['third_folder']."Md/MarkdownExtra.inc.php");
// This array is related to the defined SQL enum, do not touch.
$poi_types = array(
"basic_hut" => array("Abri sommaire", "Abri", "#ef2929", "basic_hut"),
"wilderness_hut" => array("Cabane non gardée", "Cabane", "#ef2929", "wilderness_hut"),
"alpine_hut" => array("Refuge gardé", "Refuge", "#ef2929", "alpine_hut"),
"halt" => array("Gîte d'étape", "Gîte", "#4e9a06", "halt"),
"bivouac" => array("Zone de bivouac", "Bivouac", "#ef2929", "bivouac"),
"campsite" => array("Camping", "Camping", "#4e9a06", "campsite")
);
class Poi
{
public $poi_id = NULL;
public $locale_id = NULL;
public $source_id = NULL;
public $version_id = NULL;
public $is_public = NULL;
public $permalink = NULL;
public $creation_date = NULL;
public $name = NULL;
public $position = NULL;
public $type = NULL;
public $locale = NULL;
public $source = NULL;
public $remote_source_id = NULL;
public $author = NULL;
public $version = NULL;
public $update_date = NULL;
public $is_archive = NULL;
public $alt_type = NULL;
public $is_destroyed = NULL;
public $alt_name = NULL;
public $alt_position = NULL;
public $parameters = NULL;
/*****
** Checks if a page at this URL exists and return the ID
*****/
public function checkPermalink($permalink, $withArchive=0, $elementNb=0) {
global $config;
$con = pg_connect("host=".$config['SQL_host']." dbname=".$config['SQL_db']." user=".$config['SQL_user']." password=".$config['SQL_pass'])
or die ("Could not connect to server\n");
$query = "SELECT poi_versions.id AS version_id, * FROM pois INNER JOIN poi_locales ON pois.id = poi_locales.poi_id INNER JOIN poi_sources ON poi_locales.id = poi_sources.locale_id INNER JOIN poi_versions ON poi_sources.id = poi_versions.source_id WHERE permalink=$1";
if($withArchive==0) {
$query .= " AND is_archive=FALSE AND is_public=TRUE";
}
$query .= " ORDER BY update_date DESC LIMIT 1 OFFSET $2";
pg_prepare($con, "prepare1", $query)
or die ("Cannot prepare statement\n");
$result = pg_execute($con, "prepare1", array($permalink, $elementNb))
or die ("Cannot execute statement\n");
pg_close($con);
if(pg_num_rows($result) == 1) {
$row = pg_fetch_assoc($result);
$this->populate($row);
return 1;
}
else {
return 0;
}
}
/*****
** Populate the object using its ID
*****/
public function populate($row) {
$this->$poi_id = $row['poi_id'];
$this->$locale_id = $row['locale_id'];
$this->$source_id = $row['source_id'];
$this->$version_id = $row['version_id'];
$this->$is_public = $row['is_public'];
$this->$permalink = $row['permalink'];
$this->$creation_date = $row['creation_date'];
$this->$name = $row['name'];
$this->$position = $row['position'];
$this->$type = $row['type'];
$this->$locale = $row['locale'];
$this->$source = $row['source'];
$this->$remote_source_id = $row['remote_source_id'];
$this->$author = $row['author'];
$this->$version = $row['version'];
$this->$update_date = $row['update_date'];
$this->$is_archive = $row['is_archive'];
$this->$alt_type = $row['alt_type'];
$this->$is_destroyed = $row['is_destroyed'];
$this->$alt_name = $row['alt_name'];
$this->$alt_position = $row['alt_position'];
$this->$parameters = $row['parameters'];
}
/*****
** Create a new poi, all field required except alt_*, *_id
*****/
public function insert() {
global $config;
global $user;
$con = pg_connect("host=".$config['SQL_host']." dbname=".$config['SQL_db']." user=".$config['SQL_user']." password=".$config['SQL_pass'])
or die ("Could not connect to server\n");
// Because it is the first insert.
$this->alt_type = $this->type;
$this->alt_name = $this->name;
$this->alt_position = $this->position;
$query = "INSERT INTO pois (is_public, permalink, creation_date, name, position, type) VALUES
(TRUE, $1, $2, $3, $4, $5) RETURNING id";
pg_prepare($con, "prepare1", $query)
or die ("Cannot prepare statement\n");
$result = pg_execute($con, "prepare1", array($this->permalink, date('r'), $this->name, $this->position, $this->type))
or die ("Cannot execute statement\n");
$this->poi_id = pg_fetch_assoc($result)['id'];
$query = "INSERT INTO poi_locales (locale, poi_id) VALUES
($1, $2) RETURNING id";
pg_prepare($con, "prepare2", $query)
or die ("Cannot prepare statement\n");
$result = pg_execute($con, "prepare2", array($this->locale, $this->poi_id))
or die ("Cannot execute statement\n");
$this->locale_id = pg_fetch_assoc($result)['id'];
$query = "INSERT INTO poi_sources (source, remote_source_id, author, locale_id) VALUES
($1, $2, $3, $4) RETURNING id";
pg_prepare($con, "prepare3", $query)
or die ("Cannot prepare statement\n");
$result = pg_execute($con, "prepare3", array($this->source, $this->remote_source_id, $this->author, $this->locale_id))
or die ("Cannot execute statement\n");
$this->source_id = pg_fetch_assoc($result)['id'];
$query = "INSERT INTO poi_versions (version, update_date, is_archive, alt_type, is_destroyed, alt_name, alt_position, parameters, source_id) VALUES
('0', $1, FALSE, $2, $3, $4, $5, $6, $7) RETURNING id";
pg_prepare($con, "prepare4", $query)
or die ("Cannot prepare statement\n");
$result = pg_execute($con, "prepare4", array(date('r'), $this->alt_type, $this->is_destroyed, $this->alt_name, $this->alt_position, $this->parameters, $this->source_id))
or die ("Cannot execute statement\n");
$this->version_id = pg_fetch_assoc($result)['id'];
$query = "INSERT INTO poi_contributors (poi, contributor) VALUES
($1, $2)";
pg_prepare($con, "prepare5", $query)
or die ("Cannot prepare statement\n");
$result = pg_execute($con, "prepare5", array($this->source_id, $user->id))
or die ("Cannot execute statement\n");
pg_close($con);
error_log(
date('r')." \t".$user->name." (".$user->id.") \tINSERT \tCreate new poi '".$this->permalink."'\r\n",
3,
$config['logs_folder'].'wiki.log');
}
}
?>

11
public/.htaccess Executable file
View File

@@ -0,0 +1,11 @@
AddDefaultCharset UTF-8
RewriteEngine On
# Everything uses the routing system
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule . ./index.php [L]
php_value short_open_tag 1

8
public/index.php Executable file
View File

@@ -0,0 +1,8 @@
<?php
/**
* Point d'entrée web : charge la configuration et le routeur principal.
*/
require_once __DIR__ . '/../src/Core/config.php';
require_once __DIR__ . '/../src/Core/routes.php';

View File

@@ -0,0 +1,12 @@
<!-- Footer -->
<footer>
<div class="flex">
<p class="flex-element"><a target="_blank" href="https://www.facebook.com/kabano09"><i class="fab fa-facebook-square"></i></a> Léo Serre &mdash; <script>document.write("06 " + "1" + "8 6" + "2 3" + "2 ");</script>&#48;&#53;</p>
<div id="footernav" class="flex-element">
<!-- Footer links -->
<a href="<?=$config['rel_root_folder']?>wiki/cgv">CGV</a> &mdash;
<a href="<?=$config['rel_root_folder']?>wiki/legal">Mentions Légales</a> &mdash;
<a href="<?=$config['rel_root_folder']?>contact">Contact</a>
</div>
</div>
</footer>

View File

@@ -1,46 +1,50 @@
<!-- Head: metadata and assets -->
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, height=device-height"> <meta name="viewport" content="width=device-width, height=device-height, initial-scale=1.0">
<link rel="shortcut icon" href="<?=$config['views_url']?>img/favicon.png"> <link rel="shortcut icon" href="<?=$config['views_url']?>img/favicon.png">
<? if (isset($head['css'])) { <!-- Stylesheets -->
<?php if (isset($head['css'])) {
foreach(explode(";",$head['css']) as $css) { ?> foreach(explode(";",$head['css']) as $css) { ?>
<link rel="stylesheet" href="<?=$config['views_url']?>css/<?=$css?>"/> <link rel="stylesheet" href="<?=$config['views_url']?>css/<?=$css?>"/>
<? } <?php }
} }
else { ?> else { ?>
<link rel="stylesheet" href="<?=$config['views_url']?>css/d.index.css"/> <link rel="stylesheet" href="<?=$config['views_url']?>css/d.index.css"/>
<? } ?> <?php } ?>
<link rel="stylesheet" href="<?=$config['views_url']?>third/fontawesome-free-5.4.1-web/css/all.min.css"/> <link rel="stylesheet" href="<?=$config['views_url']?>third/fontawesome-free-5.4.1-web/css/all.min.css"/>
<!-- Scripts -->
<script type="text/javascript" src="<?=$config['views_url']?>third/jquery-3.3.1.min.js"></script> <script type="text/javascript" src="<?=$config['views_url']?>third/jquery-3.3.1.min.js"></script>
<? if (isset($head['third'])) { <?php if (isset($head['third'])) {
foreach(explode(";",$head['third']) as $third) { ?> foreach(explode(";",$head['third']) as $third) { ?>
<script type="text/javascript" src="<?=$config['views_url']?>third/<?=$third?>"></script> <script type="text/javascript" src="<?=$config['views_url']?>third/<?=$third?>"></script>
<? } <?php }
} ?> } ?>
<script type="text/javascript" src="<?=$config['views_url']?>js/d.header.js"></script> <script type="text/javascript" src="<?=$config['views_url']?>js/d.header.js"></script>
<? if (isset($head['js'])) { <?php if (isset($head['js'])) {
foreach(explode(";",$head['js']) as $js) { ?> foreach(explode(";",$head['js']) as $js) { ?>
<script type="text/javascript" src="<?=$config['views_url']?>js/<?=$js?>"></script> <script type="text/javascript" src="<?=$config['views_url']?>js/<?=$js?>"></script>
<? } <?php }
} ?> } ?>
<? if (isset($head['title'])) { ?> <!-- Metadata -->
<?php if (isset($head['title'])) { ?>
<title><?=$head['title']?> &mdash; Kabano</title> <title><?=$head['title']?> &mdash; Kabano</title>
<? } <?php }
else { ?> else { ?>
<title>Cabanes et bivouac en montagne</title> <title>Refuges de montagne et métallerie agricole</title>
<? } ?> <?php } ?>
<? if (isset($head['description'])) { ?> <?php if (isset($head['description'])) { ?>
<meta name="description" content="<?=$head['description']?>"> <meta name="description" content="<?=$head['description']?>">
? } <?php }
else { ?> else { ?>
<meta name="description" content="Annuaire collaboratif des hébergements pour les activitées de plein air : cabanes, refuges, campings..."> <meta name="description" content="Entreprise de services dans la fabrication, la réparation, et l'entretien de bâtiments et machines agricoles">
<? } ?> <?php } ?>
<? if (isset($head['keywords'])) { ?> <?php if (isset($head['keywords'])) { ?>
<meta name="keywords" content="<?=$head['keywords']?>"> <meta name="keywords" content="<?=$head['keywords']?>">
<? } <?php }
else { ?> else { ?>
<meta name="keywords" content="kabano, huts, mountain, hiking, cabanes, refuges, bivouac, montagne, randonnée"> <meta name="keywords" content="kabano, cabanes, refuges, bivouac, montagne, randonnée, métallerie, agricole">
<? } ?> <?php } ?>
</head> </head>

68
public/views/blocks/d.nav.html Executable file
View File

@@ -0,0 +1,68 @@
<!-- Header navigation -->
<header>
<div id="Hcontent">
<a href="<?=$config['rel_root_folder']?>" id="logo">
<img alt="Kabano logo" src="<?=$config['views_url'].'img/'?>header.svg">
</a>
<nav>
<!-- Main menu -->
<input type="checkbox" id="togglemenu"><label for="togglemenu" class="hamburger on-bar"><i class="icon fas fa-bars"></i></label>
<ul id="menu">
<li class="on-bar has-sub with-subtitle"><a class="on-bar" href="#">Restauration<br>
<span class="subtitle">de refuges pastoraux</span></a>
<ul>
<li><a href="<?=$config['rel_root_folder']?>wiki/restauration-de-refuges">Activités</a></li>
<li><a href="<?=$config['rel_root_folder']?>wiki/portfolio-restauration">Réalisations</a></li>
</ul>
</li>
<li class="on-bar with-subtitle"><a class="on-bar" href="<?=$config['rel_root_folder']?>wiki/metallerie">Métallerie<br>
<span class="subtitle">agricole</span></a></li>
<li class="on-bar has-sub with-subtitle">
<a class="on-bar" href="#">Inventaire<br>
<span class="subtitle">des cabanes de montagne</span></a>
<ul>
<li><a href="<?=$config['rel_root_folder']?>map">Carte</a></li>
<li><a href="<?=$config['rel_root_folder']?>community">Contribuer</a></li>
</ul>
</li>
<li class="on-bar has-sub menu-icon">
<?php if ($user->id == 0) { ?>
<a class="on-bar" href="#"><i class="icon fas fa-user"></i></a>
<?php } elseif ($user->is_avatar_present == 't') { ?>
<a class="on-bar" href="#"><img alt="Avatar" class="icon avatar" src="<?=$config['rel_root_folder']?>medias/avatars/<?=$user->id?>_s.jpg"></a>
<?php } else { ?>
<a class="on-bar" href="#"><i class="icon fas fa-user-secret"></i></a>
<?php } ?>
<ul>
<!-- Account actions -->
<?php if($user->rank == 'visitor') { ?>
<li id="connectform">
<form action="<?=$config['rel_root_folder']?>user/login" method="post">
<input type="text" name="login" placeholder="Nom d'utilisateur">
<input type="password" name="password" placeholder="Mot de passe">
<input type="submit" name="submit" value="Se connecter">
</form>
</li>
<li><a href="<?=$config['rel_root_folder']?>user/signin">S'inscrire</a></li>
<?php } else { ?>
<li><a href="<?=$config['rel_root_folder']?>user/p">Mon profil</a></li>
<li><a href="<?=$config['rel_root_folder']?>user/member_list">Liste des membres</a></li>
<?php if($user->rankIsHigher('moderator')) { ?>
<li><a href="<?=$config['rel_root_folder']?>admin">Administration</a></li>
<?php } ?>
<li><a href="<?=$config['rel_root_folder']?>user/logout">Se déconnecter</a></li>
<?php } ?>
</ul>
</li>
<li class="on-bar has-sub menu-icon"><a class="on-bar" href="#"><i class="icon fas fa-question"></i></a>
<ul>
<!-- Help and info -->
<li><a href="<?=$config['rel_root_folder']?>blog">Blog</a></li>
<li><a href="<?=$config['rel_root_folder']?>contact">Contact</a></li>
<li><a href="<?=$config['rel_root_folder']?>wiki/about">À propos</a></li>
</ul>
</li>
</ul>
</nav>
</div>
</header>

View File

@@ -0,0 +1,70 @@
/* Feuille de style: css/d.admin.css */
/*********************************/
/** Wiki files page **/
/*********************************/
#wiki_files table {
width: 100%;
margin: 10px auto 30px;
}
#wiki_files table, #wiki_files td {
border: 1px solid #ccc;
border-collapse: collapse;
}
#wiki_files th {
border: 1px solid #aaa;
border-collapse: collapse;
}
#wiki_files th a {
color: inherit !important;
}
#wiki_files th i {
float: right;
}
#wiki_files td, #wiki_files th {
padding: 5px;
}
#wiki_files tr:nth-child(even) {
background: #efefef;
}
#wiki_files tr:nth-child(odd) {
background: #e1e1e1;
}
#wiki_files tr.first {
background: #ccc;
}
#wiki_files tr:hover {
background: #f5f5f5;
}
#wiki_files tr.first:hover {
background: #ccc;
}
#wiki_files td a {
display: block;
}
#wiki_files .center {
text-align: center;
}
#send_file {
display: flex;
}
#send_file div {
padding: 10px;
margin: 10px;
}
#send_file div {
flex: 2
}
#send_file input[type="submit"] {
text-align: center;
width: 150px;
flex: 1;
margin: 10px;
padding: 10px;
border-bottom: 2px solid blue;
}

View File

@@ -1,3 +1,4 @@
/* Feuille de style: css/d.blog.css */
/*********************************/ /*********************************/
/** Blog list page **/ /** Blog list page **/
/*********************************/ /*********************************/
@@ -41,18 +42,8 @@
} }
#blog_list .pagebuttons { #blog_list .pagebuttons {
text-align: center;
margin: 40px 0 30px 0; margin: 40px 0 30px 0;
} }
#blog_list .pagebuttons a {
background: #efefef;
border: 1px solid #ccc;
padding: 5px;
font-size: 1.5em;
}
#blog_list .pagebuttons .previous {
margin-right: -1px;
}
/*********************************/ /*********************************/
/** Blog view article page **/ /** Blog view article page **/
@@ -89,6 +80,31 @@
border: 1px inset; border: 1px inset;
} }
#blogContent img {
max-width: 100%;
border: 1px solid #bbb;
}
#blogContent .imglegend {
position: relative;
}
#blogContent .imglegend img {
display: block;
}
#blogContent .imglegend p {
display: block;
background: rgba(0,0,0,0.5);
color: white;
font-size: 14px;
font-variant: small-caps;
line-height: 20px;
position: absolute;
bottom: 0;
right: 0;
margin: 0;
padding: 2px 5px;
}
#new_comment { #new_comment {
clear: both; clear: both;
margin: 100px auto 0 auto; margin: 100px auto 0 auto;
@@ -109,7 +125,7 @@
} }
#new_comment_label input { #new_comment_label input {
display: none; display: none;
margin: -2px; margin: 3px;
float: right; float: right;
padding: 5px 10px; padding: 5px 10px;
position: relative; position: relative;
@@ -230,12 +246,17 @@ form.form label {
float: right; float: right;
font-size: 17px; font-size: 17px;
} }
#permalink_container {
position: relative;
}
#permalink { #permalink {
width: calc(100% - 20px); width: calc(100% - 225px);
padding-left: 215px;
}
#permalink_label {
position: absolute;
top: 10px;
left: 10px;
opacity: 0.8;
} }
form.form input[type=submit] {
width: auto;
margin: auto;
border-bottom: 2px solid blue;
}

View File

@@ -1,3 +1,4 @@
/* Feuille de style: css/d.index.css */
* { * {
border: 0; border: 0;
margin: 0; margin: 0;
@@ -25,7 +26,8 @@ a:hover {
text-decoration: none; text-decoration: none;
} }
input { input, textarea {
font-family: "Fira Sans", "Open Sans",Helvetica,Arial,sans-serif;
border-bottom-left-radius: 3px; border-bottom-left-radius: 3px;
border-bottom-right-radius: 3px; border-bottom-right-radius: 3px;
} }
@@ -38,6 +40,10 @@ small {
font-weight: 500; font-weight: 500;
} }
pre {
overflow: auto;
}
.button { .button {
padding: 5px 10px; padding: 5px 10px;
margin: 5px 10px; margin: 5px 10px;
@@ -50,6 +56,27 @@ small {
background: #eeeeff; background: #eeeeff;
} }
.pagebuttons {
text-align: center;
}
.pagebuttons a {
background: #efefef;
border: 1px solid #ccc;
padding: 5px;
font-size: 1.5em;
}
.pagebuttons .previous {
margin-right: -1px;
}
form.form input[type=submit] {
width: auto;
margin: auto;
border-bottom: 2px solid blue;
}
/* FONTS */ /* FONTS */
@font-face { @font-face {
@@ -100,7 +127,7 @@ header {
z-index: 1000; z-index: 1000;
} }
header ul { #menu {
float: right; float: right;
position: relative; position: relative;
} }
@@ -111,18 +138,28 @@ header li {
vertical-align: middle; vertical-align: middle;
} }
header li a { header li a, .hamburger {
color: white; color: white;
padding: 25px 15px 15px; padding: 25px 15px 15px;
height: 20px; height: 20px;
display: block; display: block;
vertical-align: middle; vertical-align: middle;
} }
header li a:hover { header li a:hover, header li a:focus-within {
color: white; color: white;
} }
header li.with-subtitle a {
padding: 15px 15px 25px;
}
header li:hover a { header li .subtitle {
font-size: 80%;
font-style: italic;
white-space: nowrap;
padding-left: 5px;
}
header li:hover a, header li:focus-within a {
border-bottom: 6px solid blue; border-bottom: 6px solid blue;
background: #212121; background: #212121;
} }
@@ -143,11 +180,13 @@ header .icon.avatar {
height: 28px; height: 28px;
} }
header li.has-sub:hover a { header li.has-sub:hover a, header li.has-sub:focus-within a {
border-bottom: 6px solid #212121; border-bottom: 6px solid #212121;
} }
header li.has-sub:hover > a {
header li.has-sub:hover > ul { cursor: default;
}
header li.has-sub:hover > ul, header li.has-sub:focus-within > ul {
display: block; display: block;
} }
@@ -159,6 +198,12 @@ header li.has-sub ul {
background: #212121; background: #212121;
} }
header li.with-subtitle ul {
right: unset;
position: relative;
min-width: 100%;
}
header li.has-sub ul li { header li.has-sub ul li {
display: block; display: block;
height: 46px; height: 46px;
@@ -176,7 +221,7 @@ header li.has-sub ul li a {
border-bottom: none; border-bottom: none;
} }
header li.has-sub ul li:hover { header li.has-sub ul li:hover, header li.has-sub ul li:focus-within {
border-left: 6px solid blue; border-left: 6px solid blue;
border-bottom: none; border-bottom: none;
} }
@@ -207,13 +252,63 @@ header input[type=submit] {
border-bottom: 1px solid #777; border-bottom: 1px solid #777;
} }
header input:hover { header input:hover, header input:focus-within {
background: #DDD; background: #DDD;
color: #222; color: #222;
} }
.hamburger {
display: none;
float: right;
}
#togglemenu {
display: none;
}
@media (max-width: 800px) {
#menu {
display: none;
background: black;
float: inherit;
position: static;
}
.hamburger {
display: block;
}
#togglemenu:checked ~ #menu {
display: block;
}
header li {
width: 100%;
height: inherit;
}
header li.menu-icon {
width: unset;
}
header li.menu-icon a {
padding: 20px 15px;
}
header li .subtitle {
padding-left: 0px;
}
header li.has-sub ul {
width: 100%;
}
header li.has-sub:hover ul, header li.has-sub:focus-within ul, header li.has-sub:hover ul li, header li.has-sub:focus-within ul li, header li.has-sub:hover ul a, header li.has-sub:focus-within ul a {
background-color: #212121;
border: 0;
}
header li.has-sub:hover a, header li.has-sub:focus-within a {
border-left: 6px solid blue;
border-bottom: 0;
}
header form {
width: unset;
}
}
#Hcontent { #Hcontent {
width: 850px; max-width: 850px;
margin: 0 auto; margin: 0 auto;
} }
@@ -238,14 +333,14 @@ section {
position: relative; position: relative;
background: white; background: white;
margin: auto; margin: auto;
width: 820px; max-width: 820px;
min-height: calc(100% - 98px); min-height: calc(100% - 94px);
z-index: 10; z-index: 10;
padding: 15px; padding: 15px;
text-align: justify; text-align: justify;
} }
section#index { section#index {
min-height: calc(100% - 98px - 320px); min-height: calc(100% - 95px - 320px);
} }
section h1 { section h1 {
@@ -254,12 +349,15 @@ section h1 {
margin-top: 20px; margin-top: 20px;
border-bottom: 1px solid #bbb; border-bottom: 1px solid #bbb;
} }
section#index h1{
font-size: 40px;
}
section .subtitle { section .subtitle {
font-variant: small-caps; font-variant: small-caps;
font-weight: 500; font-weight: 500;
background: #ddd; background: #ddd;
margin: 0 20px 20px 0; margin: 0 20px 5px 0;
display: inline-block; display: inline-block;
padding: 3px 5px; padding: 3px 5px;
float: right; float: right;
@@ -269,23 +367,30 @@ section p {
margin: 20px 0; margin: 20px 0;
} }
@media (max-width: 800px) {
section h1 {
font-size: 1.8rem;
text-align: left;
}
section#index h1 {
font-size: 1.7rem;
}
}
/***************************************/ /***************************************/
footer { footer {
background: #212121; background: #212121;
width: 820px; max-width: 820px;
padding: 15px; padding: 15px;
margin: 15px auto 0 auto; margin: 15px auto 0 auto;
color: #c1c1c1; color: #c1c1c1;
text-align: left;
}
footer {
} }
footer #footernav { footer #footernav {
float: right;
padding: 0; padding: 0;
margin: 0; margin: 0;
margin-left: auto;
} }
footer a { footer a {
@@ -296,13 +401,19 @@ footer a:hover {
color: white; color: white;
} }
footer .flex {
display: flex;
flex-wrap: wrap;
gap: 1rem;
}
/*********************************/ /*********************************/
/** Index page **/ /** Index page **/
/*********************************/ /*********************************/
#indexFullW { #indexFullW {
position: relative; position: relative;
background: url('../img/aside.jpg') center center no-repeat #070707; background: url('../img/aside.jpg') left center no-repeat #070707;
width: 100%; width: 100%;
height: 320px; height: 320px;
z-index: 100; z-index: 100;
@@ -311,44 +422,25 @@ footer a:hover {
#AScontent { #AScontent {
height: 320px; height: 320px;
width: 850px; max-width: 850px;
margin: auto; margin: auto;
position: relative;
} }
#spacebeforesponsors { #imglegend {
height: 238px; text-align: right;
}
#sponsors {
height: 70px;
background: rgba(0,0,0,0.5); background: rgba(0,0,0,0.5);
padding: 5px 30px;
}
#sponsors a {
float: right;
display: block;
padding-top: 5px;
padding-left: 5px;
padding-right: 5px;
}
#sponsors a img {
height: 60px;
display: inline;
}
#sponsors p {
float: left;
color: white; color: white;
font-size: 20px; font-size: 14px;
font-variant: small-caps; font-variant: small-caps;
line-height: 70px; line-height: 20px;
position: absolute;
width: 100%;
bottom: 0px;
} }
#imglegend p {
section .thumb { padding: 5px;
margin: 0 10px; height: 20px;
border: 1px solid #aaa;
} }
/*********************************/ /*********************************/
@@ -370,9 +462,10 @@ section .thumb {
cursor: pointer; cursor: pointer;
font-weight: 500; font-weight: 500;
font-size: 1.1em; font-size: 1.1em;
line-height: 56px;
} }
.action .title a, .action .title p { .action .title a, .action .title p {
padding: 15px 10px 15px 71px; padding: 0 10px 0 71px;
margin: 0; margin: 0;
color: inherit; color: inherit;
display: block; display: block;
@@ -394,4 +487,4 @@ section .thumb {
} }
.action .description p { .action .description p {
padding: 10px 20px; padding: 10px 20px;
} }

View File

@@ -1,3 +1,4 @@
/* Feuille de style: css/d.map.css */
/* Custom configuration for the map page */ /* Custom configuration for the map page */
html { html {
@@ -9,10 +10,54 @@ body {
footer { footer {
position: absolute; position: absolute;
bottom: 0; bottom: 0;
left: calc(50% - 425px); right: 50%;
transform: translateX(50%);
width: 100%;
max-width: 820px;
z-index: 10000; z-index: 10000;
} }
#advert {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 9999;
background: rgba(50,50,50,0.8);
color: #ddd;
padding: 20px;
border-bottom: 6px solid blue;
text-align: center;
}
#advert a{
color: white;
}
#advert .dots span {
opacity: 0;
animation: appear 1.5s infinite;
}
#advert .dots span:nth-child(1) {
animation-delay: 0s;
}
#advert .dots span:nth-child(2) {
animation-delay: 0.3s;
}
#advert .dots span:nth-child(3) {
animation-delay: 0.6s;
}
@keyframes appear {
0%, 80%, 100% {
opacity: 0;
}
40% {
opacity: 1;
}
}
/***************************************** /*****************************************
Controls of the map Controls of the map
*****************************************/ *****************************************/
@@ -121,10 +166,12 @@ footer {
.leaflet-control-layers-expanded a { .leaflet-control-layers-expanded a {
display: none !important; display: none !important;
} }
.leaflet-control-layers-list { .leaflet-control-layers-list {
padding: 3px 8px !important; padding: 3px 8px !important;
color: white !important; color: white !important;
background: #212121 !important; background: #212121 !important;
width: inherit !important;
} }
/* Scale */ /* Scale */
@@ -152,19 +199,23 @@ footer {
#footer-credits, #footer-legend { #footer-credits, #footer-legend {
background: #212121; background: #212121;
width: 820px;
padding: 15px; padding: 15px;
margin: 15px auto 0 auto; margin: 15px auto 0 auto;
color: #c1c1c1; color: #c1c1c1;
text-align: left; text-align: left;
position: absolute; position: absolute;
bottom: 0; bottom: 0;
left: calc(50% - 425px); right: 50%;
transform: translateX(50%);
width: 100%;
max-width: 820px;
z-index: 10000; z-index: 10000;
display: flex;
} }
#footer-credits .close-link, #footer-legend .close-link { #footer-credits .close-link, #footer-legend .close-link {
float: right; position: absolute;
right: 10px;
color: white; color: white;
padding: 0 8px; padding: 0 8px;
cursor: pointer; cursor: pointer;
@@ -177,6 +228,14 @@ footer {
color: white; color: white;
} }
.legend_item {
flex: 1;
text-align: center;
}
.poi_icon {
height: 15px;
}
.leaflet-fullscreen-on .easy-button-container { .leaflet-fullscreen-on .easy-button-container {
display: none; display: none;
} }

676
public/views/css/d.poi.css Executable file
View File

@@ -0,0 +1,676 @@
/* Feuille de style: css/d.poi.css */
/*********************************/
/** Common **/
/*********************************/
html, body {
height: 100%;
}
#sticky {
position: relative;
min-height: 0;
top: 65%;
z-index: 10;
pointer-events: none;
}
#sticky * {
pointer-events: auto;
}
@keyframes fadeinfadeout {
0% {color: #444;}
50% {color: #999;}
100% {color: #444;}
}
#slide-icon {
position: absolute;
left: 400px;
top: -35px;
color: #000;
font-size: 60px;
color: #555;
animation-name: fadeinfadeout;
animation-duration: 2s;
animation-iteration-count: infinite;
cursor: pointer;
}
#mapid {
position: fixed;
height: 100%;
width: 100%;
top: 0;
}
section.archive > * {
opacity: 0.5;
}
/* Comments of a poi */
#new_comment {
clear: both;
margin: 30px auto 0 auto;
width: 90%;
background: #efefef;
border: 1px solid #ccc;
border-bottom: 3px solid #ccc;
}
#new_comment_label {
background: #ccc;
padding: 15px 10px;
cursor: pointer;
font-weight: 500;
font-size: 1.1em;
}
#new_comment_label p {
margin: 0;
}
#new_comment_label input {
display: none;
margin: 5px;
float: right;
padding: 5px 10px;
position: relative;
top: -7px;
width: 140px;
}
#new_comment_form {
display: none;
}
#new_comment_form textarea {
margin: 0;
border: 0;
font-size: 14px;
width: calc(100% - 20px);
}
#new_comment_label.sent {
cursor: default;
}
section article {
margin: 30px auto 0 auto;
width: 90%;
background: #efefef;
border: 1px solid #ccc;
border-bottom: 2px solid #ccc;
border-bottom-right-radius: 5px;
border-bottom-left-radius: 5px;
}
section .comment_title {
background: #ccc;
padding: 5px 10px;
}
section .delete_link {
font-variant: small-caps;
font-weight: 500;
padding: 4px 0;
float: right;
}
section .icon {
border: 1px solid #999;
border-radius: 3px;
margin: 0 3px 0 3px;
padding: 4px 0;
line-height: 20px;
text-align: center;
width: 28px;
background: #ccc;
vertical-align: middle;
}
section .icon.avatar {
padding: 0;
height: 28px;
}
section .comment_content {
padding: 5px 10px;
}
section article.comment_archive {
opacity: 0.5;
}
/*********************************/
/** Editor page **/
/*********************************/
form.form input, form.form textarea, #locale {
font-size: 16px;
padding: 10px;
}
form.form input, form.form textarea, form.form input[type=radio]:checked+label, #locale {
background: #ddd;
border-bottom: 2px solid #ccc;
}
form.form h1 input {
flex: 2 !important;
font-size: 18px;
}
form.form h1 {
padding: 10px 0;
margin: 0 0 10px 0;
}
#locale {
flex: 1;
margin: 10px 5px 0 5px;
font-size: 17px;
}
.flex_line {
display: flex;
flex-direction: row;
position: relative;
}
.flex_line > :first-child {
margin-left: 0 !important;
}
.flex_line > :last-child, .last-child {
margin-right: 0 !important;
}
.flex_line input[type=number], .flex_line input[type=text] {
flex: 1;
margin: 10px 5px 0 5px;
}
.noarrow::-webkit-inner-spin-button,
.noarrow::-webkit-outer-spin-button,
.noarrow {
-webkit-appearance: none;
-moz-appearance: textfield;
appearance: textfield;
margin: 0;
}
form.form input[type=submit] {
width: auto;
display: block;
margin: 10px auto;
border-bottom: 2px solid blue;
}
form.form input[type=radio] {
position: absolute;
float: left;
opacity: 0%;
top: 50%;
left: 50%;
}
form.form input[type=radio]+label {
margin-top: 10px;
font-size: 13px;
flex: 1;
text-align: center;
padding: 10px;
vertical-align: middle;
border-bottom: 2px solid transparent;
}
form.form input[type=radio]+label img {
width: 32px;
height: 32px;
}
#specific_form .threecb:after {
font-family: "Font Awesome 5 Free";
font-weight: 400;
vertical-align: middle;
padding: 3px 8px 2px 4px;
margin: 2px 10px;
display: inline-block;
width: 21px;
background: #ddd;
font-size: 25px;
border-radius: 100px;
}
#specific_form .threecb.check:after {
content: "\f058"; /* check */
}
#specific_form .threecb.uncheck:after {
content: "\f057"; /* cross */
}
#specific_form .threecb.intermediate:after {
content: "\f059"; /* question */
}
#specific_form input {
margin: 2px 10px;
}
#specific_form textarea {
margin: 5px 0;
display: block;
width: calc(100% - 20px);
height: 100px;
}
#specific_form .flex_line {
align-items: center;
}
#specific_form .flex_line input {
flex: 1;
}
#abstract {
text-align: center;
color: #555;
font-style: italic;
}
form.form input[type="checkbox"] {
display:none;
}
form.form input[type="checkbox"] + span:before {
font-family: "Font Awesome 5 Free";
font-weight: 400;
vertical-align: middle;
padding: 2px 5px 2px 4px;
margin-right: 10px;
display: inline-block;
width: 21px;
background: #ddd;
font-size: 25px;
}
form.form input[type="checkbox"] + span:before {
content: "\f0c8"; /* check-empty */
}
form.form input[type="checkbox"]:checked + span:before {
content: "\f14a"; /* check */
}
#permalink_container {
position: relative;
margin: 2px 0;
}
#permalink {
width: calc(100% - 194px);
padding-left: 184px;
}
#permalink_label {
position: absolute;
top: 10px;
left: 10px;
opacity: 0.8;
font-size: 16px;
}
/*****************************************
Controls of the map
*****************************************/
/* General */
.leaflet-control-container {
position: absolute !important;
width: 850px !important;
height: 100%;
left: calc(50% - 425px) !important;
font-family: "Fira Sans", "Open Sans",Helvetica,Arial,sans-serif !important;
}
.leaflet-fullscreen-on .leaflet-control-container {
position: absolute !important;
width: 100% !important;
left: 0 !important;
}
.leaflet-bottom.leaflet-left {
bottom: 35% !important;
margin-bottom: -50px !important;
}
.leaflet-fullscreen-on .leaflet-bottom.leaflet-left {
margin-bottom: 15px !important;
margin-left: 15px !important;
bottom: 0 !important;
}
.leaflet-bottom.leaflet-right {
bottom: 35% !important;
margin-bottom: -50px !important;
}
.leaflet-fullscreen-on .leaflet-bottom.leaflet-right {
margin-bottom: 15px !important;
margin-right: 15px !important;
bottom: 0 !important;
}
.leaflet-control {
clear: none !important;
padding: 0 !important;
border-radius: 0 !important;
box-shadow: none !important;
color: #c1c1c1 !important;
}
.leaflet-right .leaflet-control {
margin: 0 0 0 15px !important;
}
.leaflet-left .leaflet-control {
margin: 0 15px 0 0 !important;
}
.leaflet-control a, .leaflet-control button {
display: inline-block !important;
float: none !important;
border: none !important;
background-color: #212121 !important;
border-radius: 0 !important;
color: #c1c1c1 !important;
border-right: 1px #3e3e3e solid !important;
}
.leaflet-control a:last-child, .leaflet-control button:last-child {
border-right: none !important;
}
/* Zoom */
.leaflet-control-zoom-in, .leaflet-control-zoom-out {
font-size: 10px !important;
}
.leaflet-disabled {
background-color: rgba(33, 33, 33, 0.8) !important;
opacity: 0.8 !important;
}
/* Fullscreen */
.leaflet-control-fullscreen a {
background: #212121 !important;
}
.leaflet-control-fullscreen a:before {
content: "\f065";
font-family: "Font Awesome 5 Free";
font-weight: 900;
background: none !important;
}
.leaflet-fullscreen-on .leaflet-control-fullscreen a:before {
content: "\f066";
font-family: "Font Awesome 5 Free";
font-weight: 900;
}
/* Baselayers */
.leaflet-control-layers a {
background: #212121 !important;
width: 26px !important;
height: 26px !important;
line-height: 26px !important;
text-align: center !important;
border-right: none !important;
}
.leaflet-control-layers a:before {
content: "\f5fd";
font-family: "Font Awesome 5 Free";
font-weight: 900;
background: none !important;
}
.leaflet-control-layers-expanded a {
display: none !important;
}
.leaflet-control-layers-list {
padding: 3px 8px !important;
color: white !important;
background: #212121 !important;
width: inherit !important;
}
/* Scale */
.leaflet-control-scale-line {
height: 30px !important;
top: 2px !important;
position: relative !important;
background: #212121 !important;
color: #c1c1c1 !important;
text-align: center !important;
border: none !important;
font-size: 12px !important;
line-height: 30px !important;
}
.leaflet-control-scale {
opacity: 0.8 !important;
}
#elevation_icon {
font-size: 20px;
cursor: pointer;
position: relative;
top: 18px;
right: 34px;
}
#elevation_icon i {
position: absolute;
}
/*****************************************
View page
*****************************************/
.poi-icon-wrapper {
position: relative;
display: inline-flex;
align-items: center;
margin-right: 10px;
}
/* Tooltip */
.poi-icon-wrapper[data-tooltip]:hover::after {
content: attr(data-tooltip);
position: absolute;
left: 40px;
top: 50%;
transform: translateY(-50%);
background: rgba(255, 255, 255, 0.9); /* blanc transparent */
color: #000;
padding: 6px 10px;
border-radius: 6px;
font-size: 15px; /* demandé */
border: 1px solid blue; /* bordure fine noire */
white-space: nowrap;
pointer-events: none;
z-index: 9999;
}
/* Petite flèche */
.poi-icon-wrapper[data-tooltip]:hover::before {
content: "";
position: absolute;
left: 32px;
top: 50%;
transform: translateY(-50%);
border: 6px solid transparent;
border-right-color: blue; /* même couleur que la bulle */
z-index: 9999;
filter: drop-shadow(0 0 0.5px #000); /* bordure subtile sur la flèche */
}
/* Fiche d'identité POI */
.poi-idcard {
width: 100%;
padding: 20px 15px;
background: rgba(200, 220, 255, 0.25);
border-bottom: 1px solid #bbb;
margin: 0;
box-sizing: border-box;
display: flex;
flex-direction: column;
gap: 8px;
}
/* Ligne principale : coordonnées + type */
.poi-id-main {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 19px; /* demandé */
font-weight: 600;
}
/* Coordonnées */
.poi-id-coords {
display: flex;
align-items: center;
gap: 8px;
}
.poi-id-coords a {
color: #0055aa;
text-decoration: none;
}
.poi-id-coords a:hover {
text-decoration: underline;
}
.poi-id-elev {
color: #333;
}
/* Type */
.poi-id-type {
display: flex;
align-items: center;
gap: 6px;
}
/* Label discret */
.poi-id-label {
font-weight: 500;
color: #444;
}
/* Dates en petit */
.poi-id-dates {
font-size: 15px; /* demandé */
color: #555;
display: flex;
gap: 20px;
}
/* Mobile */
@media (max-width: 700px) {
.poi-id-main {
flex-direction: column;
align-items: flex-start;
gap: 4px;
}
.poi-id-dates {
flex-direction: column;
gap: 2px;
}
}
/*****************************************
* CHAMPS GÉNÉRIQUES
*****************************************/
.field {
display: flex;
flex-direction: column;
gap: 4px;
padding-bottom: 12px;
}
.field > label {
font-weight: 600;
font-size: 17px;
}
/*****************************************
* TEXTES LONGS (t_)
*****************************************/
.field-t .field-value {
padding: 10px 12px;
font-size: 15px;
}
/*****************************************
* NOMBRES ET LIENS EN LIGNE (n_ et l_)
*****************************************/
/* Label + valeur sur une seule ligne */
.field-n,
.field-l {
flex-direction: row;
align-items: baseline;
gap: 6px;
}
/* On enlève le padding bas qui faisait “bloc” */
.field-n,
.field-l {
padding-bottom: 4px;
}
/* Valeur inline */
.inline-value {
display: inline-block;
font-size: 15px;
color: #222;
}
/* Liens */
.inline-value a {
color: #1a5ad7;
font-weight: 600;
text-decoration: none;
}
.inline-value a:hover {
text-decoration: underline;
}
/*****************************************
* Booleans grid in poi view
*****************************************/
.bool-grid {
margin: 20px 0 0 0;
padding: 20px 15px;
background: rgba(200, 220, 255, 0.25);
border-top: 1px solid #bbb;
}
.bool-row {
display: grid;
grid-auto-flow: column;
grid-auto-columns: 1fr;
text-align: center;
margin-bottom: 10px;
}
.bool-row.labels {
font-size: 16px;
}
.bool-label {
padding: 5px;
}
.bool-row.values {
margin-top: 5px;
}
.boolean-pill {
display: inline-block;
padding: 8px 12px;
border-radius: 20px;
font-weight: 700;
font-size: 18px;
background: white;
}
@media (max-width: 900px) {
.bool-row {
grid-auto-flow: row;
grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
}
}

View File

@@ -1,9 +1,10 @@
/* Feuille de style: css/d.user.css */
/*********************************/ /*********************************/
/** Login page **/ /** Login page **/
/*********************************/ /*********************************/
form.form { form.form {
width: 50%; width: 80%;
margin: 25px auto; margin: 25px auto;
text-align: center; text-align: center;
} }
@@ -24,12 +25,6 @@ form.form input {
font-size: 18px; font-size: 18px;
} }
form.form input[type=submit] {
width: auto;
margin: auto;
border-bottom: 2px solid blue;
}
/*********************************/ /*********************************/
/** Profile page **/ /** Profile page **/
/*********************************/ /*********************************/
@@ -204,16 +199,3 @@ form.edituser #picturebuttons a {
padding: 0; padding: 0;
height: 28px; height: 28px;
} }
#member_list .pagebuttons {
text-align: center;
}
#member_list .pagebuttons a {
background: #efefef;
border: 1px solid #ccc;
padding: 5px;
font-size: 1.5em;
}
#member_list .pagebuttons .previous {
margin-right: -1px;
}

View File

@@ -1,3 +1,4 @@
/* Feuille de style: css/d.wiki.css */
/*********************************/ /*********************************/
/** View page **/ /** View page **/
/*********************************/ /*********************************/
@@ -32,12 +33,6 @@ form.form input {
font-size: 17px; font-size: 17px;
} }
form.form input[type=submit] {
width: auto;
margin: auto;
border-bottom: 2px solid blue;
}
#wikiContent { #wikiContent {
margin: 50px 0; margin: 50px 0;
} }
@@ -50,6 +45,7 @@ form.form input[type=submit] {
#wikiContent blockquote { margin-left: 40px; margin-right: 40px } #wikiContent blockquote { margin-left: 40px; margin-right: 40px }
#wikiContent ol, #wikiContent ul, #wikiContent dd { margin-left: 40px } #wikiContent ol, #wikiContent ul, #wikiContent dd { margin-left: 40px }
#wikiContent ol ul, #wikiContent ul ol, #wikiContent ul ul, #wikiContent ol ol { margin-top: 0; margin-bottom: 0 } #wikiContent ol ul, #wikiContent ul ol, #wikiContent ul ul, #wikiContent ol ol { margin-top: 0; margin-bottom: 0 }
#wikiContent hr { border: 1px solid #bbb }
#wikiContent .footnotes { #wikiContent .footnotes {
font-size: 0.8em; font-size: 0.8em;
@@ -57,10 +53,31 @@ form.form input[type=submit] {
#wikiContent .footnotes p { #wikiContent .footnotes p {
margin: 0.4em 0; margin: 0.4em 0;
} }
#wikiContent hr {
border: 1px inset;
}
#wiki_page.archive { #wiki_page.archive {
opacity: 0.5; opacity: 0.5;
} }
#wikiContent img {
max-width: 100%;
border: 1px solid #bbb;
}
#wikiContent .imglegend {
position: relative;
}
#wikiContent .imglegend img {
display: block;
}
#wikiContent .imglegend p {
display: block;
background: rgba(0,0,0,0.5);
color: white;
font-size: 14px;
font-variant: small-caps;
line-height: 20px;
position: absolute;
bottom: 0;
right: 0;
margin: 0;
padding: 2px 5px;
}

View File

@@ -0,0 +1,46 @@
<!DOCTYPE html>
<!-- Page: admin backups -->
<html lang="fr">
<?php include('blocks/d.head.html'); ?>
<body>
<?php include('blocks/d.nav.html'); ?>
<section>
<h1><?=$head['title']?></h1>
<br>
<!-- Command output -->
<pre><?php
foreach($output as $line) {
echo $line."<br>";
}
?></pre>
<br>
<!-- Download links -->
<?php $i=0;
foreach($backup_file as $file) {
if (file_exists($file ?? '')) { ?>
<a href='<?=$config['rel_root_folder']?>tmp/<?=$backup_filename[$i]?>' target='_blank'><i class="fas fa-file-export"></i> Télécharger le fichier "<i><?=$backup_filename[$i]?></i>"</a><br>
<?php } else { ?>
Fichier <?=$file?> non généré
<?php }
$i++;
}?>
<br>
<!-- Archive list -->
<h4>Archives des anciennes sauvegardes</h4>
<ul style="padding: 1em 0 1em 40px;">
<?php foreach($backup_files as $file) { ?>
<li style="padding: 0 0 0.2em 0;"><?=basename($file)?> - <a href='<?=$config['rel_root_folder']?>tmp/<?=basename($file)?>' target='_blank'><i class="fas fa-download"></i> Télécharger</a> - <a href='<?=$config['rel_root_folder']?>admin/<?=$controller->splitted_url[1]?>/delete/<?=basename($file)?>'><i class="fas fa-trash"></i> Effacer</a></li>
<?php } ?>
</ul>
</section>
<?php include('blocks/d.footer.html'); ?>
</body>
</html>

View File

@@ -0,0 +1,25 @@
<!DOCTYPE html>
<!-- Page: admin git pull -->
<html lang="fr">
<?php include('blocks/d.head.html'); ?>
<body>
<?php include('blocks/d.nav.html'); ?>
<section>
<h1><?=$head['title']?></h1>
<br>
<!-- Command output -->
<pre><?php
foreach($output as $line) {
echo $line."<br>";
}
?></pre>
</section>
<?php include('blocks/d.footer.html'); ?>
</body>
</html>

31
public/views/d.admin.html Executable file
View File

@@ -0,0 +1,31 @@
<!DOCTYPE html>
<!-- Page: admin dashboard -->
<html lang="fr">
<?php include('blocks/d.head.html'); ?>
<body>
<?php include('blocks/d.nav.html'); ?>
<!-- Admin actions -->
<section>
<h1>Administration</h1>
<br>
<?php if($user->rankIsHigher("administrator")) { ?>
<!-- Administrator tools -->
<a href="<?=$config['rel_root_folder']?>admin/git-pull" class="button"><i class="fas fa-sync-alt"></i> Mettre à jour</a> <small>Met à jour le logiciel depuis le dépôt GIT.</small><br><br>
<a href="<?=$config['rel_root_folder']?>admin/sql-backup" class="button"><i class="fas fa-file-export"></i> Sauvegarde SQL</a><a href="<?=$config['rel_root_folder']?>admin/files-backup" class="button"><i class="fas fa-file-export"></i> Archive des médias</a><small>Génère un dump SQL et une archive de fichiers téléchargeable.</small><br><br>
<?php } ?>
<?php if($user->rankIsHigher("moderator")) { ?>
<!-- Moderator tools -->
<a href="<?=$config['rel_root_folder']?>admin/logs" class="button"><i class="fas fa-history"></i> Voir les logs</a> <small>Permet d'accéder aux 200 dernières lignes des logs bruts des actions sur la base de données.</small><br><br>
<a href="<?=$config['rel_root_folder']?>admin/wiki-files" class="button"><i class="fas fa-paperclip"></i> Fichiers attachés</a><small>Gérer les fichiers attachés pour le wiki : liste, ajout, suppression...</small><br><br>
<a href="<?=$config['rel_root_folder']?>admin/stats" class="button"><i class="fas fa-chart-line"></i> Statistiques</a><small>Analyser les logs et afficher les statistiques.</small><br><br>
<?php } ?>
</section>
<?php include('blocks/d.footer.html'); ?>
</body>
</html>

View File

@@ -1,41 +1,46 @@
<!DOCTYPE html> <!DOCTYPE html>
<!-- Page: admin logs -->
<html lang="fr"> <html lang="fr">
<? include('blocks/d.head.html'); ?> <?php include('blocks/d.head.html'); ?>
<body> <body>
<? include('blocks/d.nav.html'); ?> <?php include('blocks/d.nav.html'); ?>
<!-- Logs viewer -->
<section> <section>
<h1>Logs.</h1> <h1><?=$head['title']?></h1>
<!-- Log file selector -->
<span class="subtitle"> <span class="subtitle">
<select id="logfile"> <select id="logfile">
<? $i = 0; <?php $i = 0;
foreach ($files_list as $row) { foreach ($files_list as $row) {
if ($row != "." && $row != "..") { ?> if ($row != "." && $row != "..") { ?>
<option <?=$i==$filenb?'selected':''?> value="<?=$i?>"><? echo $row; ?></option> <option <?=$i==$filenb?'selected':''?> value="<?=$i?>"><?php echo $row; ?></option>
<? $i++; <?php $i++;
} ?> } ?>
<? } ?> <?php } ?>
</select> </select>
</span> </span>
<br> <br>
<br> <br>
<pre><? <!-- Log content -->
<pre><?php
foreach($output as $line) { foreach($output as $line) {
echo $line."<br>"; echo $line."<br>";
} }
?></pre> ?></pre>
</section> </section>
<!-- Log file navigation -->
<script type="text/javascript"> <script type="text/javascript">
$( "#logfile" ).change(function() { $( "#logfile" ).change(function() {
window.location.href = "<?=$config['rel_root_folder']?>admin/logs/"+$( this ).val(); window.location.href = "<?=$config['rel_root_folder']?>admin/logs/"+$( this ).val();
}); });
</script> </script>
<? include('blocks/d.footer.html'); ?> <?php include('blocks/d.footer.html'); ?>
</body> </body>
</html> </html>

View File

@@ -0,0 +1,31 @@
<!DOCTYPE html>
<!-- Page: admin statistics -->
<html lang="fr">
<?php include('blocks/d.head.html'); ?>
<body>
<?php include('blocks/d.nav.html'); ?>
<!-- Statistics summary -->
<section>
<h1><?=$head['title']?></h1>
<br>
<!-- Command output -->
<pre><?php
print_r($output);
?></pre>
<br>
<!-- Report link -->
<?php if (file_exists($report)) { ?>
<a href='<?=$config['rel_root_folder']?>tmp/report.html' target='_blank'><i class="fas fa-chart-line"></i> Voir le rapport</a>
<?php } else { ?>
Echec de la commande
<?php } ?>
</section>
<?php include('blocks/d.footer.html'); ?>
</body>
</html>

View File

@@ -0,0 +1,80 @@
<!DOCTYPE html>
<!-- Page: admin wiki files -->
<html lang="fr">
<?php include('blocks/d.head.html'); ?>
<body>
<?php include('blocks/d.nav.html'); ?>
<!-- Files table -->
<section id="wiki_files">
<h1><?=$head['title']?></h1>
<!-- Pagination summary -->
<p class="subtitle">Fichiers attachés <?=$first?> à <?=$last?> sur les <?=$filenb?> présents</p>
<br>
<br>
<!-- Upload form -->
<form action="<?=$config['rel_root_folder']?>admin/wiki-files/upload/" method="post" enctype="multipart/form-data" id="send_file">
<div>
<label for="file">Envoyer un fichier :</label>
<input type="file" id="file" name="file">
</div>
<input type="submit" value="Envoyer">
</form>
<!-- File list -->
<table>
<tr class="first">
<th>
<a href="<?=$config['rel_root_folder']?>admin/wiki-files/<?=$page+1?>?orderby=name&amp;order=<?=$order=='ASC'?'DESC':'ASC'?>">Nom</a>
<?=$orderby=='name'?$order=='ASC'?'<i class="fas fa-caret-down" aria-hidden="true"></i>':'<i class="fas fa-caret-up" aria-hidden="true"></i>':''?>
</th>
<th>
<a href="<?=$config['rel_root_folder']?>admin/wiki-files/<?=$page+1?>?orderby=type&amp;order=<?=$order=='ASC'?'DESC':'ASC'?>">Type</a>
<?=$orderby=='type'?$order=='ASC'?'<i class="fas fa-caret-down" aria-hidden="true"></i>':'<i class="fas fa-caret-up" aria-hidden="true"></i>':''?>
</th>
<th>
<a href="<?=$config['rel_root_folder']?>admin/wiki-files/<?=$page+1?>?orderby=size&amp;order=<?=$order=='ASC'?'DESC':'ASC'?>">Taille</a>
<?=$orderby=='size'?$order=='ASC'?'<i class="fas fa-caret-down" aria-hidden="true"></i>':'<i class="fas fa-caret-up" aria-hidden="true"></i>':''?>
</th>
<th>
<a href="<?=$config['rel_root_folder']?>admin/wiki-files/<?=$page+1?>?orderby=creation_date&amp;order=<?=$order=='ASC'?'DESC':'ASC'?>">Date de création</a>
<?=$orderby=='creation_date'?$order=='ASC'?'<i class="fas fa-caret-down" aria-hidden="true"></i>':'<i class="fas fa-caret-up" aria-hidden="true"></i>':''?>
</th>
<?php if ($user->rankIsHigher("administrator")) { ?>
<th>Suppression</th>
<?php } ?>
</tr>
<?php foreach (array_slice($files, $first-1, $rows_per_pages, true) as $file) { ?>
<tr>
<td>
<a href="<?=$config['rel_root_folder']?>medias/wiki/<?=$file['name']?>"><?=$file['name']?></a>
</td>
<td><i class='fas <?=getFontAwesomeIcon($file['type'])?>'></i> <?=$file['type']?></td>
<td><?=formatBytes($file['size'], $user->locale)?></td>
<td><?php echo datefmt_format($user->date_format,date_create($file['creation_date'], new DateTimeZone("UTC"))) ?></td>
<?php if ($user->rankIsHigher("administrator")) { ?>
<td class="center">
<a href="<?=$config['rel_root_folder']?>admin/wiki-files/delete/<?=$file['name']?>?orderby=<?=$orderby?>&amp;order=<?=$order?>" onclick="return confirm('Es-tu sûr de vouloir supprimer ?');"><span class="external-link"><i class="fas fa-trash"></i></span></a>
</td>
<?php } ?>
</tr>
<?php } ?>
</table>
<!-- Pagination controls -->
<div class="pagebuttons">
<?php if ($page != 0) { ?><a class="previous" href="<?=$config['rel_root_folder']?>admin/wiki-files/<?=$page?>?orderby=<?=$orderby?>&amp;order=<?=$order?>"><i class="fas fa-chevron-left fa-fw"></i></a><?php }
if (($page+1)*$rows_per_pages < $filenb) { ?><a class="next" href="<?=$config['rel_root_folder']?>admin/wiki-files/<?=$page+2?>?orderby=<?=$orderby?>&amp;order=<?=$order?>"><i class="fas fa-chevron-right fa-fw"></i></a><?php } ?>
</div>
</section>
<?php include('blocks/d.footer.html'); ?>
</body>
</html>

View File

@@ -1,52 +1,66 @@
<!DOCTYPE html> <!DOCTYPE html>
<!-- Page: blog editor -->
<html lang="fr"> <html lang="fr">
<? include('blocks/d.head.html'); ?> <?php include('blocks/d.head.html'); ?>
<body> <body>
<? include('blocks/d.nav.html'); ?> <?php include('blocks/d.nav.html'); ?>
<!-- Blog edit form -->
<section> <section>
<? if(isset($new) AND $new==1) { ?> <?php if(isset($new) AND $new==1) { ?>
<!-- Create article -->
<form class="form" action="<?=$config['rel_root_folder']?>blog/new" method="post"> <form class="form" action="<?=$config['rel_root_folder']?>blog/new" method="post">
<? } <?php }
else { ?> else { ?>
<!-- Update article -->
<form class="form" action="<?=$config['rel_root_folder']?>blog/<?=$blogArticle->permalink?>/edit" method="post"> <form class="form" action="<?=$config['rel_root_folder']?>blog/<?=$blogArticle->permalink?>/edit" method="post">
<? } ?> <?php } ?>
<h1> <h1>
<!-- Locale and title -->
<select name="locale" id="locale"> <select name="locale" id="locale">
<? foreach($locales->objs as $locale) { ?> <?php foreach($locales->objs as $locale) { ?>
<option <?=$blogArticle->locale==$locale->name?'selected':''?> value="<?=$locale->name?>"><?=$locale->display_name?></option> <option <?=$blogArticle->locale==$locale->name?'selected':''?> value="<?=$locale->name?>"><?=$locale->display_name?></option>
<? } ?> <?php } ?>
</select> </select>
<input type="text" value="<?=$blogArticle->name?>" name="name" id="name" placeholder="Titre"> <input type="text" value="<?=$blogArticle->name?>" name="name" id="name" placeholder="Titre">
</h1> </h1>
<? if(isset($error) AND $error=="permalink") { ?> <?php if(isset($error) AND $error=="permalink") { ?>
<!-- Permalink error -->
<p style="color: red;">L'URL sélectionnée est déjà prise.</p> <p style="color: red;">L'URL sélectionnée est déjà prise.</p>
<? } ?> <?php } ?>
<!-- Article content -->
<textarea rows="30" name="content" id="content" placeholder="Contenu de l'article"><?=$blogArticle->content?></textarea> <textarea rows="30" name="content" id="content" placeholder="Contenu de l'article"><?=$blogArticle->content?></textarea>
<? if(isset($new) AND $new==1) { ?> <?php if(isset($new) AND $new==1) { ?>
<input type="text" value="<?=$blogArticle->permalink?>" name="permalink" id="permalink" placeholder="URL"> <!-- Permalink settings -->
<? } ?> <div id="permalink_container">
<label id="permalink_label" for="permalink"><?=$config['web_root_folder']?>blog/</label>
<input type="text" name="permalink" id="permalink" placeholder="URL" required>
</div>
<?php } ?>
<!-- Article options -->
<label for="is_commentable"> <label for="is_commentable">
<input type="checkbox" name="is_commentable" id="is_commentable" <input type="checkbox" name="is_commentable" id="is_commentable"
<? if($blogArticle->is_commentable == 't') { ?> <?php if($blogArticle->is_commentable == 't') { ?>
checked checked
<? } ?> <?php } ?>
/> />
<span>Autoriser les commentaires</span> <span>Autoriser les commentaires</span>
</label> </label>
<!-- Form submission -->
<input name="submit" id="submit" type="submit" value="Envoyer"> <input name="submit" id="submit" type="submit" value="Envoyer">
</form> </form>
</section> </section>
<!-- Permalink generation -->
<script type="text/javascript"> <script type="text/javascript">
$( "#name" ).keyup(function() { $( "#name" ).keyup(function() {
permalink = $( "#name" ).val(); permalink = $( "#name" ).val();
@@ -66,7 +80,7 @@ $( "#name" ).change(function() {
}); });
</script> </script>
<? include('blocks/d.footer.html'); ?> <?php include('blocks/d.footer.html'); ?>
</body> </body>
</html> </html>

View File

@@ -1,55 +1,60 @@
<!DOCTYPE html> <!DOCTYPE html>
<!-- Page: blog list -->
<html lang="fr"> <html lang="fr">
<? include('blocks/d.head.html'); ?> <?php include('blocks/d.head.html'); ?>
<body> <body>
<? include('blocks/d.nav.html'); ?> <?php include('blocks/d.nav.html'); ?>
<!-- Blog listing -->
<section id="blog_list"> <section id="blog_list">
<h1>Blog.</h1> <h1>Blog</h1>
<!-- Actions and pagination -->
<p class="subtitle"> <p class="subtitle">
<? if ($user->rankIsHigher("moderator")) { ?> <?php if ($user->rankIsHigher("moderator")) { ?>
<a href="<?=$config['rel_root_folder']?>blog/new"><i class="fas fa-plus"></i> Nouvel article</a> &mdash; <a href="<?=$config['rel_root_folder']?>blog/new"><i class="fas fa-plus"></i> Nouvel article</a> &mdash;
<? } ?> <?php } ?>
<a href="<?=$config['rel_root_folder']?>blog/rss"><i class="fas fa-rss" aria-hidden="true"></i> Flux RSS</a> &mdash; <a href="<?=$config['rel_root_folder']?>blog/rss"><i class="fas fa-rss" aria-hidden="true"></i> Flux RSS</a> &mdash;
Articles <?=$first?> à <?=$last?> sur <?=$blogArticles->number?> Articles <?=$first?> à <?=$last?> sur <?=$blogArticles->number?>
</p> </p>
<!-- Article cards -->
<div id="articles_list"> <div id="articles_list">
<? foreach ($blogArticles->objs as $row) { ?> <?php foreach ($blogArticles->objs as $row) { ?>
<article <? if($row->is_archive == 't') echo 'class="article_archive" '; ?>> <article<?php if($row->is_public == 'f') echo ' class="article_archive" '; ?>>
<h2 class="article_title"><?=$row->name?>.</h2> <h2 class="article_title"><?=$row->name?></h2>
<div class="article_content"><?=mb_substr($row->content_txt,0,200)?>...</div> <div class="article_content"><?=mb_substr($row->content_txt,0,200)?>...</div>
<p class="article_legend"> <p class="article_legend">
<a class="article_link" href="<?=$config['rel_root_folder']?>blog/<?=$row->permalink?>">Lire la suite...</a> <a class="article_link" href="<?=$config['rel_root_folder']?>blog/<?=$row->permalink?>">Lire la suite...</a>
<span class="article_infos"> <span class="article_infos">
Le <? echo strftime('%e %B %G',strtotime($row->update_date)) ?> par <?php echo datefmt_format($user->date_format,date_create($row->update_date, new DateTimeZone("UTC"))) ?> par
<? if ($user->rankIsHigher("registered")) { ?> <?php if ($user->rankIsHigher("registered")) { ?>
<a href="<?=$config['rel_root_folder']?>user/p/<?=$row->author?>"><?=$row->author_name?></a> <a href="<?=$config['rel_root_folder']?>user/p/<?=$row->author?>"><?=$row->author_name?></a>
<? } <?php }
else { ?> else { ?>
<?=$row->author_name?> <?=$row->author_name?>
<? } ?> <?php } ?>
</span> </span>
</p> </p>
</article> </article>
<? } ?> <?php } ?>
</div> </div>
<!-- Pagination controls -->
<div class="pagebuttons"> <div class="pagebuttons">
<? if ($page != 0) { ?><a class="previous" href="<?=$config['rel_root_folder']?>blog/<?=$page?>"><i class="fas fa-chevron-left fa-fw"></i></a><? } <?php if ($page != 0) { ?><a class="previous" href="<?=$config['rel_root_folder']?>blog/<?=$page?>"><i class="fas fa-chevron-left fa-fw"></i></a><?php }
if (($page+1)*$articles_per_pages < $blogArticles->number) { ?><a class="next" href="<?=$config['rel_root_folder']?>blog/<?=$page+2?>"><i class="fas fa-chevron-right fa-fw"></i></a><? } ?> if (($page+1)*$articles_per_pages < $blogArticles->number) { ?><a class="next" href="<?=$config['rel_root_folder']?>blog/<?=$page+2?>"><i class="fas fa-chevron-right fa-fw"></i></a><?php } ?>
</div> </div>
</section> </section>
<? include('blocks/d.footer.html'); ?> <?php include('blocks/d.footer.html'); ?>
</body> </body>
</html> </html>

View File

@@ -1,4 +1,4 @@
<? <?php /* Template: d.blog.list.rss */
$ts = gmdate("D, d M Y H:i:s", time() + 60) . " GMT"; $ts = gmdate("D, d M Y H:i:s", time() + 60) . " GMT";
header("Content-disposition: filename=blog.rss"); header("Content-disposition: filename=blog.rss");
@@ -26,20 +26,20 @@ echo ('<?xml version="1.0" encoding="UTF-8"?>'); ?>
<width>154</width> <width>154</width>
</image> </image>
<? foreach ($blogArticles->objs as $row) { ?> <?php foreach ($blogArticles->objs as $row) { ?>
<item> <item>
<title><?=$row->name?></title> <title><?=$row->name?></title>
<link><?=$config['web_root_folder']?>blog/<?=$row->permalink?></link> <link><?=$config['web_root_folder']?>blog/<?=$row->permalink?></link>
<guid><?=$config['web_root_folder']?>blog/<?=$row->permalink?></guid> <guid><?=$config['web_root_folder']?>blog/<?=$row->permalink?></guid>
<pubDate><?=gmdate(DATE_RFC822, strtotime($row->update_date))?></pubDate> <pubDate><?=gmdate(DATE_RSS, strtotime($row->update_date))?></pubDate>
<description><![CDATA[ <description><![CDATA[
<?=$row->content_html?> <?=$row->content_html?>
]]></description> ]]></description>
</item> </item>
<? } ?> <?php } ?>
</channel> </channel>
</rss> </rss>

156
public/views/d.blog.view.html Executable file
View File

@@ -0,0 +1,156 @@
<!DOCTYPE html>
<!-- Page: blog article -->
<html lang="fr">
<?php include('blocks/d.head.html'); ?>
<body>
<?php include('blocks/d.nav.html'); ?>
<?php
// Droits et état de l'article
$isArchiveOrPrivate = $blogArticle->is_archive == "t" || $blogArticle->is_public == "f";
$canViewHistory = $user->rankIsHigher('premium');
$canModerate = $user->rankIsHigher('moderator');
$canWriteComment = $user->rankIsHigher("registered");
$canOpenCommentForm = $canWriteComment && !$isArchiveOrPrivate;
$hasHistory = isset($blogHistory);
$isVisitor = $user->rank == "visitor";
$isCommentable = $blogArticle->is_commentable == "t";
?>
<!-- Blog article -->
<section id="blog_article" <?=$isArchiveOrPrivate ? 'class="archive"' : ''?>>
<h1><?=$blogArticle->name?></h1>
<?php if ($canViewHistory) { ?>
<!-- History and actions -->
<span class="subtitle">
<?php if ($hasHistory) { ?>
<select id="bloghistory">
<?php $historyIndex = 0; ?>
<?php foreach ($blogHistory->objs as $row) { ?>
<?php
$isSelected = $row->version_id == $blogArticle->version_id ? 'selected' : '';
$isActive = $row->is_archive == "f" ? '&bull; ' : '';
$formattedDate = datefmt_format(
$user->datetimeshort_format,
date_create($row->update_date, new DateTimeZone("UTC"))
);
?>
<option <?=$isSelected?> value="<?=$historyIndex?>"><?=$isActive?><?=$formattedDate?></option>
<?php $historyIndex++; ?>
<?php } ?>
</select>
<?php }
if ($canModerate && $hasHistory) { ?>
&mdash;
<?php }
if ($canModerate) { ?>
<a href="<?=$config['rel_root_folder']?>blog/<?=$blogArticle->permalink?>/edit"><i class="fas fa-pencil-alt"></i> Éditer l'article</a> &mdash;
<?php if ($blogArticle->is_public == 't') { ?>
<a href="<?=$config['rel_root_folder']?>blog/<?=$blogArticle->permalink?>/delete"><i class="fas fa-trash"></i> Effacer l'article</a>
<?php } else { ?>
<a href="<?=$config['rel_root_folder']?>blog/<?=$blogArticle->permalink?>/restore"><i class="fas fa-eye"></i> Restaurer l'article</a>
<?php } ?>
<?php } ?>
</span>
<?php } ?>
<!-- Article content -->
<div id="blogContent">
<?=$blogArticle->content_html?>
</div>
<!-- Signature -->
<p id="blogTimestamp">Article écrit par
<?php if ($user->rankIsHigher("blocked")) { ?>
<a href="<?=$config['rel_root_folder']?>user/p/<?=$blogArticle->author?>"><?=$blogArticle->author_name?></a>
<?php } else { ?>
<?=$blogArticle->author_name?>
<?php } ?>
le <?php echo datefmt_format($user->datetime_format,date_create($blogArticle->creation_date, new DateTimeZone("UTC"))) ?></p>
<!-- Comments -->
<?php if ($isCommentable) { ?>
<!-- Comment form -->
<div id="new_comment">
<form class="form" action="<?=$config['rel_root_folder']?>blog/<?=$blogArticle->permalink?>/new_comment" method="post">
<div id="new_comment_label" <?=$isVisitor ? "class='sent' " : ""?>>
<?php if ($isArchiveOrPrivate) { ?>
<p>Impossible de commenter un article non publié</p>
<?php } else if ($canWriteComment) { ?>
<input name="submit" type="submit" value="Envoyer">
<p>Ajouter un nouveau commentaire</p>
<?php } else { ?>
<p>Veuillez vous connecter pour ajouter un commentaire</p>
<?php } ?>
</div>
<div id="new_comment_form">
<textarea id="comment" name="comment" rows="5" placeholder="Votre commentaire"></textarea>
</div>
</form>
</div>
<!-- Comment list -->
<?php foreach ($blogArticles_comments->objs as $comment) { ?>
<?php $canManageComment = $canModerate || $user->id == $comment->author; ?>
<article <?php if($comment->is_archive == 't' || $comment->is_public == 'f') echo 'class="comment_archive" '; ?>>
<div class="comment_title">
<?php if ($comment->author_obj->is_avatar_present=='t') { ?>
<img alt="Avatar" class="icon avatar" src="<?=$config['rel_root_folder']?>medias/avatars/<?=$comment->author_obj->id?>_s.jpg">
<?php } else { ?>
<i class="icon fas fa-user-secret"></i>
<?php } ?>
<?php if ($user->rankIsHigher("blocked")) { ?>
<a class="username" href="<?=$config['rel_root_folder']?>user/p/<?=$comment->author_obj->id?>"><?=$comment->author_obj->name?></a>
<?php } else { ?>
<?=$comment->author_obj->name?>
<?php } ?>
le <?php echo datefmt_format($user->datetime_format,date_create($comment->update_date, new DateTimeZone("UTC"))) ?>
<?php if ($canManageComment && $comment->is_public == 't') { ?>
<span class="delete_link"><a href="<?=$config['rel_root_folder']?>blog/<?=$blogArticle->permalink?>/delete_comment/<?=$comment->id?>"><i class="fas fa-trash"></i> Effacer le commentaire</a></span>
<?php } ?>
<?php if ($canManageComment && $comment->is_public == 'f') { ?>
<span class="delete_link"><a href="<?=$config['rel_root_folder']?>blog/<?=$blogArticle->permalink?>/restore_comment/<?=$comment->id?>"><i class="fas fa-eye"></i> Restaurer le commentaire</a></span>
<?php } ?>
</div>
<div class="comment_content">
<?=$comment->comment_html?>
</div>
</article>
<?php }
} ?>
<!-- Footer spacing -->
<br>
<br>
<div style="clear: both;"> </div>
</section>
<?php if ($canViewHistory) { ?>
<!-- History switch -->
<script type="text/javascript">
$( "#bloghistory" ).change(function() {
window.location.href = "<?=$config['rel_root_folder']?>blog/<?=$blogArticle->permalink?>/"+$( this ).val();
});
</script>
<?php } ?>
<?php if ($canOpenCommentForm) { ?>
<!-- Comment form toggle -->
<script type="text/javascript">
$( "#new_comment_label" ).click(function() {
$( "#new_comment_form" ).show(400);
$( "#new_comment_label input" ).show(0);
$( "#new_comment_label").addClass('sent');
});
</script>
<?php } ?>
<?php include('blocks/d.footer.html'); ?>
</body>
</html>

View File

@@ -1,32 +1,37 @@
<!DOCTYPE html> <!DOCTYPE html>
<!-- Page: community contributions -->
<html lang="fr"> <html lang="fr">
<? include('blocks/d.head.html'); ?> <?php include('blocks/d.head.html'); ?>
<body> <body>
<? include('blocks/d.nav.html'); ?> <?php include('blocks/d.nav.html'); ?>
<!-- Main content -->
<section> <section>
<h1>Contribuer au projet Kabano.</h1> <h1>Contribuer au projet Kabano</h1>
<p>&Eacute;tant un projet collaboratif, Kabano se repose sur vos contributions pour diffuser des informations au plus proche de la réalité. En participant au projet Kabano, vous acceptez de placer vos collaborations sous <a href="<?=$config['rel_root_folder']?>wiki/licences">nos licences libres</a>.</p> <p>&Eacute;tant un projet collaboratif, Kabano se repose sur vos contributions pour diffuser des informations au plus proche de la réalité. En participant au projet Kabano, vous acceptez de placer vos collaborations sous <a href="<?=$config['rel_root_folder']?>wiki/licences">nos licences libres</a>.</p>
<br> <br>
<!-- Contribution: add POI -->
<div class="action"> <div class="action">
<? if($user->rankIsHigher("registered")) { ?> <?php if($user->rankIsHigher("registered")) { ?>
<div class="title"><i class="fas fa-home"></i> <div class="title"><i class="fas fa-home"></i>
<a href="<?=$config['rel_root_folder']?>poi/new">Ajouter un hébergement de montagne</a> <a href="<?=$config['rel_root_folder']?>poi/new">Ajouter un hébergement de montagne</a>
</div> </div>
<? } else { ?> <?php } else { ?>
<!-- Login required -->
<div class="title" id="js_open_1"><i class="fas fa-home"></i> <div class="title" id="js_open_1"><i class="fas fa-home"></i>
<p>Ajouter un hébergement de montagne</p> <p>Ajouter un hébergement de montagne</p>
</div> </div>
<div class="description" id="js_openned_1"> <div class="description" id="js_openned_1">
<p>Vous devez être connecté pour pouvoir ajouter un hébergement. &Ccedil;a nous permet de laisser les robots à la porte.</p> <p>Vous devez être connecté pour pouvoir ajouter un hébergement. &Ccedil;a nous permet de laisser les robots à la porte.</p>
</div> </div>
<? } ?> <?php } ?>
</div> </div>
<!-- Contribution: comments -->
<div class="action"> <div class="action">
<div class="title" id="js_open_2"><i class="fas fa-comment"></i> <div class="title" id="js_open_2"><i class="fas fa-comment"></i>
<p>Ajouter un commentaire sur un hébergement</p> <p>Ajouter un commentaire sur un hébergement</p>
@@ -36,6 +41,7 @@
</div> </div>
</div> </div>
<!-- Contribution: maintenance -->
<div class="action"> <div class="action">
<div class="title" id="js_open_3"><i class="fas fa-wrench"></i> <div class="title" id="js_open_3"><i class="fas fa-wrench"></i>
<p>Faire une demande de travaux</p> <p>Faire une demande de travaux</p>
@@ -47,6 +53,7 @@
</section> </section>
<!-- Description toggles -->
<script type="text/javascript"> <script type="text/javascript">
$( "#js_open_1" ).click(function() { $( "#js_open_1" ).click(function() {
$( "#js_openned_1" ).show(400); $( "#js_openned_1" ).show(400);
@@ -59,7 +66,7 @@ $( "#js_open_3" ).click(function() {
}); });
</script> </script>
<? include('blocks/d.footer.html'); ?> <?php include('blocks/d.footer.html'); ?>
</body> </body>
</html> </html>

View File

@@ -1,58 +1,64 @@
<!DOCTYPE html> <!DOCTYPE html>
<!-- Page: contact -->
<html lang="fr"> <html lang="fr">
<? include('blocks/d.head.html'); ?> <?php include('blocks/d.head.html'); ?>
<body> <body>
<? include('blocks/d.nav.html'); ?> <?php include('blocks/d.nav.html'); ?>
<!-- Contact form -->
<section> <section>
<h1>Nous contacter.</h1> <h1>Me contacter</h1>
<form class="form" action="<?=$config['rel_root_folder']?>contact" method="post"> <form class="form" action="<?=$config['rel_root_folder']?>contact" method="post">
<? if($error=="name") { ?> <!-- Error messages -->
<?php if($error=="name") { ?>
<p style="color: red;">Veuillez renseigner votre nom.</p> <p style="color: red;">Veuillez renseigner votre nom.</p>
<? } ?> <?php } ?>
<? if($error=="subject") { ?> <?php if($error=="subject") { ?>
<p style="color: red;">Veuillez renseigner un sujet.</p> <p style="color: red;">Veuillez renseigner un sujet.</p>
<? } ?> <?php } ?>
<? if($error=="email") { ?> <?php if($error=="email") { ?>
<p style="color: red;">Veuillez renseigner une adresse mail.</p> <p style="color: red;">Veuillez renseigner une adresse mail.</p>
<? } ?> <?php } ?>
<? if($error=="message") { ?> <?php if($error=="message") { ?>
<p style="color: red;">Veuillez renseigner un message.</p> <p style="color: red;">Veuillez renseigner un message.</p>
<? } ?> <?php } ?>
<? if($error=="unknown") { ?> <?php if($error=="unknown") { ?>
<p style="color: red;">Une erreur est survenue.</p> <p style="color: red;">Une erreur est survenue.</p>
<? } ?> <?php } ?>
<? if($error=="spam") { ?> <?php if($error=="spam") { ?>
<p style="color: red;">Veuillez n'envoyer qu'un message et attendre la fin du compte à rebours.<br> <p style="color: red;">Veuillez n'envoyer qu'un message et attendre la fin du compte à rebours.<br>
Avez-vous javascript activé et attendu la fin du compte à rebours ?</p> Avez-vous javascript activé et attendu la fin du compte à rebours ?</p>
<? } ?> <?php } ?>
<? if($error=="none") { ?> <?php if($error=="none") { ?>
<p style="color: green;">Message bien envoyé.</p> <p style="color: green;">Message bien envoyé.</p>
<? } ?> <?php } ?>
<!-- Fields -->
<input type="text" name="name" id="name" placeholder="Nom" value="<?=$contact['name']?>"> <input type="text" name="name" id="name" placeholder="Nom" value="<?=$contact['name']?>">
<input type="text" name="email" id="email" placeholder="Adresse mail" value="<?=$contact['email']?>"> <input type="email" name="email" id="email" placeholder="Adresse mail" value="<?=$contact['email']?>">
<input type="text" name="subject" id="subject" placeholder="Sujet" value="<?=$contact['subject']?>"> <input type="text" name="subject" id="subject" placeholder="Sujet" value="<?=$contact['subject']?>">
<textarea name="message" id="message" rows="12" placeholder="Contenu de votre message"><?=$contact['message']?></textarea> <textarea name="message" id="message" rows="12" placeholder="Contenu de votre message"><?=$contact['message']?></textarea>
<? if($user->rankIsHigher("registered")) { ?> <!-- Anti-spam -->
<?php if($user->rankIsHigher("registered")) { ?>
<input type="hidden" name="captcha" value="-2"> <input type="hidden" name="captcha" value="-2">
<input type="submit" name="submit" value="Envoyer"> <input type="submit" name="submit" value="Envoyer">
<? } <?php }
else { ?> else { ?>
<!-- Required wait -->
<p id="captcha"> <p id="captcha">
<input type="hidden" id="captchahidden" name="captcha" value="10"> <input type="hidden" id="captchahidden" name="captcha" value="10">
<span id="captchatext">Merci d'attendre <b id="captchasec">10 s</b> avant de pouvoir nous contacter.<br> <span id="captchatext">Merci d'attendre <b id="captchasec">10 s</b> avant de pouvoir me contacter.<br>
<small>Ceci nous permet de laisser les robots à la porte.</small></span> <small>Ceci me permet de laisser les robots à la porte.</small></span>
<input disabled id="captchasubmit" style="display:none;" type="submit" name="submit" value="Envoyer"> <input disabled id="captchasubmit" style="display:none;" type="submit" name="submit" value="Envoyer">
</p> </p>
<? } ?> <?php } ?>
<input type="hidden" name="ns" value="<?=$contact['ns']?>"/> <input type="hidden" name="ns" value="<?=$contact['ns']?>"/>
</form> </form>
</section> </section>
<? include('blocks/d.footer.html'); ?> <?php include('blocks/d.footer.html'); ?>
</body> </body>
</html> </html>

47
public/views/d.index.html Executable file
View File

@@ -0,0 +1,47 @@
<!DOCTYPE html>
<!-- Page: homepage -->
<html lang="fr">
<?php include('blocks/d.head.html'); ?>
<body>
<?php include('blocks/d.nav.html'); ?>
<!-- Hero image -->
<aside id="indexFullW">
<div id="AScontent">
<div id="imglegend">
<p>Refuge de Pointe Basse</p>
</div>
</div>
</aside>
<!-- Load wiki content -->
<?php
require_once($config['models_folder']."d.wiki.php");
$wikiPage = new Kabano\WikiPage();
$wikiPage->checkPermalink('index');
$wikiPage->md2html();
?>
<!-- Main content -->
<section id="index">
<h1><?=$wikiPage->name?></h1>
<?php if($user->rankIsHigher('moderator')) { ?>
<!-- Edit shortcut -->
<span class="subtitle">
<a href="<?=$config['rel_root_folder']?>wiki/index/edit"><i class="fas fa-pencil-alt"></i> Éditer la page</a>
</span>
<?php } ?>
<br><br>
<?=$wikiPage->content_html?>
</section>
<?php include('blocks/d.footer.html'); ?>
</body>
</html>

44
public/views/d.map.html Executable file
View File

@@ -0,0 +1,44 @@
<!DOCTYPE html>
<!-- Page: map view -->
<html lang="fr">
<?php include('blocks/d.head.html'); ?>
<body>
<?php include('blocks/d.nav.html'); ?>
<!-- Map -->
<div id="mapid" style="height: 100%;"></div>
<!-- Credits panel -->
<div id="footer-credits" style="display: none;">
<i class="fa fa-times close-link" aria-hidden="true"></i>
<p><i id="map-credits"></i></p>
</div>
<!-- Legend panel -->
<div id="footer-legend" style="display: none;">
<i class="fa fa-times close-link" aria-hidden="true"></i>
<?php foreach($poi_types as $type) { ?>
<span class="legend_item"><img src="<?=$config['views_url']?>img/<?=$type[3]?>.svg" class="poi_icon"> <?=$type[1]?></span>
<?php } ?>
</div>
<?php include('blocks/d.footer.html'); ?>
<!-- Map configuration -->
<script>
var root = "<?=$config['rel_root_folder']?>";
// POI icons
window.poi_icons = {
<?php foreach($poi_types as $type) { ?>
"<?=$type[3]?>": "<?=$config['views_url']?>img/<?=$type[3]?>.svg",
<?php } ?>
"default": "<?=$config['views_url']?>img/default.svg"
};
</script>
</body>
</html>

256
public/views/d.poi.edit.html Executable file
View File

@@ -0,0 +1,256 @@
<!DOCTYPE html>
<!-- Page: point of interest editor -->
<html lang="fr">
<?php include('blocks/d.head.html'); ?>
<body>
<?php include('blocks/d.nav.html'); ?>
<!-- Map canvas -->
<div id="mapid"></div>
<!-- POI form panel -->
<div id="sticky">
<section>
<i id="slide-icon" class="fas fa-chevron-up"></i>
<?php if(isset($new) AND $new==1) { ?>
<!-- Create POI -->
<form class="form" action="<?=$config['rel_root_folder']?>poi/new" method="post">
<?php }
else { ?>
<!-- Update POI -->
<form class="form" action="<?=$config['rel_root_folder']?>poi/<?=$poi->permalink?>/edit" method="post">
<?php } ?>
<!-- Basic fields -->
<h1 class="flex_line">
<input type="text" value="<?=$poi->name?>" name="name" id="name" placeholder="Nom de l'hébergement" required>
<select name="locale" id="locale">
<?php foreach($locales->objs as $locale) { ?>
<option <?=$poi->locale==$locale->name?'selected':''?> value="<?=$locale->name?>"><?=$locale->display_name?></option>
<?php } ?>
</select>
</h1>
<!-- Location fields -->
<div class="flex_line">
<input type="number" class="noarrow" step="any" value="<?=$poi->lat?>" name="lat" id="lat" placeholder="Latitude" required>
<input type="number" class="noarrow" step="any" value="<?=$poi->lon?>" name="lon" id="lon" placeholder="Longitude" required>
<input type="number" class="noarrow last-child" step="any" value="<?=$poi->ele?>" name="ele" id="ele" placeholder="Altitude">
<div id="elevation_icon" style="display:none;" title="Calculer l'altitude"><i class="fas fa-search-location"></i></div>
</div>
<!-- Type selector -->
<div class="flex_line" id="type_selector">
<?php foreach($poi_types as $type) { ?>
<input type="radio" name="poi_type" value="<?=$type[3]?>" id="<?=$type[3]?>" required
<?=$poi->poi_type == $type[3] ? 'checked' : ''?>>
<label for="<?=$type[3]?>"><img src="<?=$config['views_url']?>img/<?=$type[3]?>.svg"><br><?=$type[0]?></label>
<?php } ?>
</div>
<!-- Dynamic form data -->
<script type="text/javascript">
<?php
$poi_params = $poi->parameters ?? new stdClass();
?>
var poi_params = <?= json_encode($poi_params) ?>;
var current_poi_type = "<?= $poi->poi_type ?>";
var unsaved = false;
// Stocke les abstracts et les squelettes de formulaire
<?php foreach($poi_types as $type) { ?>
window["<?=$type[3]?>_abstract"] = "<?=$type[4]?>";
window["<?=$type[3]?>_jsonform"] = <?=json_encode($type[5])?>;
<?php } ?>
// 3 états : 0 = non, 1 = intermédiaire, 2 = oui
function update3State(id) {
var input = $("input[name="+id+"]");
var label = $("label[for="+id+"]");
var v = parseInt(input.val(), 10);
// cycle propre : 0 → 1 → 2 → 0
if (v === 0) v = 1;
else if (v === 1) v = 2;
else v = 0;
input.val(v);
label.removeClass("uncheck intermediate check");
if (v === 0) label.addClass("uncheck");
if (v === 1) label.addClass("intermediate");
if (v === 2) label.addClass("check");
unsaved = true;
}
// Génère / met à jour le sous-formulaire selon le type
function updateForm(type) {
$("#abstract").html(window[type + '_abstract']);
var html_form = "";
var jsonform = window[type + '_jsonform'];
$.each(jsonform, function(index, value) {
var prefix = index.charAt(0);
var existing = (poi_params && typeof poi_params[index] !== 'undefined')
? poi_params[index]
: null;
switch (prefix) {
case 'b':
var cls = 'intermediate';
var val = 1;
if (existing == 0) {
cls = 'uncheck';
val = 0;
} else if (existing == 2) {
cls = 'check';
val = 2;
} else if (existing == -1 || existing === null) {
cls = 'intermediate';
val = 1;
}
html_form +=
'<label class="threecb ' + cls + '" for="' + index + '" onclick="update3State(\'' + index + '\')">' +
value +
'</label>' +
'<input value="' + val + '" type="hidden" name="' + index + '" id="' + index + '"><br>';
break;
case 'n':
html_form +=
'<div class="flex_line">' +
'<label for="' + index + '">' + value + '</label>' +
'<input min="0" type="number" name="' + index + '" id="' + index + '" ' +
(existing !== null ? 'value="' + existing + '"' : '') +
'>' +
'</div>';
break;
case 't':
html_form +=
'<label for="' + index + '">' + value + '</label>' +
'<textarea name="' + index + '" id="' + index + '">';
if (existing !== null) {
html_form += String(existing)
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;");
}
html_form += '</textarea>';
break;
case 'l':
html_form +=
'<div class="flex_line">' +
'<label for="' + index + '">' + value + '</label>' +
'<input placeholder="https://" type="url" name="' + index + '" id="' + index + '" ' +
(existing ? 'value="' + existing + '"' : '') +
'>' +
'</div>';
break;
default:
console.log("ERROR: " + index + "'s type is not known");
}
});
$("#specific_form").html(html_form);
unsaved = false;
$("#specific_form :input").change(function(){
unsaved = true;
});
}
$(document).ready(function(){
// Au chargement : générer le formulaire du type actuel
if (current_poi_type) {
updateForm(current_poi_type);
}
unsaved = !is_new;
$('#type_selector label').click(function(){
if (unsaved === true) {
if (!confirm("Des changements ont été apportés et vont être supprimés, voulez-vous continuer ?")) {
return false;
}
}
const type = $(this).attr("for"); // robuste
current_poi_type = type;
updateForm(type);
});
});
</script>
<!-- Type description -->
<p id="abstract"></p>
<!-- Dynamic fields -->
<div id="specific_form"></div>
<?php if(isset($new) AND $new==1) { ?>
<!-- Permalink -->
<div id="permalink_container">
<label id="permalink_label" for="permalink"><?=$config['web_root_folder']?>poi/</label>
<input type="text" name="permalink" id="permalink" placeholder="URL" required>
</div>
<?php } ?>
<!-- Permalink generation -->
<script type="text/javascript">
$( "#name" ).keyup(function() {
permalink = $( "#name" ).val();
permalink = permalink.replace(/ /g,'_');
permalink = permalink.toLowerCase();
permalink = permalink.replace(/[^a-z0-9_]/g,'-');
permalink = permalink.replace(/[_-]+$/g,'');
$( "#permalink" ).val(permalink);
});
$( "#name" ).change(function() {
permalink = $( "#name" ).val();
permalink = permalink.replace(/ /g,'_');
permalink = permalink.toLowerCase();
permalink = permalink.replace(/[^a-z0-9_]/g,'-');
permalink = permalink.replace(/[_-]+$/g,'');
$( "#permalink" ).val(permalink);
});
</script>
<!-- Form submission -->
<input name="submit" id="submit" type="submit" value="<?= isset($new) && $new == 1 ? "Ajouter l'hébergement" : "Mettre à jour l'hébergement" ?>">
</form>
</section>
<!-- Map variables -->
<script>
<?php if($poi->lat != null && $poi->lon != null) { ?>
var poi_lat = <?=$poi->lat?>;
var poi_lon = <?=$poi->lon?>;
<?php } ?>
var poi_type = "<?=$poi->poi_type?>";
var is_new = <?= isset($new) && $new == 1 ? "true" : "false" ?>;
var root = "<?=$config['rel_root_folder']?>";
</script>
<!-- Scroll helper -->
<script type="text/javascript">
$( "#slide-icon" ).click(function() {
$( "html, body" ).animate({scrollTop: "300px"});
});
</script>
<?php include('blocks/d.footer.html'); ?>
</div>
</body>
</html>

View File

@@ -0,0 +1,311 @@
<!DOCTYPE html>
<!-- Page: point of interest view -->
<html lang="fr">
<?php include('blocks/d.head.html'); ?>
<body>
<?php include('blocks/d.nav.html'); ?>
<?php
$isArchiveOrPrivate = $poi->is_archive == "t" || $poi->is_public == "f";
$canViewHistory = $user->rankIsHigher('premium');
$canModerate = $user->rankIsHigher('moderator');
$canWriteComment = $user->rankIsHigher("registered");
$canOpenCommentForm = $canWriteComment && !$isArchiveOrPrivate;
$hasHistory = isset($PoiHistory);
$isVisitor = $user->rank == "visitor";
$isCommentable = $poi->is_commentable == 't';
?>
<!-- Map canvas -->
<div id="mapid"></div>
<!-- POI details panel -->
<div id="sticky">
<section <?=$isArchiveOrPrivate ? 'class="archive"' : ''?>>
<i id="slide-icon" class="fas fa-chevron-up"></i>
<!-- POI header -->
<h1 class="flex_line">
<span class="poi-icon-wrapper" data-tooltip="<?=htmlspecialchars($poi_types[$poi->poi_type][4] ?? '')?>">
<img class="poi-icon"
src="<?=$config['rel_root_folder']?>views/img/<?=$poi->poi_type?>.svg"
alt="">
</span>
<span><?=$poi->name?></span>
</h1>
<!-- POI card -->
<div class="poi-idcard">
<div class="poi-id-main">
<div class="poi-id-coords">
<span class="poi-id-label">📍 Coordonnées</span>
<a href="geo:<?=$poi->lat?>,<?=$poi->lon?>" class="poi-id-value">
<?=$poi->lat?>, <?=$poi->lon?>
</a>
<?php if ($poi->ele !== null && $poi->ele !== '') { ?>
<span class="poi-id-elev">⛰️ <?=$poi->ele?> m</span>
<?php } ?>
</div>
<div class="poi-id-type">
<span class="poi-id-label">🏷️ Type</span>
<span class="poi-id-value">
<?=$poi_types[$poi->poi_type][1] ?? $poi->poi_type?>
</span>
</div>
</div>
<div class="poi-id-dates">
<span>Créé : <?=$poi->creation_date?></span>
<span>Mis à jour : <?=$poi->update_date?></span>
</div>
</div>
<?php if ($canViewHistory) { ?>
<!-- History and actions -->
<span class="subtitle">
<?php if ($hasHistory) { ?>
<select id="PoiHistory">
<?php $historyIndex = 0; ?>
<?php foreach ($PoiHistory->objs as $row) { ?>
<?php
$isSelected = $row->version_id == $poi->version_id ? 'selected' : '';
$isActive = $row->is_archive == "f" ? '&bull; ' : '';
$formattedDate = datefmt_format(
$user->datetimeshort_format,
date_create($row->update_date, new DateTimeZone("UTC"))
);
?>
<option <?=$isSelected?> value="<?=$historyIndex?>"><?=$isActive?><?=$formattedDate?></option>
<?php $historyIndex++; ?>
<?php } ?>
</select>
<?php }
if ($canModerate && $hasHistory) { ?>
&mdash;
<?php }
if ($canModerate) { ?>
<a href="<?=$config['rel_root_folder']?>poi/<?=$poi->permalink?>/edit"><i class="fas fa-pencil-alt"></i> Éditer le point</a> &mdash;
<?php if ($poi->is_public == 't') { ?>
<a href="<?=$config['rel_root_folder']?>poi/<?=$poi->permalink?>/delete"><i class="fas fa-trash"></i> Effacer le point</a>
<?php } else { ?>
<a href="<?=$config['rel_root_folder']?>poi/<?=$poi->permalink?>/restore"><i class="fas fa-eye"></i> Restaurer le point</a>
<?php } ?>
<?php } ?>
</span>
<?php } ?>
<br>
<br>
<?php
$poiFields = $poi_types[$poi->poi_type][5];
$poiValues = $poi->parameters ?? [];
// Séparer les booléens des autres champs
$boolFields = [];
$otherFields = [];
foreach ($poiFields as $key => $label) {
if ($key[0] === 'b') {
$boolFields[$key] = $label;
} else {
$otherFields[$key] = $label;
}
}
?>
<div id="specific_form" class="view-mode">
<!-- Detail fields -->
<?php foreach ($otherFields as $key => $label): ?>
<?php
$value = $poiValues[$key] ?? null;
$type = $key[0];
?>
<div class="field field-<?= $type ?>">
<label><?= $label ?></label>
<?php if ($type === 'n'): ?>
<span class="inline-value"><?= $value !== null ? $value : "<em>—</em>" ?></span>
<?php elseif ($type === 't'): ?>
<div class="field-value">
<?= $value ? nl2br(htmlspecialchars($value)) : "<em>Aucune information.</em>" ?>
</div>
<?php elseif ($type === 'l'): ?>
<span class="inline-value">
<?php if ($value): ?>
<a href="<?= htmlspecialchars($value) ?>" target="_blank"><?= $value ?></a>
<?php else: ?>
<em></em>
<?php endif; ?>
</span>
<?php endif; ?>
</div>
<?php endforeach; ?>
<!-- Boolean grid -->
<?php if (!empty($boolFields)): ?>
<?php
$boolIcons = [
0 => "<span class='boolean-pill boolean-no'>❌</span>",
1 => "<span class='boolean-pill boolean-maybe'>❓</span>",
2 => "<span class='boolean-pill boolean-yes'>✔️</span>",
-1 => "<span class='boolean-pill boolean-unknown'></span>"
];
?>
<div class="bool-grid">
<!-- Boolean labels -->
<div class="bool-row labels">
<?php foreach ($boolFields as $key => $label): ?>
<div class="bool-label"><?= $label ?></div>
<?php endforeach; ?>
</div>
<!-- Boolean values -->
<div class="bool-row values">
<?php foreach ($boolFields as $key => $label): ?>
<?php
$value = $poiValues[$key] ?? 2;
$icon = $boolIcons[$value];
?>
<div class="bool-cell">
<?= $icon ?>
</div>
<?php endforeach; ?>
</div>
</div>
<?php endif; ?>
</div>
<?php if ($isCommentable) { ?>
<!-- Comments -->
<div id="new_comment">
<form class="form" action="<?=$config['rel_root_folder']?>poi/<?=$poi->permalink?>/new_comment" method="post">
<div id="new_comment_label" <?=$isVisitor ? "class='sent' " : ""?>>
<?php if ($isArchiveOrPrivate) { ?>
<p>Impossible de commenter un point non publié</p>
<?php } else if ($canWriteComment) { ?>
<input name="submit" type="submit" value="Envoyer">
<p>Ajouter un nouveau commentaire</p>
<?php } else { ?>
<p>Veuillez vous connecter pour ajouter un commentaire</p>
<?php } ?>
</div>
<div id="new_comment_form">
<textarea id="comment" name="comment" rows="5" placeholder="Votre commentaire"></textarea>
</div>
</form>
</div>
<?php if (isset($poi_comments) && $poi_comments->number > 0) { ?>
<!-- Comment list -->
<div id="comments">
<?php foreach ($poi_comments->objs as $comment) { ?>
<?php $canManageComment = $canModerate || $user->id == $comment->author; ?>
<article <?php if($comment->is_archive == 't' || $comment->is_public == 'f') echo 'class="comment_archive" '; ?>>
<div class="comment_title">
<?php if ($comment->author_obj->is_avatar_present == 't') { ?>
<img alt="Avatar" class="icon avatar" src="<?=$config['rel_root_folder']?>medias/avatars/<?=$comment->author_obj->id?>_s.jpg">
<?php } else { ?>
<i class="icon fas fa-user-secret"></i>
<?php } ?>
<?php if ($user->rankIsHigher("blocked")) { ?>
<a class="username" href="<?=$config['rel_root_folder']?>user/p/<?=$comment->author_obj->id?>">
<?=$comment->author_obj->name?>
</a>
<?php } else { ?>
<?=$comment->author_obj->name?>
<?php } ?>
le <?php echo datefmt_format($user->datetime_format, date_create($comment->update_date, new DateTimeZone("UTC"))) ?>
<?php if ($canManageComment && $comment->is_public == 't') { ?>
<span class="delete_link">
<a href="<?=$config['rel_root_folder']?>poi/<?=$poi->permalink?>/delete_comment/<?=$comment->id?>">
<i class="fas fa-trash"></i> Effacer le commentaire
</a>
</span>
<?php } ?>
<?php if ($canManageComment && $comment->is_public == 'f') { ?>
<span class="delete_link">
<a href="<?=$config['rel_root_folder']?>poi/<?=$poi->permalink?>/restore_comment/<?=$comment->id?>">
<i class="fas fa-eye"></i> Restaurer le commentaire
</a>
</span>
<?php } ?>
</div>
<div class="comment_content">
<?=$comment->comment_html?>
</div>
</article>
<?php } ?>
<br></div>
<?php } else { ?>
<p>Aucun commentaire pour le moment.</p>
<?php } ?>
<?php } ?>
</section>
<?php include('blocks/d.footer.html'); ?>
</div>
<!-- Map variables -->
<script>
var poi_lat = <?=$poi->lat?>;
var poi_lon = <?=$poi->lon?>;
var poi_type = "<?=$poi->poi_type?>";
var poi_mode = "view";
var root = "<?=$config['rel_root_folder']?>";
</script>
<?php if ($canViewHistory) { ?>
<!-- History selector -->
<script type="text/javascript">
$( "#PoiHistory" ).change(function() {
window.location.href = "<?=$config['rel_root_folder']?>poi/<?=$poi->permalink?>/"+$( this ).val();
});
</script>
<?php } ?>
<?php if ($canOpenCommentForm) { ?>
<!-- Comment form toggle -->
<script type="text/javascript">
$( "#new_comment_label" ).click(function() {
$( "#new_comment_form" ).show(400);
$( "#new_comment_label input" ).show(0);
$( "#new_comment_label").addClass('sent');
});
</script>
<?php } ?>
<!-- Scroll helper -->
<script type="text/javascript">
$( "#slide-icon" ).click(function() {
$( "html, body" ).animate({scrollTop: "300px"});
});
</script>
</body>
</html>

View File

@@ -1,24 +1,27 @@
<!DOCTYPE html> <!DOCTYPE html>
<!-- Page: user login -->
<html lang="fr"> <html lang="fr">
<? include('blocks/d.head.html'); ?> <?php include('blocks/d.head.html'); ?>
<body> <body>
<? include('blocks/d.nav.html'); ?> <?php include('blocks/d.nav.html'); ?>
<section> <section>
<h1>Connexion.</h1> <h1>Connexion</h1>
<!-- Login form -->
<form class="form" action="<?=$config['rel_root_folder']?>user/login" method="post" id="login"> <form class="form" action="<?=$config['rel_root_folder']?>user/login" method="post" id="login">
<? if(isset($_GET['error']) AND $_GET['error']==1) { ?> <!-- Status messages -->
<?php if(isset($_GET['error']) AND $_GET['error']==1) { ?>
<p style="color: red;">Erreur lors de la connexion, merci de réessayer.</p> <p style="color: red;">Erreur lors de la connexion, merci de réessayer.</p>
<? } ?> <?php } ?>
<? if(isset($_GET['status']) AND $_GET['status']=="created") { ?> <?php if(isset($_GET['status']) AND $_GET['status']=="created") { ?>
<p style="color: #006600;">Votre compte a été créé, vous pouvez vous connecter.</p> <p style="color: #006600;">Votre compte a été créé, vous pouvez vous connecter.</p>
<? } ?> <?php } ?>
<? if(isset($_GET['status']) AND $_GET['status']=="password_sent") { ?> <?php if(isset($_GET['status']) AND $_GET['status']=="password_sent") { ?>
<p style="color: #006600;">Un nouveau mot de passe vous a été envoyé par mail.</p> <p style="color: #006600;">Un nouveau mot de passe vous a été envoyé par mail.</p>
<? } ?> <?php } ?>
<input type="text" name="login" id="login" placeholder="Nom d'utilisateur"> <input type="text" name="login" id="login" placeholder="Nom d'utilisateur">
<input type="password" name="password" id="password" placeholder="Mot de passe"> <input type="password" name="password" id="password" placeholder="Mot de passe">
<input type="submit" name="submit" value="Se connecter"> <input type="submit" name="submit" value="Se connecter">
@@ -28,7 +31,7 @@
</form> </form>
</section> </section>
<? include('blocks/d.footer.html'); ?> <?php include('blocks/d.footer.html'); ?>
</body> </body>
</html> </html>

View File

@@ -1,14 +1,16 @@
<!DOCTYPE html> <!DOCTYPE html>
<!-- Page: member list -->
<html lang="fr"> <html lang="fr">
<? include('blocks/d.head.html'); ?> <?php include('blocks/d.head.html'); ?>
<body> <body>
<? include('blocks/d.nav.html'); ?> <?php include('blocks/d.nav.html'); ?>
<!-- Member table -->
<section id="member_list"> <section id="member_list">
<h1>Liste des membres.</h1> <h1>Liste des membres</h1>
<p class="subtitle">Membres <?=$first?> à <?=$last?> sur les <?=$users->number?> inscrits</p> <p class="subtitle">Membres <?=$first?> à <?=$last?> sur les <?=$users->number?> inscrits</p>
<table> <table>
@@ -34,37 +36,37 @@
<?=$orderby=='website'?$order=='ASC'?'<i class="fas fa-caret-down" aria-hidden="true"></i>':'<i class="fas fa-caret-up" aria-hidden="true"></i>':''?> <?=$orderby=='website'?$order=='ASC'?'<i class="fas fa-caret-down" aria-hidden="true"></i>':'<i class="fas fa-caret-up" aria-hidden="true"></i>':''?>
</th> </th>
</tr> </tr>
<? foreach ($users->objs as $row) { ?> <?php foreach ($users->objs as $row) { ?>
<tr> <tr>
<td> <td>
<? if ($row->is_avatar_present=='t') { ?> <?php if ($row->is_avatar_present=='t') { ?>
<img alt="Avatar" class="icon avatar" src="<?=$config['rel_root_folder']?>medias/avatars/<?=$row->id?>_s.jpg"> <img alt="Avatar" class="icon avatar" src="<?=$config['rel_root_folder']?>medias/avatars/<?=$row->id?>_s.jpg">
<? } else { ?> <?php } else { ?>
<i class="icon fas fa-user-secret"></i> <i class="icon fas fa-user-secret"></i>
<? } ?> <?php } ?>
<a class="username" href="<?=$config['rel_root_folder']?>user/p/<?=$row->id?>"><?=$row->name?></a> <a class="username" href="<?=$config['rel_root_folder']?>user/p/<?=$row->id?>"><?=$row->name?></a>
</td> </td>
<td><?=$row->get_rank()?></td> <td><?=$row->get_rank()?></td>
<td><? echo strftime('%e %B %G',strtotime($row->register_date)) ?></td> <td><?php echo datefmt_format($user->date_format,date_create($row->register_date, new DateTimeZone("UTC"))) ?></td>
<td><? echo strftime('%e %B %G',strtotime($row->visit_date)) ?></td> <td><?php echo datefmt_format($user->date_format,date_create($row->visit_date, new DateTimeZone("UTC"))) ?></td>
<td> <td>
<? if ($row->website != "") { ?> <?php if ($row->website != "") { ?>
<a target="_blank" href="<?=$row->website?>">Site internet <span class="external-link"><i class="fas fa-external-link-alt"></i></span></a> <a target="_blank" href="<?=$row->website?>">Site internet <span class="external-link"><i class="fas fa-external-link-alt"></i></span></a>
<? } ?> <?php } ?>
</td> </td>
</tr> </tr>
<? } ?> <?php } ?>
</table> </table>
<div class="pagebuttons"> <div class="pagebuttons">
<? if ($page != 0) { ?><a class="previous" href="<?=$config['rel_root_folder']?>user/member_list/<?=$page?>?orderby=<?=$orderby?>&amp;order=<?=$order?>"><i class="fas fa-chevron-left fa-fw"></i></a><? } <?php if ($page != 0) { ?><a class="previous" href="<?=$config['rel_root_folder']?>user/member_list/<?=$page?>?orderby=<?=$orderby?>&amp;order=<?=$order?>"><i class="fas fa-chevron-left fa-fw"></i></a><?php }
if (($page+1)*$rows_per_pages < $users->number) { ?><a class="next" href="<?=$config['rel_root_folder']?>user/member_list/<?=$page+2?>?orderby=<?=$orderby?>&amp;order=<?=$order?>"><i class="fas fa-chevron-right fa-fw"></i></a><? } ?> if (($page+1)*$rows_per_pages < $users->number) { ?><a class="next" href="<?=$config['rel_root_folder']?>user/member_list/<?=$page+2?>?orderby=<?=$orderby?>&amp;order=<?=$order?>"><i class="fas fa-chevron-right fa-fw"></i></a><?php } ?>
</div> </div>
</section> </section>
<? include('blocks/d.footer.html'); ?> <?php include('blocks/d.footer.html'); ?>
</body> </body>
</html> </html>

View File

@@ -0,0 +1,26 @@
<!DOCTYPE html>
<!-- Page: password reset -->
<html lang="fr">
<?php include('blocks/d.head.html'); ?>
<body>
<?php include('blocks/d.nav.html'); ?>
<section>
<h1>Envoi d'un mot de passe</h1>
<!-- Reset form -->
<form class="form" action="<?=$config['rel_root_folder']?>user/password_lost" method="post" id="password_lodt">
<?php if(isset($_GET['error']) AND $_GET['error']==1) { ?>
<p style="color: red;">Cette adresse mail n'existe pas.</p>
<?php } ?>
<input type="email" name="email" id="email" placeholder="Adresse mail">
<input type="submit" name="submit" value="Envoyer un nouveau mot de passe">
</form>
</section>
<?php include('blocks/d.footer.html'); ?>
</body>
</html>

View File

@@ -1,25 +1,29 @@
<!DOCTYPE html> <!DOCTYPE html>
<!-- Page: profile editor -->
<html lang="fr"> <html lang="fr">
<? include('blocks/d.head.html'); ?> <?php include('blocks/d.head.html'); ?>
<body> <body>
<? include('blocks/d.nav.html'); ?> <?php include('blocks/d.nav.html'); ?>
<!-- Profile form -->
<section id="profile"> <section id="profile">
<? if ($userProfile->id != 0) { ?> <?php if ($userProfile->id != 0) { ?>
<h1><?=$userProfile->name?></h1> <h1><?=$userProfile->name?></h1>
<article> <article>
<? if(isset($nameError) AND $nameError==1) { ?> <!-- Status messages -->
<?php if(isset($nameError) AND $nameError==1) { ?>
<p style="color: #660000;">Veuillez choisir un autre nom d'utilisateur.</p> <p style="color: #660000;">Veuillez choisir un autre nom d'utilisateur.</p>
<? } ?> <?php } ?>
<? if(isset($emailError) AND $emailError==1) { ?> <?php if(isset($emailError) AND $emailError==1) { ?>
<p style="color: #660000;">Veuillez choisir un autre email.</p> <p style="color: #660000;">Veuillez choisir un autre email.</p>
<? } ?> <?php } ?>
<? if(isset($updated) AND $updated==1) { ?> <?php if(isset($updated) AND $updated==1) { ?>
<p style="color: #006600;">Le profil a été mis à jour.</p> <p style="color: #006600;">Le profil a été mis à jour.</p>
<? } ?> <?php } ?>
<!-- Profile fields -->
<form action="<?=$config['rel_root_folder']?>user/p/<?=$userProfile->id?>/edit" method="post" class="edituser" enctype="multipart/form-data"> <form action="<?=$config['rel_root_folder']?>user/p/<?=$userProfile->id?>/edit" method="post" class="edituser" enctype="multipart/form-data">
<aside class="<?=$userProfile->is_avatar_present=='t'?'':'no'?>avatar"> <aside class="<?=$userProfile->is_avatar_present=='t'?'':'no'?>avatar">
<div id="picturebuttonscontainer"> <div id="picturebuttonscontainer">
@@ -39,23 +43,30 @@
<div id="description"> <div id="description">
<ul> <ul>
<li><label for="name">Nom d'utilisateur :</label><input name="name" id="name" type="text" value="<?=$userProfile->name?>" placeholder="Charlie"></li> <li><label for="name">Nom d'utilisateur :</label><input name="name" id="name" type="text" value="<?=$userProfile->name?>" placeholder="Charlie"></li>
<li><label for="email">Adresse mail :</label><input name="email" id="email" type="text" value="<?=$userProfile->email?>" placeholder="charlie@mountain.org"></li> <li><label for="email">Adresse mail :</label><input name="email" id="email" type="email" value="<?=$userProfile->email?>" placeholder="charlie@mountain.org"></li>
<li><label for="password">Mot de passe :</label><input name="password" id="password" type="password" placeholder="Nouveau mot de passe"></li> <li><label for="password">Mot de passe :</label><input name="password" id="password" type="password" placeholder="Nouveau mot de passe"></li>
<li><label for="locale">Langue :</label> <li><label for="locale">Langue :</label>
<select name="locale" id="locale"> <select name="locale" id="locale">
<? foreach($locales->objs as $locale) { ?> <?php foreach($locales->objs as $locale) { ?>
<option <?=$userProfile->get_locale()==$locale->display_name?'selected':''?> value="<?=$locale->name?>"><?=$locale->display_name?></option> <option <?=$userProfile->get_locale()==$locale->display_name?'selected':''?> value="<?=$locale->name?>"><?=$locale->display_name?></option>
<? } ?> <?php } ?>
</select></li> </select></li>
<? if($user->rankIsHigher("administrator")) { ?> <li><label for="timezone">Fuseau horaire :</label>
<select name="timezone" id="timezone">
<?php $timezones = timezone_identifiers_list();
foreach($timezones as $timezone) { ?>
<option <?=$userProfile->timezone==$timezone?'selected':''?> value="<?=$timezone?>"><?=$timezone?></option>
<?php } ?>
</select></li>
<?php if($user->rankIsHigher("administrator")) { ?>
<li><label for="rank">Rang : </label> <li><label for="rank">Rang : </label>
<select name="rank" id="rank"> <select name="rank" id="rank">
<? foreach($ranks as $rank) { ?> <?php foreach($ranks as $rank) { ?>
<option <?=$userProfile->rank==$rank[3]?'selected':''?> value="<?=$rank[3]?>"><?=$rank[1]?></option> <option <?=$userProfile->rank==$rank[3]?'selected':''?> value="<?=$rank[3]?>"><?=$rank[1]?></option>
<? } ?> <?php } ?>
</select></li> </select></li>
<? } ?> <?php } ?>
<li><label for="website">Site internet :</label><input name="website" id="website" type="text" value="<?=$userProfile->website?>" placeholder="mountain.org"></li> <li><label for="website">Site internet :</label><input name="website" id="website" type="url" value="<?=$userProfile->website?>" placeholder="https://mountain.org"></li>
<input name="submit" id="submit" type="submit" value="Envoyer"> <input name="submit" id="submit" type="submit" value="Envoyer">
</ul> </ul>
@@ -63,12 +74,12 @@
<div style="clear:both;"></div> <div style="clear:both;"></div>
</form> </form>
</article> </article>
<? } else { ?> <?php } else { ?>
<p style="color:red;">Le profil demandé n'existe pas.</p> <p style="color:red;">Le profil demandé n'existe pas.</p>
<? } ?> <?php } ?>
</section> </section>
<? include('blocks/d.footer.html'); ?> <?php include('blocks/d.footer.html'); ?>
</body> </body>
</html> </html>

View File

@@ -1,66 +1,70 @@
<!DOCTYPE html> <!DOCTYPE html>
<!-- Page: user profile -->
<html lang="fr"> <html lang="fr">
<? include('blocks/d.head.html'); ?> <?php include('blocks/d.head.html'); ?>
<body> <body>
<? include('blocks/d.nav.html'); ?> <?php include('blocks/d.nav.html'); ?>
<section id="profile"> <section id="profile">
<? if ($userProfile->id != 0) { ?> <?php if ($userProfile->id != 0) { ?>
<!-- Profile header -->
<h1><?=$userProfile->name?></h1> <h1><?=$userProfile->name?></h1>
<? if($user->rankIsHigher("moderator") || $user->id == $userProfile->id) { ?> <?php if($user->rankIsHigher("moderator") || $user->id == $userProfile->id) { ?>
<a class="subtitle" id="editprofile" href="<?=$config['rel_root_folder']?>user/p/<?=$userProfile->id?>/edit"><i class="fas fa-pencil-alt"></i> Éditer les paramètres du compte</a> <a class="subtitle" id="editprofile" href="<?=$config['rel_root_folder']?>user/p/<?=$userProfile->id?>/edit"><i class="fas fa-pencil-alt"></i> Éditer les paramètres du compte</a>
<? } ?> <?php } ?>
<article> <article>
<!-- Profile info -->
<div id="profilepart"> <div id="profilepart">
<? if(isset($mailsent) AND $mailsent==1) { ?> <?php if(isset($mailsent) AND $mailsent==1) { ?>
<p style="color: #006600;">Le message a bien été envoyé.</p> <p style="color: #006600;">Le message a bien été envoyé.</p>
<? } ?> <?php } ?>
<aside class="<?=$userProfile->is_avatar_present=='t'?'':'no'?>avatar"> <aside class="<?=$userProfile->is_avatar_present=='t'?'':'no'?>avatar">
<img alt="Avatar" id="profileavatar" src="<?=$config['rel_root_folder']?>medias/avatars/<?=$userProfile->id?>_p.jpg" alt="Profile picture"> <img alt="Avatar" id="profileavatar" src="<?=$config['rel_root_folder']?>medias/avatars/<?=$userProfile->id?>_p.jpg" alt="Profile picture">
<i id="profilenoavatar" class="fas fa-user-secret"></i> <i id="profilenoavatar" class="fas fa-user-secret"></i>
</aside> </aside>
<div id="description"> <div id="description">
<p>Langue : <?=$userProfile->get_locale()?></p> <p>Langue : <?=$userProfile->get_locale()?></p>
<p>Inscrit le <? echo strftime('%e %B %G, %kh%Mm%Ss',strtotime($userProfile->register_date)) ?> <small><abbr title="Temps Universel Coordonné">UTC</abbr></small></p> <p>Inscrit le <?php echo datefmt_format($user->datetime_format,date_create($userProfile->register_date, new DateTimeZone("UTC"))) ?></p>
<p>Dernière connexion le <? echo strftime('%e %B %G, %kh%Mm%Ss',strtotime($userProfile->visit_date)) ?> <small><abbr title="Temps Universel Coordonné">UTC</abbr></small></p> <p>Dernière connexion le <?php echo datefmt_format($user->datetime_format,date_create($userProfile->visit_date, new DateTimeZone("UTC"))) ?></p>
<p><?=$userProfile->get_rank()?></p> <p><?=$userProfile->get_rank()?></p>
<p> <p>
<? if ($userProfile->website != "") { ?> <?php if ($userProfile->website != "") { ?>
<a target="_blank" href="<?=$userProfile->website?>">Site internet <span class="external-link"><i class="fas fa-external-link-alt"></i></span></a> <a target="_blank" href="<?=$userProfile->website?>">Site internet <span class="external-link"><i class="fas fa-external-link-alt"></i></span></a>
<? } <?php }
if ($userProfile->website != "" AND $userProfile->id != $user->id) { ?> if ($userProfile->website != "" AND $userProfile->id != $user->id) { ?>
&mdash; &mdash;
<? } <?php }
if ($userProfile->id != $user->id) { ?> if ($userProfile->id != $user->id) { ?>
<a href="#" onclick="$('#profilepart').hide(0, function(){$('#contact').show('fast');});">Contacter par mail</a> <a href="#" onclick="$('#profilepart').hide(0, function(){$('#contact').show('fast');});">Contacter par mail</a>
<? } <?php }
if ($user->rankIsHigher("premium") AND ($userProfile->website != "" OR $userProfile->id != $user->id)) { ?> if ($user->rankIsHigher("premium") AND ($userProfile->website != "" OR $userProfile->id != $user->id)) { ?>
&mdash; &mdash;
<? } <?php }
if ($user->rankIsHigher("premium")) { ?> if ($user->rankIsHigher("premium")) { ?>
<a href="mailto:<?=$userProfile->email?>"><?=$userProfile->email?></a> <a href="mailto:<?=$userProfile->email?>"><?=$userProfile->email?></a>
<? } ?> <?php } ?>
</p> </p>
</div> </div>
<div style="clear:both;"></div> <div style="clear:both;"></div>
</div> </div>
<? if ($userProfile->id != $user->id) { ?> <?php if ($userProfile->id != $user->id) { ?>
<!-- Contact form -->
<form style="display:none;" class="form" id="contact" action="<?=$config['rel_root_folder']?>user/p/<?=$userProfile->id?>" method="post" > <form style="display:none;" class="form" id="contact" action="<?=$config['rel_root_folder']?>user/p/<?=$userProfile->id?>" method="post" >
<textarea rows="12" name="message" id="message" placeholder="Votre message"></textarea> <textarea rows="12" name="message" id="message" placeholder="Votre message"></textarea>
<p><i>Votre adresse email sera transmise à votre destinataire.</i></p> <p><i>Votre adresse email sera transmise à votre destinataire.</i></p>
<input type="submit" name="submit" value="Envoyer"> <input type="submit" name="submit" value="Envoyer">
</form> </form>
<? } ?> <?php } ?>
</article> </article>
<? } else { ?> <?php } else { ?>
<p style="color:red;">Le profil demandé n'existe pas.</p> <p style="color:red;">Le profil demandé n'existe pas.</p>
<? } ?> <?php } ?>
</section> </section>
<? include('blocks/d.footer.html'); ?> <?php include('blocks/d.footer.html'); ?>
</body> </body>
</html> </html>

View File

@@ -1,31 +1,34 @@
<!DOCTYPE html> <!DOCTYPE html>
<!-- Page: user signin -->
<html lang="fr"> <html lang="fr">
<? include('blocks/d.head.html'); ?> <?php include('blocks/d.head.html'); ?>
<body> <body>
<? include('blocks/d.nav.html'); ?> <?php include('blocks/d.nav.html'); ?>
<section> <section>
<h1>Inscription.</h1> <h1>Inscription</h1>
<!-- Signup form -->
<form class="form" action="<?=$config['rel_root_folder']?>user/signin" method="post" id="signin"> <form class="form" action="<?=$config['rel_root_folder']?>user/signin" method="post" id="signin">
<? if(isset($_GET['error']) AND $_GET['error']=="name") { ?> <!-- Status messages -->
<?php if(isset($_GET['error']) AND $_GET['error']=="name") { ?>
<p style="color: red;">Veuillez choisir un autre nom d'utilisateur.</p> <p style="color: red;">Veuillez choisir un autre nom d'utilisateur.</p>
<? } ?> <?php } ?>
<? if(isset($_GET['error']) AND $_GET['error']=="email") { ?> <?php if(isset($_GET['error']) AND $_GET['error']=="email") { ?>
<p style="color: red;">Cette adresse mail est déjà prise.</p> <p style="color: red;">Cette adresse mail est déjà prise.</p>
<? } ?> <?php } ?>
<? if(isset($_GET['error']) AND $_GET['error']=="empty") { ?> <?php if(isset($_GET['error']) AND $_GET['error']=="empty") { ?>
<p style="color: red;">Merci de remplir tous les champs, il n'y en a que trois.</p> <p style="color: red;">Merci de remplir tous les champs, il n'y en a que trois.</p>
<? } ?> <?php } ?>
<? if(isset($_GET['error']) AND $_GET['error']=="captcha") { ?> <?php if(isset($_GET['error']) AND $_GET['error']=="captcha") { ?>
<p style="color: red;">Nous n'avons pas pu vérifier que vous êtes un humain.<br> <p style="color: red;">Nous n'avons pas pu vérifier que vous êtes un humain.<br>
Avez-vous javascript activé et attendu la fin du compte à rebours ?</p> Avez-vous javascript activé et attendu la fin du compte à rebours ?</p>
<? } ?> <?php } ?>
<input type="text" name="login" id="login" placeholder="Nom d'utilisateur"> <input type="text" name="login" id="login" placeholder="Nom d'utilisateur">
<input type="password" name="password" id="password" placeholder="Mot de passe"> <input type="password" name="password" id="password" placeholder="Mot de passe">
<input type="text" name="email" id="email" placeholder="Adresse mail"> <input type="email" name="email" id="email" placeholder="Adresse mail">
<p id="captcha"> <p id="captcha">
<input type="hidden" id="captchahidden" name="captcha" value="10"> <input type="hidden" id="captchahidden" name="captcha" value="10">
<span id="captchatext">Merci d'attendre <b id="captchasec">10 s</b> avant de pouvoir vous inscrire.<br> <span id="captchatext">Merci d'attendre <b id="captchasec">10 s</b> avant de pouvoir vous inscrire.<br>
@@ -35,7 +38,7 @@
</form> </form>
</section> </section>
<? include('blocks/d.footer.html'); ?> <?php include('blocks/d.footer.html'); ?>
</body> </body>
</html> </html>

View File

@@ -1,19 +1,21 @@
<!DOCTYPE html> <!DOCTYPE html>
<!-- Page: wiki editor -->
<html lang="fr"> <html lang="fr">
<? include('blocks/d.head.html'); ?> <?php include('blocks/d.head.html'); ?>
<body> <body>
<? include('blocks/d.nav.html'); ?> <?php include('blocks/d.nav.html'); ?>
<!-- Wiki form -->
<section> <section>
<form class="form" action="<?=$config['rel_root_folder']?>wiki/<?=$wikiPage->permalink?>/edit" method="post"> <form class="form" action="<?=$config['rel_root_folder']?>wiki/<?=$wikiPage->permalink?>/edit" method="post">
<h1> <h1>
<select name="locale" id="locale"> <select name="locale" id="locale">
<? foreach($locales->objs as $locale) { ?> <?php foreach($locales->objs as $locale) { ?>
<option <?=$wikiPage->locale==$locale->name?'selected':''?> value="<?=$locale->name?>"><?=$locale->display_name?></option> <option <?=$wikiPage->locale==$locale->name?'selected':''?> value="<?=$locale->name?>"><?=$locale->display_name?></option>
<? } ?> <?php } ?>
</select> </select>
<input type="text" value="<?=$wikiPage->name?>" name="name" id="name" placeholder="Titre"> <input type="text" value="<?=$wikiPage->name?>" name="name" id="name" placeholder="Titre">
</h1> </h1>
@@ -24,7 +26,7 @@
</form> </form>
</section> </section>
<? include('blocks/d.footer.html'); ?> <?php include('blocks/d.footer.html'); ?>
</body> </body>
</html> </html>

78
public/views/d.wiki.view.html Executable file
View File

@@ -0,0 +1,78 @@
<!DOCTYPE html>
<!-- Page: wiki view -->
<html lang="fr">
<?php include('blocks/d.head.html'); ?>
<body>
<?php include('blocks/d.nav.html'); ?>
<?php
$isArchiveOrPrivate = $wikiPage->is_archive == "t" || $wikiPage->is_public == "f";
$canViewHistory = $user->rankIsHigher('premium');
$canModerate = $user->rankIsHigher('moderator');
$hasHistory = isset($wikiHistory);
?>
<!-- Wiki content -->
<section id="wiki_page" <?=$isArchiveOrPrivate ? 'class="archive"' : ''?>>
<h1><?=$wikiPage->name?></h1>
<?php if ($canViewHistory) { ?>
<!-- History and actions -->
<span class="subtitle">
<?php if ($hasHistory) { ?>
<select id="wikihistory">
<?php $historyIndex = 0; ?>
<?php foreach ($wikiHistory->objs as $row) { ?>
<?php
$isSelected = $row->version_id == $wikiPage->version_id ? 'selected' : '';
$isActive = $row->is_archive == "f" ? '&bull; ' : '';
$formattedDate = datefmt_format(
$user->datetimeshort_format,
date_create($row->update_date, new DateTimeZone("UTC"))
);
?>
<option <?=$isSelected?> value="<?=$historyIndex?>"><?=$isActive?><?=$formattedDate?></option>
<?php $historyIndex++; ?>
<?php } ?>
</select>
<?php }
if ($canModerate && $hasHistory) { ?>
&mdash;
<?php }
if ($canModerate) { ?>
<a href="<?=$config['rel_root_folder']?>wiki/<?=$wikiPage->permalink?>/edit"><i class="fas fa-pencil-alt"></i> Éditer la page</a> &mdash;
<?php if ($wikiPage->is_public=="t") { ?>
<a href="<?=$config['rel_root_folder']?>wiki/<?=$wikiPage->permalink?>/delete"><i class="fas fa-trash"></i> Effacer la page</a>
<?php } else { ?>
<a href="<?=$config['rel_root_folder']?>wiki/<?=$wikiPage->permalink?>/restore"><i class="fas fa-eye"></i> Restaurer la page</a>
<?php }?>
<?php } ?>
</span>
<?php } ?>
<!-- Page body -->
<div id="wikiContent">
<?=$wikiPage->content_html?>
</div>
<!-- Timestamp -->
<p id="wikiTimestamp">Page mise à jour le <?php echo datefmt_format($user->datetime_format,date_create($wikiPage->update_date, new DateTimeZone("UTC"))) ?></p>
<div style="clear: both;"> </div>
</section>
<?php if ($canViewHistory) { ?>
<!-- History selector -->
<script type="text/javascript">
$( "#wikihistory" ).change(function() {
window.location.href = "<?=$config['rel_root_folder']?>wiki/<?=$wikiPage->permalink?>/"+$( this ).val();
});
</script>
<?php } ?>
<?php include('blocks/d.footer.html'); ?>
</body>
</html>

View File

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

BIN
public/views/img/aside.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

View File

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

Before

Width:  |  Height:  |  Size: 356 B

After

Width:  |  Height:  |  Size: 356 B

View File

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

View File

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

View File

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@@ -1,4 +1,5 @@
// Gestion de l'upload et suppression d'avatar côté client.
$(window).ready(function() { $(window).ready(function() {
$("#deleteavatar").click(function() { $("#deleteavatar").click(function() {
$("aside").removeClass("avatar").addClass("noavatar"); $("aside").removeClass("avatar").addClass("noavatar");
@@ -27,6 +28,7 @@ $(window).ready(function() {
}); });
// Prévisualisation du fichier image dans le profil.
function readURL(input) { function readURL(input) {
if (input.files && input.files[0]) { if (input.files && input.files[0]) {
var reader = new FileReader(); var reader = new FileReader();
@@ -37,4 +39,4 @@ function readURL(input) {
reader.readAsDataURL(input.files[0]); reader.readAsDataURL(input.files[0]);
} }
}$ }

View File

@@ -1,5 +1,7 @@
// Compte à rebours du captcha.
var time = 9; var time = 9;
// Active le bouton lorsque le délai est écoulé.
$(window).ready(function() { $(window).ready(function() {
var interval = setInterval(function() { var interval = setInterval(function() {
if (time > 0) { if (time > 0) {
@@ -19,4 +21,3 @@ $(window).ready(function() {
} }
}, 1000); }, 1000);
}); });

View File

@@ -1,6 +1,8 @@
// Gestion des animations du header en scroll.
var small = 2; var small = 2;
function reduce() { function reduce() {
// Réduit la hauteur du header.
$( "header" ).animate({ $( "header" ).animate({
height: "45px" height: "45px"
}, 100, function() { }, 100, function() {
@@ -21,15 +23,22 @@ function reduce() {
}, 100, function() { }, 100, function() {
// Animation complete. // Animation complete.
}); });
$( "header a.on-bar" ).animate({ $( "header li:not(.with-subtitle) a.on-bar" ).animate({
paddingTop: "15px", paddingTop: "15px",
paddingBottom: "5px" paddingBottom: "5px"
}, 100, function() { }, 100, function() {
// Animation complete. // Animation complete.
}); });
$( "header li.with-subtitle a.on-bar" ).animate({
paddingTop: "5px",
paddingBottom: "15px"
}, 100, function() {
// Animation complete.
});
} }
function enlarge() { function enlarge() {
// Restaure la taille du header.
$( "header" ).animate({ $( "header" ).animate({
height: "65px" height: "65px"
}, 100, function() { }, 100, function() {
@@ -50,26 +59,34 @@ function enlarge() {
}, 100, function() { }, 100, function() {
// Animation complete. // Animation complete.
}); });
$( "header a.on-bar" ).animate({ $( "header li:not(.with-subtitle) a.on-bar" ).animate({
paddingTop: "25px", paddingTop: "25px",
paddingBottom: "15px" paddingBottom: "15px"
}, 100, function() { }, 100, function() {
// Animation complete. // Animation complete.
}); });
$( "header li.with-subtitle a.on-bar" ).animate({
paddingTop: "15px",
paddingBottom: "25px"
}, 100, function() {
// Animation complete.
});
} }
// Déclenche les animations selon le scroll.
$(window).scroll(function() { $(window).scroll(function() {
var position = $(window).scrollTop(); var position = $(window).scrollTop();
if (position>80 && small!=1) { if (position>80 && small!=1 && $('body').width() > 800) {
small = 1; small = 1;
reduce(); reduce();
} }
else if (position<=80 && small!=0) { else if (position<=80 && small!=0 && $('body').width() > 800) {
small = 0; small = 0;
enlarge(); enlarge();
} }
}); });
// Affichage du texte du logo au survol.
$(window).ready(function() { $(window).ready(function() {
$( "#logo" ).hover( $( "#logo" ).hover(
function() { function() {
@@ -78,4 +95,4 @@ $(window).ready(function() {
$("#kabanologotext").hide(100); $("#kabanologotext").hide(100);
} }
) )
}); });

131
public/views/js/d.map.js Executable file
View File

@@ -0,0 +1,131 @@
// Carte principale et marqueurs de POI.
var mymap;
var markers = [];
$( document ).ready(function() {
// Différentes couches pour la carte.
var topo_maptiler = L.tileLayer('https://api.maptiler.com/maps/topographique/{z}/{x}/{y}.png?key=Sm8M7mJ53GtYdl773rpi', {tms: false, attribution: 'Carte © <a href="https://www.maptiler.com/copyright/" target="_blank">MapTiler</a>, Données © <a href="http://www.openstreetmap.org/copyright" target="_blank">Contributeurs OpenStreetMap</a>', tileSize: 512, zoomOffset: -1, minZoom: 1});
var ign = L.tileLayer('https://data.geopf.fr/private/wmts?&REQUEST=GetTile&SERVICE=WMTS&VERSION=1.0.0&STYLE=normal&TILEMATRIXSET=PM&FORMAT=image/jpeg&LAYER=GEOGRAPHICALGRIDSYSTEMS.MAPS&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&apikey=ign_scan_ws', {attribution: 'Carte & Connées © <a href="http://ign.fr/" target="_blank">IGN-F/Géoportail</a>'});
// Couches de base.
var baseLayers = {
"OpenStreetMap": topo_maptiler,
"IGN France": ign
};
mymap = L.map('mapid', {
zoomControl: false,
layers: [topo_maptiler]
}).setView([47, 3], 6);
$("#map-credits").html(topo_maptiler.getAttribution());
L.control.scale({
position: "bottomleft",
imperial: false
}).addTo(mymap);
var credits = L.easyButton('fa-info',
function(control, mymap){
$("footer").hide();
$("#footer-credits").show();
$("#footer-legend").hide();
}, 'Credits');
var legend = L.easyButton('fa-question',
function(control, mymap){
$("footer").hide();
$("#footer-credits").hide();
$("#footer-legend").show();
}, 'Legend');
L.easyBar([ credits, legend, ], {position: "bottomleft"}).addTo(mymap);
L.control.fullscreen({
position: "bottomleft"
}).addTo(mymap);
L.control.zoom({
zoomOutText: "<i class=\"fa fa-minus\" aria-hidden=\"true\"></i>",
zoomInText: "<i class=\"fa fa-plus\" aria-hidden=\"true\"></i>",
position: "bottomleft"
}).addTo(mymap);
L.control.layers(baseLayers,null,{
position: "bottomright"
}).addTo(mymap);
mymap.removeControl(mymap.attributionControl);
$(".close-link").click(function() {
$("footer").show();
$("#footer-credits").hide();
$("#footer-legend").hide();
});
mymap.on('baselayerchange', function(e) {
$("#map-credits").html(e.layer.getAttribution());
});
// Ajuste la taille des icônes selon le niveau de zoom.
mymap.on("zoomend", function () {
var z = mymap.getZoom();
var size = 32;
if (z < 8) size = 20;
if (z < 4) size = 12;
markers.forEach(function(marker) {
var icon = marker.options.icon;
icon.options.iconSize = [size, size];
icon.options.iconAnchor = [size/2, size];
marker.setIcon(icon);
});
});
// ---------------------------------------------------------
// CHARGEMENT DES POIs
// ---------------------------------------------------------
$.getJSON(root + "poi/api_list", function(pois) {
var icons = {};
// Préparer les icônes
for (const type in window.poi_icons) {
icons[type] = L.icon({
iconUrl: window.poi_icons[type],
iconSize: [32, 32],
iconAnchor: [16, 32],
popupAnchor: [0, -32]
});
}
// Ajouter les POIs
pois.forEach(function(poi) {
var icon = icons[poi.type] || icons["default"];
var marker = L.marker([poi.lat, poi.lon], { icon: icon })
.addTo(mymap);
// Tooltip discret au survol
marker.bindTooltip(poi.name, {
direction: "top",
offset: [0, -10],
opacity: 0.9,
className: "poi-tooltip"
});
// Clic → ouvrir la fiche directement
marker.on("click", function() {
window.location = root + "poi/" + poi.permalink;
});
markers.push(marker);
});
// Ajuster la vue
if (markers.length > 0) {
var group = L.featureGroup(markers);
mymap.fitBounds(group.getBounds(), { padding: [30, 30] });
}
});
});

136
public/views/js/d.poi_map.js Executable file
View File

@@ -0,0 +1,136 @@
// Carte des POIs et marqueur principal.
var mymap;
var poi_layer;
$(document).ready(function() {
// Mode : edit (formulaire) ou view (affichage)
var isEdit = (typeof poi_mode === "undefined" || poi_mode === "edit");
// Différentes couches pour la carte.
var topo_maptiler = L.tileLayer(
'https://api.maptiler.com/maps/topographique/{z}/{x}/{y}.png?key=Sm8M7mJ53GtYdl773rpi',
{
tms: false,
attribution: 'Carte © <a href="https://www.maptiler.com/copyright/" target="_blank">MapTiler</a>, Données © <a href="http://www.openstreetmap.org/copyright" target="_blank">Contributeurs OpenStreetMap</a>',
tileSize: 512,
zoomOffset: -1,
minZoom: 1
}
);
var ign = L.tileLayer(
'https://data.geopf.fr/private/wmts?&REQUEST=GetTile&SERVICE=WMTS&VERSION=1.0.0&STYLE=normal&TILEMATRIXSET=PM&FORMAT=image/jpeg&LAYER=GEOGRAPHICALGRIDSYSTEMS.MAPS&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&apikey=ign_scan_ws',
{
attribution: 'Carte & Connées © <a href="http://ign.fr/" target="_blank">IGN-F/Géoportail</a>'
}
);
// Couches de base.
var baseLayers = {
"OpenStreetMap": topo_maptiler,
"IGN France": ign
};
mymap = L.map('mapid', {
zoomControl: false,
layers: [topo_maptiler]
}).setView([47, 3], 6);
$("#map-credits").html(topo_maptiler.getAttribution());
L.control.scale({
position: "bottomleft",
imperial: false
}).addTo(mymap);
L.control.fullscreen({
position: "bottomleft"
}).addTo(mymap);
L.control.zoom({
zoomOutText: "<i class=\"fa fa-minus\" aria-hidden=\"true\"></i>",
zoomInText: "<i class=\"fa fa-plus\" aria-hidden=\"true\"></i>",
position: "bottomleft"
}).addTo(mymap);
L.control.layers(baseLayers, null, {
position: "bottomright"
}).addTo(mymap);
mymap.removeControl(mymap.attributionControl);
mymap.on('baselayerchange', function(e) {
$("#map-credits").html(e.layer.getAttribution());
});
// Position initiale : soit celle du POI, soit le centre par défaut
var startLat = (typeof poi_lat !== "undefined" && poi_lat) ? poi_lat : 47;
var startLon = (typeof poi_lon !== "undefined" && poi_lon) ? poi_lon : 3;
// Icône : si poi_type défini, on lutilise, sinon icône Leaflet par défaut
var poiicon = null;
if (typeof poi_type !== "undefined" && poi_type) {
poiicon = L.icon({
iconSize: [24, 24],
iconAnchor: [12, 12],
iconUrl: root + "views/img/" + poi_type + ".svg"
});
}
if (poiicon) {
poi_layer = L.marker([startLat, startLon], {draggable: isEdit, icon: poiicon}).addTo(mymap);
} else {
poi_layer = L.marker([startLat, startLon], {draggable: isEdit}).addTo(mymap);
}
if (isEdit) {
// Mise à jour des coordonnées à chaque déplacement.
poi_layer.bindTooltip("Glissez moi au bon endroit.", {permanent: true, direction: 'auto'}).openTooltip();
}
// Interactions uniquement en mode édition
if (isEdit) {
mymap.on('click', function(e){
poi_layer.setLatLng(e.latlng);
});
poi_layer.on('move', function(e){
poi_layer.unbindTooltip();
$("#lat").val(+e.latlng.lat.toFixed(6));
$("#lon").val(+e.latlng.lng.toFixed(6));
$("#elevation_icon").show();
});
// Si l'utilisateur modifie les champs lat/lon manuellement.
$("#lat,#lon").change(function() { // If the user changes the lat/lon input values manualy
if(isNaN($("#lat").val()) || isNaN($("#lon").val()) || $("#lat").val().length==0 || $("#lon").val()==null)
$("#elevation_icon").hide();
else {
$("#elevation_icon").show();
poi_layer.setLatLng([$("#lat").val(),$("#lon").val()]);
}
});
var editPoiIcon = L.icon({
iconSize: [24, 24],
iconAnchor: [12, 12]
});
$("#type_selector label").click(function(e) {
poi_layer.unbindTooltip();
editPoiIcon.options.iconUrl = e.currentTarget.firstChild.currentSrc;
poi_layer.setIcon(editPoiIcon);
});
// Chargement de l'altitude via le proxy.
$("#elevation_icon").click(function(e) {
$(this).find($(".fas")).removeClass('fa-search-location').addClass('fa-spinner').addClass('fa-spin');
$.get(root+"poi/elevation_proxy", {location:$("#lat").val()+","+$("#lon").val()}, function(result){
$("#ele").val(result.results[0].elevation);
$("#elevation_icon").find($(".fas")).removeClass('fa-spinner').removeClass('fa-spin').addClass('fa-search-location');
});
});
} else {
// Mode affichage : centrer sur le POI si coordonnées présentes
if (typeof poi_lat !== "undefined" && typeof poi_lon !== "undefined") {
mymap.setView([poi_lat, poi_lon], 14);
}
}
});

View File

Before

Width:  |  Height:  |  Size: 673 KiB

After

Width:  |  Height:  |  Size: 673 KiB

View File

Before

Width:  |  Height:  |  Size: 139 KiB

After

Width:  |  Height:  |  Size: 139 KiB

View File

Before

Width:  |  Height:  |  Size: 708 KiB

After

Width:  |  Height:  |  Size: 708 KiB

Some files were not shown because too many files have changed in this diff Show More