From 0866cd93181f24d2529830d21c4ed8a9e5cffa4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment?= Date: Fri, 12 Jul 2024 10:19:56 +0200 Subject: [PATCH 1/8] add django-jinja-markdown extension --- content/pages/a_page.md | 17 +++++++++++++++++ jssg/jinja2.py | 3 ++- jssg/settings.py | 4 +++- requirements.txt | 1 + 4 files changed, 23 insertions(+), 2 deletions(-) diff --git a/content/pages/a_page.md b/content/pages/a_page.md index 19c7922..221750c 100644 --- a/content/pages/a_page.md +++ b/content/pages/a_page.md @@ -8,8 +8,25 @@ template_engine jinja2 } --- +{% from "widgets/page_header.html" import page_header %} +

Page 1

Go to page 2

+
+{% markdown %} +``` +This is markdown. +``` +{% endmarkdown %} +
+ + +{{ page_header(markdown(' +test +#test +####test + +')) }} \ No newline at end of file diff --git a/jssg/jinja2.py b/jssg/jinja2.py index 5bea8bb..e91e1d5 100644 --- a/jssg/jinja2.py +++ b/jssg/jinja2.py @@ -1,6 +1,6 @@ from django.templatetags.static import static from django.urls import reverse - +from django_jinja_markdown.templatetags.md import markdown from jinja2 import Environment from jssg.templatetags.filter_opengraph_metadata import filter_opengraph_metadata @@ -14,6 +14,7 @@ def environment(**options): { "static": static, "url": reverse, + "markdown": markdown } ) env.filters.update( diff --git a/jssg/settings.py b/jssg/settings.py index 830599b..32822be 100644 --- a/jssg/settings.py +++ b/jssg/settings.py @@ -58,6 +58,7 @@ # Application definition INSTALLED_APPS = [ + "django_jinja_markdown", "django.contrib.contenttypes", "whitenoise.runserver_nostatic", "django.contrib.staticfiles", @@ -80,7 +81,8 @@ "DIRS": [path / "jinja2" for path in JFME_TEMPLATES_DIRS], "APP_DIRS": True, "OPTIONS": { - "environment": "jssg.jinja2.environment" + "environment": "jssg.jinja2.environment", + "extensions": ["django_jinja_markdown.extensions.MarkdownExtension"] }, }, { diff --git a/requirements.txt b/requirements.txt index c196e9e..dc05782 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,3 +4,4 @@ django_vite_plugin==3.0.0 markdown2[all]==2.4.13 whitenoise==6.7.0 Jinja2==3.1.4 +django_jinja_markdown.extensions.MarkdownExtension \ No newline at end of file From 434aea2bba771e33a7ac9cd79cbf7f0380e4f429 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment?= Date: Mon, 15 Jul 2024 09:53:41 +0200 Subject: [PATCH 2/8] add dependency in requirement.txt --- content/pages/a_page.md | 11 ++++++----- requirements.txt | 4 ++-- tsconfig.json | 25 ++++++++++++++++++++++++- 3 files changed, 32 insertions(+), 8 deletions(-) diff --git a/content/pages/a_page.md b/content/pages/a_page.md index 221750c..941bbd4 100644 --- a/content/pages/a_page.md +++ b/content/pages/a_page.md @@ -24,9 +24,10 @@ This is markdown. -{{ page_header(markdown(' +{{ page_header( + markdown(' test -#test -####test - -')) }} \ No newline at end of file +**test** +`test` + ') +) }} \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index dc05782..ec36189 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ -Django==5.0.6 +Django==4.2.9 django-distill django_vite_plugin==3.0.0 markdown2[all]==2.4.13 whitenoise==6.7.0 Jinja2==3.1.4 -django_jinja_markdown.extensions.MarkdownExtension \ No newline at end of file +django-jinja-markdown \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 984c649..40307d7 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -19,7 +19,30 @@ "strict": true, "noUnusedLocals": true, "noUnusedParameters": true, - "noFallthroughCasesInSwitch": true + "noFallthroughCasesInSwitch": true, + "paths": { + "@/*": [ + "./*" + ], + "@s:django_jinja_markdown/*": [ + "./env/lib/python3.9/site-packages/django_jinja_markdown/static/django_jinja_markdown/*" + ], + "@t:django_jinja_markdown/*": [ + "./env/lib/python3.9/site-packages/django_jinja_markdown/templates/django_jinja_markdown/*" + ], + "@s:django_distill/*": [ + "./env/lib/python3.9/site-packages/django_distill/static/django_distill/*" + ], + "@t:django_distill/*": [ + "./env/lib/python3.9/site-packages/django_distill/templates/django_distill/*" + ], + "@s:jssg/*": [ + "./jssg/static/jssg/*" + ], + "@t:jssg/*": [ + "./jssg/templates/jssg/*" + ] + } }, "include": [ "content/front/" From e84e64aefc2c3cf447465af04ec208cf24f41b9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment?= Date: Mon, 15 Jul 2024 10:04:30 +0200 Subject: [PATCH 3/8] fix syntax error --- jssg/jinja2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jssg/jinja2.py b/jssg/jinja2.py index 1747661..8c87f1b 100644 --- a/jssg/jinja2.py +++ b/jssg/jinja2.py @@ -91,7 +91,7 @@ def environment(**options): { "static": static, "url": reverse, - "markdown": markdown + "markdown": markdown, "url_for_slug": url_for_slug, "url_for_slug_path" : url_for_slug_path } From 94146f817beef738153bfccfec60d20b31a85c2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment?= Date: Tue, 16 Jul 2024 15:37:16 +0200 Subject: [PATCH 4/8] first implementation of blog categories --- content/posts/19700101_hello.md | 6 ++- content/posts/post1.md | 68 ++++++++++++++++++++++++ content/posts/post2.md | 10 ++++ content/posts/post3.md | 10 ++++ content/templates/jinja2/allwidgets.html | 2 +- content/templates/jinja2/base.html | 4 +- content/templates/jinja2/post-list.html | 18 +++++++ jssg/models.py | 31 +++++++++++ jssg/urls.py | 18 ++++++- jssg/views.py | 13 ++++- tsconfig.json | 19 ++++++- 11 files changed, 190 insertions(+), 9 deletions(-) create mode 100644 content/posts/post1.md create mode 100644 content/posts/post2.md create mode 100644 content/posts/post3.md create mode 100644 content/templates/jinja2/post-list.html diff --git a/content/posts/19700101_hello.md b/content/posts/19700101_hello.md index ec8ec82..acdfc36 100644 --- a/content/posts/19700101_hello.md +++ b/content/posts/19700101_hello.md @@ -1,6 +1,10 @@ --- title Hello, world date 1970-01-01T00:00+00:00 +category test --- +{ -My first post! +} +--- +Hello world \ No newline at end of file diff --git a/content/posts/post1.md b/content/posts/post1.md new file mode 100644 index 0000000..c358eb1 --- /dev/null +++ b/content/posts/post1.md @@ -0,0 +1,68 @@ +--- +title R&D et Veille techno - Petit point sur nos projets internes +date 1970-02-01T00:00+00:00 +category Technologie +abstract Un petit tour d'horizon des projets sur lesquels nos équipes techniques travaillent actuellement ... + +--- +{ + +} +--- +L'été est là, le rythme ralentit, c'est l'occasion de parler un peu R&D + +Petit tour d'horizon des projets sur lesquels nous travaillons actuellement : + +## Tracim + +La version 4.10 est sortie début juillet et intègre un paramétrage plus fin des notifications web. C'est la première étape vers une stratégie de notifications optimisée pour être mieux informé tout en étant moins sollicité. Une vidéo de présentation de cette nouvelle version va arriver courant juillet. + +## Galae + +Une grosse mise à jour a été faite dans la stack technique, la mise en prod arrive début août. On progresse également sur la gestion des migrations depuis les outils Microsoft pour récupérer carnets d'adresses, agendas, etc (qui ne sont pas accessibles via les classiques CardDAV, CalDAV, sinon je n'en parlerais pas ;) + +## JSSG & JFME + +Clément nous a rejoint le temps d'un stage pour travailler avec Damien sur la future version statique de l'ensemble de nos sites web. + +On s'appuie sur le projet libre JSSG qu'on a amicalement forké et qui est en train de devenir JFME (JSSG For Meerkats Engine) et qui permet de gérer/générer des sites statiques avec une stratégie de construction de pages par blocs et factorisation des designs. + +## Whatelse ? + +Les 2 outils principaux (hors usines logicielles) qu'on utilise en interne sont Dolibarr et Tracim. Une partie de périmètre fonctionnel n'est adressé ni par l'un, ni par l'autre. Du coup on développe un outil interne qui permet d'implémenter toutes les fonctionnalités manquantes : tableaux de bord, préparation de fichiers bancaires, préparation de documents pour les déclarations de TVA, etc. + +Lorenzo et Damien travaillent à l'implémentation de nouvelles fonctionnalités + +## Connecteur Dolibarr en Python + +On utilise dolibarr en interne et on s'y interconnecte via plusieurs applicatifs python. On va probablement transformer le code client de l'API en un module qu'on publiera sur pypi. + +## Superset pour construire des tableaux de bord visuel + +On teste et expérimente l'utilisation de [superset](https://superset.apache.org/), un outil de la fondation Apache, pour construire des tableaux de bord graphiques. + +## Grist pour gérer des données et les enrichir par formulaire + +On teste et expériment [grist](https://www.getgrist.com/) pour la gestion de données structurées et la création de formulaires associés. + +## Suritech, l'événement veilletechno alpin libriste + +La R&D et veilletechno sont des activitées fondamentales pour perdurer. + +On a d'ailleurs organisé l'événement hashtag#suritech semaine dernière qui a été un franc succès 🎉 On réfléchit à la manière d'en faire la prochaine itération. + +On publiera l'enregistrement des conférences durant l'été. + +## Recrutement d'une ingénieure ou d'un ingénieur fullstack + +Après moultes rebondissements, on réfléchit à recruter une ingénieure ou un ingénieur fullstack geek & dynamique sur Grenoble pour contribuer à notre projet d'entreprise et nos produits tracim et galae. + +Si cela vous intéresse, envoyez-nous votre candidature (CV + quelques lignes qui expliquent pourquoi on devrait miser sur vous / pourquoi cela vous intéresse) + +~~~~ + +On ne s'arrête pas pendant l'été mais on réduit drastiquement notre présence en ligne. + +Passez toutes et tous de bonnes vacances 🌅 + +Rendez-vous début septembre pour de nouvelles aventures libres et souveraines ! 🚀 diff --git a/content/posts/post2.md b/content/posts/post2.md new file mode 100644 index 0000000..44e2120 --- /dev/null +++ b/content/posts/post2.md @@ -0,0 +1,10 @@ +--- +title post2 +date 1970-02-02T00:00+00:00 +category tech +--- +{ + +} +--- +My second post! diff --git a/content/posts/post3.md b/content/posts/post3.md new file mode 100644 index 0000000..f05888e --- /dev/null +++ b/content/posts/post3.md @@ -0,0 +1,10 @@ +--- +title post3 +date 1970-02-02T01:00+00:00 +category libre +--- +{ + +} +--- +My third post! diff --git a/content/templates/jinja2/allwidgets.html b/content/templates/jinja2/allwidgets.html index dcc18fc..166ffd4 100644 --- a/content/templates/jinja2/allwidgets.html +++ b/content/templates/jinja2/allwidgets.html @@ -19,7 +19,7 @@ diff --git a/content/templates/jinja2/base.html b/content/templates/jinja2/base.html index 412eb63..36fc4cc 100644 --- a/content/templates/jinja2/base.html +++ b/content/templates/jinja2/base.html @@ -3,7 +3,7 @@ - + @@ -13,7 +13,7 @@ {% for key, value in object.metadata.items()|filter_opengraph_metadata %} {% endfor %} - {{ object.title }} + {{ object.title|default("") }} diff --git a/content/templates/jinja2/post-list.html b/content/templates/jinja2/post-list.html new file mode 100644 index 0000000..e0a1620 --- /dev/null +++ b/content/templates/jinja2/post-list.html @@ -0,0 +1,18 @@ +{% extends "base.html" %} +{% block content %} + +
+ +
+ +{% for post in object.posts %} + {{ post.timestamp.strftime("%d/%m/%Y") }} : {{ post.title }} : {{ post.metadata.abstract }}
+{% endfor %} + +{% endblock %} \ No newline at end of file diff --git a/jssg/models.py b/jssg/models.py index e8e5b15..67ddd50 100644 --- a/jssg/models.py +++ b/jssg/models.py @@ -293,3 +293,34 @@ class Sitemap : domain = settings.JFME_DOMAIN pages_slugs = [p["slug"] for p in Page.get_pages()] posts_slugs = [p["slug"] for p in Post.get_posts()] + +class PostList : + metadata = {} + category = "" + + def __init__(self, category = "") -> None: + self.category = category + + @classmethod + def load_post_list_with_category(cls, category) : + return cls(category) + + @property + def categories(self) : + cat = set() + for post in Post.load_glob(all = True) : + cat.add(post.metadata["category"]) + return list(cat) + + @classmethod + def get_categories(cls) : + return [{"category": category} for category in cls().categories] + + @property + def posts(self) : + posts = sorted(Post.load_glob(), key=lambda p: p.timestamp, reverse=True) + if self.category == "" : + return posts + else : + return filter(lambda p: p.metadata["category"] == self.category, posts) + \ No newline at end of file diff --git a/jssg/urls.py b/jssg/urls.py index 513dc1a..a90da9f 100644 --- a/jssg/urls.py +++ b/jssg/urls.py @@ -15,17 +15,17 @@ from django_distill import distill_path, distill_re_path from jssg import views -from jssg.models import Page, Post +from jssg.models import Page, Post, PostList from jssg import settings # print([p for p in Page.get_pages()]) +# print([p for p in PostList.get_categories()]) urlpatterns = [ distill_path( "", views.IndexView.as_view(), name="index", distill_file="index.html" ), - distill_path("atom.xml", views.PostFeedsView(), name="atom_feed"), distill_re_path( r'^(?!posts/)(?P[a-zA-Z0-9-]+).html$', views.PageView.as_view(), @@ -38,7 +38,20 @@ name="page", distill_func=Page.get_pages, ), + distill_path("atom.xml", views.PostFeedsView(), name="atom_feed"), + distill_path( + "posts/", + views.PostListView.as_view(), + name = "post-index", + distill_file = "posts/index.html" + ), + distill_path( + "posts/category/.html", + views.PostListView.as_view(), + name = "post-category", + distill_func = PostList.get_categories + ), distill_path( "posts/.html", views.PostView.as_view(), @@ -51,6 +64,7 @@ name="post", distill_func=Post.get_posts, ), + distill_path( "sitemap.xml", views.SitemapView.as_view(), diff --git a/jssg/views.py b/jssg/views.py index 2aa9004..86e0766 100644 --- a/jssg/views.py +++ b/jssg/views.py @@ -22,7 +22,7 @@ from django.utils.feedgenerator import Atom1Feed from django.views.generic import DetailView -from jssg.models import Page, Post, Sitemap +from jssg.models import Page, Post, Sitemap, PostList class PostFeedsView(Feed): @@ -78,4 +78,13 @@ class SitemapView(DetailView) : template_name = "sitemap.html" def get_object(self, queryset=None) -> Model: - return self.model() \ No newline at end of file + return self.model() + +class PostListView(DetailView): + template_name = "post-list.html" + + def get_object(self, queryset=None) -> Model: + if "category" not in self.kwargs.keys() : + self.kwargs["category"] = "" + print(self.kwargs["category"]) + return PostList.load_post_list_with_category(self.kwargs["category"]) \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 984c649..2abd10b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -19,7 +19,24 @@ "strict": true, "noUnusedLocals": true, "noUnusedParameters": true, - "noFallthroughCasesInSwitch": true + "noFallthroughCasesInSwitch": true, + "paths": { + "@/*": [ + "./*" + ], + "@s:jssg/*": [ + "./jssg/static/jssg/*" + ], + "@t:jssg/*": [ + "./jssg/templates/jssg/*" + ], + "@s:django_distill/*": [ + "./env/lib/python3.9/site-packages/django_distill/static/django_distill/*" + ], + "@t:django_distill/*": [ + "./env/lib/python3.9/site-packages/django_distill/templates/django_distill/*" + ] + } }, "include": [ "content/front/" From b211d39fbeec963ac165c0c310da520ad6ef752d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment?= Date: Tue, 16 Jul 2024 16:16:25 +0200 Subject: [PATCH 5/8] add algoo.fr posts as examples --- content/posts/19700101_hello.md | 1 + content/posts/post1.md | 5 ++- content/posts/post2.md | 39 ++++++++++++++++++--- content/posts/post3.md | 55 +++++++++++++++++++++++++++--- content/templates/jinja2/post.html | 2 +- jssg/models.py | 1 + 6 files changed, 93 insertions(+), 10 deletions(-) diff --git a/content/posts/19700101_hello.md b/content/posts/19700101_hello.md index acdfc36..658eadc 100644 --- a/content/posts/19700101_hello.md +++ b/content/posts/19700101_hello.md @@ -2,6 +2,7 @@ title Hello, world date 1970-01-01T00:00+00:00 category test +abstract --- { diff --git a/content/posts/post1.md b/content/posts/post1.md index c358eb1..96c6635 100644 --- a/content/posts/post1.md +++ b/content/posts/post1.md @@ -1,6 +1,6 @@ --- title R&D et Veille techno - Petit point sur nos projets internes -date 1970-02-01T00:00+00:00 +date 2024-07-11T08:33:06+00:00 category Technologie abstract Un petit tour d'horizon des projets sur lesquels nos équipes techniques travaillent actuellement ... @@ -9,6 +9,8 @@ abstract Un petit tour d'horizon des projets sur lesquels nos équipes technique } --- + +{%markdown%} L'été est là, le rythme ralentit, c'est l'occasion de parler un peu R&D Petit tour d'horizon des projets sur lesquels nous travaillons actuellement : @@ -66,3 +68,4 @@ On ne s'arrête pas pendant l'été mais on réduit drastiquement notre présenc Passez toutes et tous de bonnes vacances 🌅 Rendez-vous début septembre pour de nouvelles aventures libres et souveraines ! 🚀 +{%endmarkdown%} \ No newline at end of file diff --git a/content/posts/post2.md b/content/posts/post2.md index 44e2120..8e9b54c 100644 --- a/content/posts/post2.md +++ b/content/posts/post2.md @@ -1,10 +1,41 @@ --- -title post2 -date 1970-02-02T00:00+00:00 -category tech +title Microsoft deviendrait-il un spyware avec la fonctionnalité Recall ? +date 2024-05-22T12:36:09+00:00 +category Technologie +abstract Le 20 mai 2024, Microsoft annonce la fonctionnalité Recall qui va "aider les utilisateurs à trouver leurs informations" en s'appuyant sur l'IA ... --- { } --- -My second post! +{% markdown %} +Le 20 mai dernier, Microsoft a annoncé sa nouvelle fonctionnalité #recall, basée sur l'#IA . Son objectif ? Vous aider à retrouver tout ce que vous avez déjà fait sur votre ordinateur. 🤗 Le moyen ? Enregistrer toute votre activité sur votre machine 😳 + +Tout ce que je tape au clavier ⌨ ? Oui, comme un Spyware 😨 + +Mais pas seulement ! 😰 + +Contrairement à ce qu'on imagine, il ne s'agit pas simplement d'enregistrer les frappes au clavier : il est également question de capturer *en permanence* ce qui est affiché à l'écran. Bien sûr, aucune donnée ne sortira de la machine et n'ira sur les serveurs Microsoft. Ouf. De toute façon, les données sont chiffrées et l'histoire est là pour vous rassurer : les clés de chiffrement ne fuitent jamais. 🔐 + +---- + +Ce que Wikipedia nous dit d'un spyware : un logiciel espion, un mouchard ou un espiogiciel (de l'anglais spyware) est un logiciel malveillant qui s'installe dans un ordinateur ou autre appareil mobile, dans le but de collecter et transférer des informations sur l'environnement dans lequel il s'est installé, très souvent sans que l'utilisateur en ait connaissance. L'essor de ce type de logiciel est associé à celui d'Internet qui lui sert de moyen de transmission de données. + +Je note un point important : *sans que l'utilisateur en ait connaissance*. + +France TV Info a publié un article sur l'annonce de la fonctionnalité Recall ; vous trouverez le lien ci-dessous. Maintenant que vous êtes au courant il ne s'agit plus d'un #spyware puisque vous êtes informé(e)s 🎁 + +---- + +Si vous préférez ne pas être confronté à ce genre de problématique, utilisez des logiciels libres et souverains comme ceux qu'on déploie, exploite et développe à #algoo : + +- 🐧 des poste de travail exploitant une distribution linux renommée telle que Debian, Ubuntu ou Zorin, +- 🏠 des outils auto-hébergés tels que Gitlab, mailtrain, dolibarr, etc, +- 💡 une plateforme de collaboration #tracim déployée en Saas en France sans exploitation des données ou déployée on premise, sur votre infrastructure y compris (et ça fonctionne même sans aucune connexion internet contrairement à d'autres) +- 📨 un service e-mail #galae exclusivement basé sur des logiciels libres et auto-hébergeable, conforme aux standards +- ... + +Bref des données dont vous maîtrisez l'hebergement, la localisation ... et l'existence. + +Vos données sont VOS données comme dirait l'autre. +{% endmarkdown %} diff --git a/content/posts/post3.md b/content/posts/post3.md index f05888e..12f5ae8 100644 --- a/content/posts/post3.md +++ b/content/posts/post3.md @@ -1,10 +1,57 @@ --- -title post3 -date 1970-02-02T01:00+00:00 -category libre +title Venez échanger sur les sujets de collaboration d'équipe et e-mail aux JDLL 2024 ! +date 2024-05-20T16:20:03+00:00 +category Univers du libre +abstract Algoo sera présente et très active aux JDLL 2024 : stand, ateliers et conférence ! --- { } --- -My third post! +{%markdown%} +Les 25 et 26 mai 2024 se tiennent les traditionnelles JDLL. Changement de lieu : ça se déroule toujours à Lyon, mais cette année ce sera [sur le site Descartes de l'ENS Lyon](https://jdll.org/contact-and-informations). + +## Le stand animé par les suricates Algoo + +Comme chaque année, nous serons présents, pour échanger, discuter, démontrer et animer autour de nos 2 thématiques principales : + +### 👉 Collaboration d'équipe en mode projet + +Venez découvrir la puissance de notre [logiciel Tracim, pensé pour la collaboration en mode projet et la collaboration asynchrone](https://www.tracim.fr) + + +Nous pourrons vous montrer ses fonctionnalités, mais aussi sa philosophie qui assure le meilleur embarquement des collaobrateurs. + +### 👉 Messagerie e-mail libre, éthique, collaborative + +Venez découvrir la flexibilité et la puissance de notre [service e-mail galae](https://www.galae.net) à travers les briques qu'il intègrent et une philosophie unique : vous laisser la main sur le paramétrage fin de votre messagerie email. + + +## Nos conférences et ateliers + +Comme chaque année nous participons activement à l'événement. Nous avons proposé une série de conférences et ateliers, tous ont été retenus ! \o/ + +### 🛠️ Comment collaborer efficacement en mode projet avec Tracim - Samedi 25 mai à 13h (atelier) + + +Damien animera l'atelier « [Découvrez comment collaborer efficacement en mode projet avec Tracim](https://pretalx.jdll.org/jdll2024/talk/CJPDZZ/) » + +### 🛠️ Dotez votre association d'un outil de collaboration auto-hébergée facile à maintenir. - Samedi 25 mai à 15h (atelier) + +Philippe animera l'atelier « [Dotez votre association d'un outil de collaboration auto-hébergée facile à maintenir.](https://pretalx.jdll.org/jdll2024/talk/MPGBWT/) » + +### 🎤 From zero to Galae : vivez de l'intérieur le lancement de la plateforme e-mail galae - Dimanche 26 mai à 16h (conférence) + +Sarah, Philippe et Damien vous relaterons l'aventure (et les mésaventures) du lancement du service e-mail Galae durant la conférence « [From zero to Galae : vivez de l'intérieur le lancement de la plateforme e-mail galae.](https://pretalx.jdll.org/jdll2024/talk/UCQJDZ/) » + +## Bonne ambiance, convivialité + +Comme d'habitude, cet événement est l'occasion d'échanger, discuter, boire un café ou une bière ... et de venir chiper sur notre stand les classiques stickers #suricate et désormais également les stickers galae :) + +Mais l'intérêt de venir aux JDLL est aussi (et surtout) de profiter de l'ensemble des conférences et stands ... + +Retrouvez ci-dessous le lien vers le planning complet des conférences et la liste exhaustive des stands et découvertes que vous pourrez faire durant les Journées Du Logiciel Libre ! + + +À très vite pour se rencontrer en chair et en os ! +{%endmarkdown%} \ No newline at end of file diff --git a/content/templates/jinja2/post.html b/content/templates/jinja2/post.html index 804119a..3204026 100644 --- a/content/templates/jinja2/post.html +++ b/content/templates/jinja2/post.html @@ -1,7 +1,7 @@ {% extends "base.html" %} {% block content %} -Publié le {{ object.timestamp.strftime("%Y-%m-%d") }}. +Publié le {{ object.timestamp.strftime("%d/%m/%Y") }} à {{ object.timestamp.strftime("%Hh%M") }}.

{{ object.title }}

{{ object.content|safe }} diff --git a/jssg/models.py b/jssg/models.py index 67ddd50..6859e6b 100644 --- a/jssg/models.py +++ b/jssg/models.py @@ -276,6 +276,7 @@ def __init__(self, content: str, **metadata) -> None: """ super().__init__(content, **metadata) self.timestamp = datetime.datetime.fromisoformat(metadata["date"]) + self.metadata["category"] = slugify(self.metadata["category"]) @classmethod def load_glob( From 2bccd0a0297ff4fd1580e4e927a91ceb31c8cd61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment?= Date: Tue, 16 Jul 2024 17:06:41 +0200 Subject: [PATCH 6/8] allow to not specify category metadata --- jssg/models.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/jssg/models.py b/jssg/models.py index 6859e6b..1115a35 100644 --- a/jssg/models.py +++ b/jssg/models.py @@ -276,7 +276,10 @@ def __init__(self, content: str, **metadata) -> None: """ super().__init__(content, **metadata) self.timestamp = datetime.datetime.fromisoformat(metadata["date"]) - self.metadata["category"] = slugify(self.metadata["category"]) + if "category" in self.metadata : + self.metadata["category"] = slugify(self.metadata["category"]) + else : + self.metadata["category"] = "" @classmethod def load_glob( @@ -310,8 +313,9 @@ def load_post_list_with_category(cls, category) : def categories(self) : cat = set() for post in Post.load_glob(all = True) : - cat.add(post.metadata["category"]) - return list(cat) + if post.metadata["category"] != "" : + cat.add(post.metadata["category"]) + return cat @classmethod def get_categories(cls) : From f7ca30e0df1c532a66a1659e59d45b9cb868c18c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment?= Date: Wed, 17 Jul 2024 10:12:11 +0200 Subject: [PATCH 7/8] beautify the post list page --- content/posts/19700101_hello.md | 1 + content/posts/post1.md | 2 +- content/posts/post2.md | 1 + content/posts/post3.md | 1 + content/templates/jinja2/post-list.html | 49 +++++++++++++++++++++++-- content/templates/jinja2/post.html | 1 + jssg/models.py | 2 +- tsconfig.json | 6 +++ 8 files changed, 58 insertions(+), 5 deletions(-) diff --git a/content/posts/19700101_hello.md b/content/posts/19700101_hello.md index 658eadc..66ed934 100644 --- a/content/posts/19700101_hello.md +++ b/content/posts/19700101_hello.md @@ -3,6 +3,7 @@ title Hello, world date 1970-01-01T00:00+00:00 category test abstract +author Bob --- { diff --git a/content/posts/post1.md b/content/posts/post1.md index 96c6635..e4e76bd 100644 --- a/content/posts/post1.md +++ b/content/posts/post1.md @@ -3,7 +3,7 @@ title R&D et Veille techno - Petit point sur nos projets internes date 2024-07-11T08:33:06+00:00 category Technologie abstract Un petit tour d'horizon des projets sur lesquels nos équipes techniques travaillent actuellement ... - +author Damien ACCORSI --- { diff --git a/content/posts/post2.md b/content/posts/post2.md index 8e9b54c..f27f03a 100644 --- a/content/posts/post2.md +++ b/content/posts/post2.md @@ -3,6 +3,7 @@ title Microsoft deviendrait-il un spyware avec la fonctionnalité Recall ? date 2024-05-22T12:36:09+00:00 category Technologie abstract Le 20 mai 2024, Microsoft annonce la fonctionnalité Recall qui va "aider les utilisateurs à trouver leurs informations" en s'appuyant sur l'IA ... +author Damien ACCORSI --- { diff --git a/content/posts/post3.md b/content/posts/post3.md index 12f5ae8..2866605 100644 --- a/content/posts/post3.md +++ b/content/posts/post3.md @@ -3,6 +3,7 @@ title Venez échanger sur les sujets de collaboration d'équipe et e-mail aux date 2024-05-20T16:20:03+00:00 category Univers du libre abstract Algoo sera présente et très active aux JDLL 2024 : stand, ateliers et conférence ! +author Damien ACCORSI --- { diff --git a/content/templates/jinja2/post-list.html b/content/templates/jinja2/post-list.html index e0a1620..6d43bd5 100644 --- a/content/templates/jinja2/post-list.html +++ b/content/templates/jinja2/post-list.html @@ -1,4 +1,4 @@ -{% extends "base.html" %} +{% extends "base.html"%} {% block content %}
@@ -6,13 +6,56 @@ Catégories : Tout {% for category in object.categories %} - {{ category }} + {{ category|replace('-', ' ')|title }} {% endfor %}
+
{% for post in object.posts %} - {{ post.timestamp.strftime("%d/%m/%Y") }} : {{ post.title }} : {{ post.metadata.abstract }}
+
+
+
+
+ + +

{{ post.title }}

+
+ +
+

{{ post.metadata.abstract }}

+
+ +
+
+
+
+
{{post.metadata.author}}
+
+ +
+
+
{{ post.timestamp.strftime("%d/%m/%Y") }}
+
+
+ +
+ + Lire la suite ... + +
+
+ +
+
+
+
{% endfor %} +
{% endblock %} \ No newline at end of file diff --git a/content/templates/jinja2/post.html b/content/templates/jinja2/post.html index 3204026..7ba96ce 100644 --- a/content/templates/jinja2/post.html +++ b/content/templates/jinja2/post.html @@ -5,4 +5,5 @@

{{ object.title }}

{{ object.content|safe }} +Tous les posts {% endblock %} diff --git a/jssg/models.py b/jssg/models.py index 1115a35..33f266e 100644 --- a/jssg/models.py +++ b/jssg/models.py @@ -299,7 +299,7 @@ class Sitemap : posts_slugs = [p["slug"] for p in Post.get_posts()] class PostList : - metadata = {} + metadata = {"page_header_h1":"Posts"} category = "" def __init__(self, category = "") -> None: diff --git a/tsconfig.json b/tsconfig.json index 2abd10b..b534021 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -30,6 +30,12 @@ "@t:jssg/*": [ "./jssg/templates/jssg/*" ], + "@s:django_jinja_markdown/*": [ + "./env/lib/python3.9/site-packages/django_jinja_markdown/static/django_jinja_markdown/*" + ], + "@t:django_jinja_markdown/*": [ + "./env/lib/python3.9/site-packages/django_jinja_markdown/templates/django_jinja_markdown/*" + ], "@s:django_distill/*": [ "./env/lib/python3.9/site-packages/django_distill/static/django_distill/*" ], From 4d50f9a0f9351e21b87672711f462418f76fe881 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment?= Date: Wed, 17 Jul 2024 13:47:40 +0200 Subject: [PATCH 8/8] Add pagination and tree structure for posts --- content/posts/ia.md | 22 +++++++ content/posts/manipuler-pdf.md | 69 ++++++++++++++++++++++ content/posts/{ => test}/19700101_hello.md | 0 content/posts/xs-compromise.md | 25 ++++++++ content/templates/jinja2/post-list.html | 35 +++++++++-- content/templates/jinja2/post.html | 4 +- jssg/models.py | 34 ++++++++--- jssg/settings.py | 1 + jssg/urls.py | 14 ++--- jssg/views.py | 2 +- 10 files changed, 183 insertions(+), 23 deletions(-) create mode 100644 content/posts/ia.md create mode 100644 content/posts/manipuler-pdf.md rename content/posts/{ => test}/19700101_hello.md (100%) create mode 100644 content/posts/xs-compromise.md diff --git a/content/posts/ia.md b/content/posts/ia.md new file mode 100644 index 0000000..50b4668 --- /dev/null +++ b/content/posts/ia.md @@ -0,0 +1,22 @@ +--- +title L'IA 🧠 va-t-elle remplacer la recherche web classique ? +date 2024-05-20T15:12:42+00:00 +category Technologie +abstract L'intelligence artificielle est partout. Tout le monde en parle ... Cet article vous propose de découvrir un cas intéressant et très puissant. +author Damien ACCORSI +--- +{ + +} +--- + +{%markdown%} +La question se pose ... + +Quelques mots-clé : #veilletechno #googlesearch #ia #notopensource + +Cette publication n'a pas vocation a approfondir et à répondre à la question mais plutôt à partager l'existence d'une solution intéressante et qui a été présentée à l'un des suricates comme le futur remplaçant de google search. + +![Perplexity va-t-il remplacer Google Search ?](/actualites/images/800x600/image-14219ee739c6a17b76d59f1d55b73776ea8b5e0e.png) + +{%endmarkdown%} \ No newline at end of file diff --git a/content/posts/manipuler-pdf.md b/content/posts/manipuler-pdf.md new file mode 100644 index 0000000..be3f3af --- /dev/null +++ b/content/posts/manipuler-pdf.md @@ -0,0 +1,69 @@ +--- +title Quels logiciels libres pour manipuler des fichiers PDF ? +date 2024-05-03T08:43:47+00:00 +category univers du libre +abstract Manipuler des fichiers PDF est chose courante ; il existe une série de logiciels libres qui permet de procéder à la majorité des manipulations que l'on est en droit d'attendre de tels outils. +author Damien ACCORSI +--- +{ + +} +--- + +{%markdown%} +Nous sommes tous amenés, à un moment ou à un autre, dans notre vie personnelle ou professionnelle, à manipuler des PDF. + +Tout le monde connait Acrobat Reader et autres services en ligne tels que Ilovepdf. + +Mais existe-t-il des logiciels libres pour procéder aux même opérations ? Si oui quels sont ces outils ? + + +## Consulter des PDF + +**Evince** est un visionneur de documents pour GNOME. Il permet de visualiser des PDFs et de les imprimer + +## Modifier et produire des PDF + +**Libreoffice** permet d'exporter les documents que l'on rédige en PDF. + +Moins connu, **Libreoffice Draw** permet quant à lui d'ouvrir des PDF existant et d'en éditer le contenu. + +## Découper, extraire, fusionner des fichiers PDF en masse (en ligne de commande) + +PDFtk permet facilement de découper un fichier PDF via la commande `pdftk file.pdf burst` + +Il est également possible d'extraire un lot de pages `pdftk file.pdf cat 3-5 output pages-3-to-5.pdf` + +Enfin, il est possible de concaténer des fichiers PDF, exemple : `pdftk file1.pdf file2.pdf cat output file1-file2-merged.pdf` + +D'autres opérations sont possibles. + +Pour un équivalent graphique, je vous renvoie vers PDF Chain qui m'a permis, par exemple, de découvrir qu'on pouvait intégrer des pièces jointes quelconques dans un PDF. + + +![](/actualites/images/500x500/image-b0158969619b6e2215ff928a68a0cd882228d06a.png) + +## Découper, extraire, fusionner des PDFs naturellement + +Pour un usage plus grand public, je ne peux que vous conseiller de vous tourner vers PDF Arranger. + +Il permet de procéder aux même opérations que les outils précédemment cités, avec l'avantage de travailler sur des éléments visuels car l'interface intègre une prévisualisation des pages, une sélection à la souris et des menus contextuels - bref un ensemble plus intuitif pour les utilisations qui ne sont pas familiers avec la ligne de commande. + +![](/actualites/images/500x500/image-3a7f8c0e10a091e5b7d8d5ac1d454ff27f1edf6d.png) + +---- + +Voilà, vous savez désormais quoi utiliser pour : + + +- 🖨 Imprimer un document PDF +- ⤵ tourner les pages d'un document PDF +- ✂ découper un document PDF page par page +- 🖇 fusionner plusieurs documents PDF +- 🔎 extraire des sections de pages d'un document PDF + + +Vous n'avez plus aucune excuse pour diffuser des données confidentielles sur des services en ligne "gratuits" ;) + + +{%endmarkdown%} \ No newline at end of file diff --git a/content/posts/19700101_hello.md b/content/posts/test/19700101_hello.md similarity index 100% rename from content/posts/19700101_hello.md rename to content/posts/test/19700101_hello.md diff --git a/content/posts/xs-compromise.md b/content/posts/xs-compromise.md new file mode 100644 index 0000000..ce16595 --- /dev/null +++ b/content/posts/xs-compromise.md @@ -0,0 +1,25 @@ +--- +title La lib de compression Xz compromise ... +date 2024-04-03T13:13:26+00:00 +category Technologie +abstract Une porte dérobée introduite dans la lib de compression Xz a été fortuitement découverte par un développeur PostgreSQL ... +author Damien ACCORSI +--- +{ + +} +--- + +{%markdown%} +La bibliothèque partagée de compression Xz (liblzma) a été compromise par l'un de ses 2 principaux développeurs. Une porte dérobée a été introduite et fortuitement découverte par un développeur du projet PostgreSQL qui [évoque humblement sa découverte sur Mastodon](https://mastodon.social/@AndresFreundTec/112180083704606941) : « I accidentally found a security issue while benchmarking postgres changes » + +L'ingéniosité de l'attaque est de passer par un contributeur au long court et par une démarche très ingénieuse ; [Ytterbium décrit en détail l'attaque dans un long journal publié sur LinuxFR](https://linuxfr.org/users/ytterbium/journaux/xz-liblzma-compromis). + +Une fois n'est pas coutume : le problème des dépendances "invisibles" (et pour autant stratégiques) se pose ... + +![Dépendances](https://imgs.xkcd.com/comics/dependency.png) + +(source: https://xkcd.com/2347/ ) + + +{%endmarkdown%} \ No newline at end of file diff --git a/content/templates/jinja2/post-list.html b/content/templates/jinja2/post-list.html index 6d43bd5..f7256f1 100644 --- a/content/templates/jinja2/post-list.html +++ b/content/templates/jinja2/post-list.html @@ -4,9 +4,9 @@
@@ -17,8 +17,7 @@
- - +

{{ post.title }}

@@ -42,7 +41,7 @@

{{ post.title }}

Lire la suite ... @@ -57,5 +56,31 @@

{{ post.title }}

{% endfor %}
+
+{% if object.page > 1 %} + {% if object.category != "" %} + Page précédente + {% else %} + Page précédente + {% endif %} +{% endif %} +{% if object.page < object.nb_pages %} + {% if object.category != "" %} + Page suivante + {% else %} + Page suivante + {% endif %} +{% endif %} +
+
+Pages : +{% for page in range(1, object.nb_pages+1) %} + {% if object.category != "" %} + {{page}} + {% else %} + {{page}} + {% endif %} +{% endfor %} +
{% endblock %} \ No newline at end of file diff --git a/content/templates/jinja2/post.html b/content/templates/jinja2/post.html index 7ba96ce..25a1e33 100644 --- a/content/templates/jinja2/post.html +++ b/content/templates/jinja2/post.html @@ -5,5 +5,7 @@

{{ object.title }}

{{ object.content|safe }} -Tous les posts + {% endblock %} diff --git a/jssg/models.py b/jssg/models.py index 33f266e..f0a6450 100644 --- a/jssg/models.py +++ b/jssg/models.py @@ -27,6 +27,8 @@ from django.core.management.commands.runserver import Command as runserver +from math import ceil + class Document: """A document. @@ -302,12 +304,18 @@ class PostList : metadata = {"page_header_h1":"Posts"} category = "" - def __init__(self, category = "") -> None: + def __init__(self, category = "", page = 1) -> None: self.category = category + self.page = page + self.posts_by_page = settings.JFME_NUMBER_OF_POSTS_BY_PAGE + if self.category == "" : + self.nb_pages = ceil(len(list(Post.load_glob(all=True))) / self.posts_by_page) # number of posts / number of posts by page + else : + self.nb_pages = ceil(len(list(filter(lambda p: p.metadata["category"] == self.category, Post.load_glob(all=True)))) / self.posts_by_page) # number of posts of the category / number of posts by page @classmethod - def load_post_list_with_category(cls, category) : - return cls(category) + def load_post_list_with_category(cls, category, page) : + return cls(category, page) @property def categories(self) : @@ -315,17 +323,25 @@ def categories(self) : for post in Post.load_glob(all = True) : if post.metadata["category"] != "" : cat.add(post.metadata["category"]) - return cat + return sorted(cat) @classmethod - def get_categories(cls) : - return [{"category": category} for category in cls().categories] + def get_categories_and_pages(cls) : + t = [] + for category in cls().categories : + t += [{"category": category, "page":page} for page in range(1, cls(category).nb_pages + 1)] + return t + + + @classmethod + def get_pages(cls) : + return [{"page": page} for page in range(1, cls().nb_pages+1)] @property def posts(self) : - posts = sorted(Post.load_glob(), key=lambda p: p.timestamp, reverse=True) + posts = sorted(Post.load_glob(all=True), key=lambda p: p.timestamp, reverse=True) if self.category == "" : - return posts + return posts[self.posts_by_page*(self.page-1):self.posts_by_page*(self.page)] else : - return filter(lambda p: p.metadata["category"] == self.category, posts) + return list(filter(lambda p: p.metadata["category"] == self.category, posts))[self.posts_by_page*(self.page-1):self.posts_by_page*(self.page)] \ No newline at end of file diff --git a/jssg/settings.py b/jssg/settings.py index 71e6f44..81b75a0 100644 --- a/jssg/settings.py +++ b/jssg/settings.py @@ -52,6 +52,7 @@ JFME_POSTS_DIRS = [path / "posts" for path in JFME_CONTENT_DIRS] JFME_TEMPLATES_DIRS = [path / "templates" for path in JFME_CONTENT_DIRS] JFME_STATIC_DIRS = [path / "static" for path in JFME_CONTENT_DIRS] +JFME_NUMBER_OF_POSTS_BY_PAGE = 3 diff --git a/jssg/urls.py b/jssg/urls.py index a90da9f..736bb23 100644 --- a/jssg/urls.py +++ b/jssg/urls.py @@ -20,7 +20,7 @@ # print([p for p in Page.get_pages()]) -# print([p for p in PostList.get_categories()]) +# print([p for p in PostList.get_categories_and_pages()]) urlpatterns = [ distill_path( @@ -41,25 +41,25 @@ distill_path("atom.xml", views.PostFeedsView(), name="atom_feed"), distill_path( - "posts/", + "posts/page.html", views.PostListView.as_view(), name = "post-index", - distill_file = "posts/index.html" + distill_func = PostList.get_pages ), distill_path( - "posts/category/.html", + "posts/category//page.html", views.PostListView.as_view(), name = "post-category", - distill_func = PostList.get_categories + distill_func = PostList.get_categories_and_pages ), distill_path( - "posts/.html", + "posts/articles/.html", views.PostView.as_view(), name="post", distill_func=Post.get_posts, ), distill_path( - "posts//.html", + "posts/articles//.html", views.PostView.as_view(), name="post", distill_func=Post.get_posts, diff --git a/jssg/views.py b/jssg/views.py index 86e0766..3145513 100644 --- a/jssg/views.py +++ b/jssg/views.py @@ -87,4 +87,4 @@ def get_object(self, queryset=None) -> Model: if "category" not in self.kwargs.keys() : self.kwargs["category"] = "" print(self.kwargs["category"]) - return PostList.load_post_list_with_category(self.kwargs["category"]) \ No newline at end of file + return PostList.load_post_list_with_category(self.kwargs["category"], self.kwargs["page"]) \ No newline at end of file