Merge pull request 'add-posts' (#9) from add-posts into main
All checks were successful
deploy / docker (push) Successful in 11m5s

Reviewed-on: https://gitea.mrdev023.fr/florian.richer/portfolio/pulls/9
This commit is contained in:
florian.richer 2024-02-18 18:10:22 +01:00
commit b797465280
10 changed files with 1424 additions and 634 deletions

1
.gitignore vendored
View file

@ -26,3 +26,4 @@ dist-ssr
# Added by cargo
/target
.sass-cache/

635
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
[package]
name = "portfolio"
version = "0.5.0"
version = "0.6.0"
edition = "2021"
[lib]
@ -9,9 +9,9 @@ crate-type = ["cdylib", "rlib"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
leptos = { version = "0.5", features = ["nightly"] }
leptos_meta = { version = "0.5", features = ["nightly"] }
leptos_router = { version = "0.5", features = ["nightly"] }
leptos = { version = "0.6", features = ["nightly"] }
leptos_meta = { version = "0.6", features = ["nightly"] }
leptos_router = { version = "0.6", features = ["nightly"] }
gloo-net = { version = "0.5", features = ["http"] }
log = "0.4"
cfg-if = "1.0"
@ -19,7 +19,7 @@ serde = "1.0"
chrono = { version = "0.4", features = ["serde"] }
# https://carlosted.github.io/icondata/
leptos_icons = "0.2"
leptos_icons = "0.3"
icondata = "0.3"
# dependecies for client (enable when csr or hydrate set)
@ -29,11 +29,11 @@ console_error_panic_hook = { version = "0.1", optional = true }
# dependecies for server (enable when ssr set)
actix-files = { version = "0.6", optional = true }
actix-web = { version = "4.4", features = ["macros"], optional = true }
leptos_actix = { version = "0.5", optional = true }
actix-web = { version = "4.5", features = ["macros"], optional = true }
leptos_actix = { version = "0.6", optional = true }
futures = { version = "0.3", optional = true }
simple_logger = { version = "4.3", optional = true }
pulldown-cmark = { version = "0.9", optional = true } # Markdown parser
pulldown-cmark = { version = "0.10", optional = true } # Markdown parser
gray_matter = { version = "0.2", optional = true } # frontmatter parser
serde_yaml = { version = "0.9", optional = true }
anyhow = { version = "1.0", optional = true }

View file

@ -0,0 +1,375 @@
---
image_path: "https://community.kde.org/images.community/thumb/a/af/Mascot_konqi-base-plasma.png/250px-Mascot_konqi-base-plasma.png"
slug: kde_first_contrib
title: Mes premières contributions à KDE
date: 2024-01-12T00:00:00Z
description: Ma première configuration et ma première contribution à l'environnement mobile (Plasma-Mobile).
project_link: none
draft: true
tags:
- kde
- linux
---
## Rapide rappel à propos de KDE
KDE est un projet qui a pour but de développer des logiciels open-source. Le projet comporte plusieurs éléments les plus connus.
- [KF5 ou KF6](https://develop.kde.org/products/frameworks/) est un ensemble de librairies utilisées pour le développement de l'ensemble des logiciels de KDE. Il est basé sur la librairie [QT](https://www.qt.io/).
> _Exemple_ : Kirigami que l'on peut voir comme un "flutter".
>
> _Note:_
>
> KF5 => Basé sur QT5
>
> KF6 => Basé sur QT6
- [Plasma Shell](https://kde.org/fr/plasma-desktop/) est l'environnement de bureau développé pour Linux.
## Ma configuration
Pour développer sur KDE, KDE fournis un utilitaire assez puissant `kdesrc-build`.
Il permet de configurer l'IDE, compiler, exécuter et gérer les dépendances avec l'aide d'une seule ligne de commande.
Pour le configurer, il suffit de suivre la procédure sur ce [lien](https://community.kde.org/Get_Involved/development/Set_up_a_development_environment).
### Mes premières difficultés
Il faut savoir que quand j'ai commencé à vouloir contribuer au projet KDE. Le projet était en train de migrer de QT5 à QT6.
Donc, les configurations nécessaires pour compiler correctement la version 6 était nettement plus compliqué que maintenant.
Il n'y avait aucune documentation pour migrer la configuration fournie de base, il fallait fouiller sur Github ou sur les blogs pour réussir
à avoir la configuration.
Aujourd'hui, il suffit juste de suivre le lien ci-dessus et on peut directement travailler sur KDE 6.
Pour le développement sur KDE Plasma 6, j'ai dû faire quelques réajustements sur le fichier `~/.config/kdesrc-buildrc`.
J'ai changé la branche par défaut avec l'option `branch-group kf6-qt6`.
Elle permet de cloner les repositories correctement et d'ajouter l'option cmake `-DBUILD_WITH_QT6=on`.
J'ai aussi changé les fichiers de configuration utilisées pour obtenir le résultat ci-dessous.
```
global
branch-group kf6-qt6
[...]
end global
include ~/kde/src/kdesrc-build/data/build-include/kf6-common-options.ksb
include ~/kde/src/kdesrc-build/data/build-include/kf6-frameworks.ksb
include ~/kde/src/kdesrc-build/data/build-include/kf6-workspace.ksb
include ~/kde/src/kdesrc-build/data/build-include/kf6-applications.ksb
include ~/kde/src/kdesrc-build/data/build-include/kf6-kdepim.ksb
```
### Configurations utiles
#### Désactiver l'arrêt de la compilation lors d'une erreur de compilation.
En général, `kdesrc-build` s'adapte et retire tous les projets qui dépendent de la dépendance qui n'a pas réussi à compiler.
Le projet était encore en cours de développement donc les erreurs de compilations étaient très régulières.
J'ai tout simplement désactivé avec l'option `stop-on-failure false`.
#### Activer le support des LSP
C'est très pratique si on utilise VSCode ou même n'importe quel outil qui supporte les [LSP](https://microsoft.github.io/language-server-protocol/).
Il suffit d'activer les options:
* `compile-commands-linking` => `true`
* `compile-commands-export` => `true`
#### Générer les projets VSCode
Il va générer automatiquement les workspaces VSCode avec les extensions recommander et le paramètrage par défaut.
Ça permet de travailler dans de très bonne condition avec VSCode.
Il suffit de l'activer avec `generate-vscode-project-config true`
#### Options utiles pour la commande kdesrc-build
* `-D` : Pour ne pas inclure les dépendances dans la compilation
> Exemple: kdesrc-build -D kate
* `-S` : Pour ne pas mettre à jour les sources
> Exemple: kdesrc-build -S kate
## Ma contribution
J'ai contribué sur le support de la lampe torche pour l'environnement Plasma Mobile.
La lampe torche fonctionnait uniquement sur les [pinephones](https://pine64.org/devices/pinephone/) en utilisant le fichier en dure `/sys/devices/platform/led-controller/leds/white:flash/brightness`
([Source](https://invent.kde.org/plasma/plasma-mobile/-/blob/f970aa7acf2e9794ab4ed6b75e8f549bece83561/quicksettings/flashlight/flashlightutil.cpp#L17)).
J'ai réécris le module pour que ça fonctionne de manière générale sur tous les téléphones.
### Rappel sur le fonctionnement du noyau Linux autour des leds
Pour comprendre comment la fonctionnalité, un petit rappel s'impose autour du fonctionnement des leds avec le noyau Linux.
Dès qu'une led est détecté par le noyau, il va mettre à disposition plusieurs fichiers.
On les trouvent dans le dossier correspondant au driver et aussi à l'emplacement physique sur la carte mère ou sur le SOC.
Mais on peut aussi les trouver plus facilement dans le répertoire `/sys/class/leds/`.
> sys => Fichiers système
> class => Trier par class.
> leds => La class `leds`. On peut trouver aussi par appareil `bluetooth`, puce `tpm`, ...
On disposent de plusieurs fichiers importants :
* `brightness` : Permet de changer ou de récupérer l'intensité de la led actuelle.
* `max_brightness` : Permet de connaitre l'intensité max de la led.
* `color` : Ce fichier n'existe pas tout le temps mais permet d'avoir la couleur de la led.
* Le reste des fichiers ne sont pas important pour nous.
### Explication du fonctionnement de mon code petit à petit
Tout d'abord, il faut savoir que j'utilise la libraire Udev. Il est prévu que je migre vers la librairie [Solid](https://invent.kde.org/frameworks/solid) une fois le support des leds ajoutées.
Udev pour faire simple, c'est une librairie qui permet d'interagir avec les appareils assez directement sans intermédiaire.
La librairie permet également de lister, filtrer, détecter si un appareil est connecté/déconnecté, ....
Pour commencer, je dois d'abord instancier Udev avec pour l'utiliser par la suite.
```cpp
struct udev *udev = udev_new();
```
Ensuite, je liste tous les périphériques qui m'intéressent donc ceux appartenant à la class `leds`.
Pour ça, il me suffit de créer un énumerateur sur lequel on appliquera tous les filtres.
> On peut voir une class comme une catégorie d'appareils.
```cpp
struct udev_enumerate *enumerate = udev_enumerate_new(udev);
```
J'applique le filtre pour lister uniquement ceux qui appartiennent à la class `leds`.
```cpp
#define TORCH_SUBSYSTEM "leds"
...
udev_enumerate_add_match_subsystem(enumerate, TORCH_SUBSYSTEM);
```
J'applique le filtre pour lister uniquement ceux qui ont dans le nom `flash` ou `torch`.
```cpp
udev_enumerate_add_match_sysname(enumerate, "*:torch");
udev_enumerate_add_match_sysname(enumerate, "*:flash");
```
Puis je lance le scan avec mes filtres.
```cpp
udev_enumerate_scan_devices(enumerate);
```
Au début, il faut savoir que je prenais le premier appareil avec le code ci-dessous mais certain téléphone ont une torche de couleur jaune et blanche.
Certain utilisateur malheureusement ne pouvait pas utiliser la fonctionnalité.
```cpp
struct udev_list_entry *devices = udev_enumerate_get_list_entry(enumerate);
struct udev_list_entry *entry = udev_list_entry_get_next(devices);
```
[Source](https://invent.kde.org/plasma/plasma-mobile/-/blob/5c6a97caa52d549c0cb02b17fc65a3a7d729d237/quicksettings/flashlight/flashlightutil.cpp)
Donc, j'ai changé le code avec le code ci-dessous qui permet d'itérer sur tous les appareils.
```cpp
struct udev_list_entry *devices = udev_enumerate_get_list_entry(enumerate);
struct udev_list_entry *entry = nullptr;
struct udev_device *device = nullptr;
udev_list_entry_foreach(entry, devices)
{
[...]
}
```
Pour chaque appareil, j'ai récuperé le répertoire ou se situe l'appareil avec le code ci-dessous
qui me renvoie par exemple: `/sys/devices/platform/led-controller/leds/white:flash`.
```cpp
const char *path = udev_list_entry_get_name(entry);
```
J'instancie une instance udev_device pour interagir avec lui depuis le répertoire.
```cpp
struct udev_device *device = udev_device_new_from_syspath(udev, path);
```
Et à partir de là, il me suffit de lire les fichiers dont j'ai besoin.
```cpp
const char *maxBrightness = udev_device_get_sysattr_value(device, "[NOM DU FICHIER]");
```
Je lis d'abord le fichier 'color' et je regarde si la couleur est blanche sinon je continue.
Si je ne trouve pas de led de couleur blanche, je prends la dernière valeur récupérée.
Une fois pour chaque appareil trouvé, il me reste plus qu'à récupérer les infos dont j'ai besoin.
Donc, la luminosité maximale `max_brightness` et la luminosité actuelle `brightness` pour correctement initialiser l'interface de Plasma Mobile.
Quand je souhaite changer la valeur, je dois d'abord convertir la valeur entière en chaîne de charactère.
```cpp
const_cast<char *>(m_torchEnabled ? "0" : m_maxBrightness)
```
Ensuite, je change la luminosité
```cpp
udev_device_set_sysattr_value(m_device, "brightness", nouvelle_valeur_en_char_*);
```
### Fichier final
[Source](https://invent.kde.org/plasma/plasma-mobile/-/blob/d162f96a63600d5b45bb8294afdb84efd85833f9/quicksettings/flashlight/flashlightutil.cpp)
```cpp
/*
* SPDX-FileCopyrightText: 2020 Han Young <hanyoung@protonmail.com>
* SPDX-FileCopyrightText: 2022 by Devin Lin <devin@kde.org>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "flashlightutil.h"
#include <cstring>
#include <fcntl.h>
#include <libudev.h>
#include <unistd.h>
#include <QDebug>
#include <QFileInfo>
#define TORCH_SUBSYSTEM "leds"
FlashlightUtil::FlashlightUtil(QObject *parent)
: QObject{parent}
, m_device{nullptr}
, m_isAvailable{false}
{
findTorchDevice();
}
FlashlightUtil::~FlashlightUtil()
{
if (m_device != nullptr) {
udev_device_unref(m_device);
}
}
void FlashlightUtil::toggleTorch()
{
if (!isAvailable()) {
qWarning() << "Flashlight not available";
return;
}
int ret = udev_device_set_sysattr_value(m_device, "brightness", const_cast<char *>(m_torchEnabled ? "0" : m_maxBrightness));
if (ret < 0) {
qWarning() << "Flashlight can't be toggled";
return;
}
m_torchEnabled = !m_torchEnabled;
Q_EMIT torchChanged(m_torchEnabled);
}
bool FlashlightUtil::torchEnabled() const
{
return m_torchEnabled;
}
bool FlashlightUtil::isAvailable() const
{
return m_isAvailable;
}
void FlashlightUtil::findTorchDevice()
{
if (m_device != nullptr) {
udev_device_unref(m_device);
}
m_device = nullptr;
m_isAvailable = false;
struct udev *udev = udev_new();
struct udev_enumerate *enumerate = udev_enumerate_new(udev);
udev_enumerate_add_match_subsystem(enumerate, TORCH_SUBSYSTEM);
udev_enumerate_add_match_sysname(enumerate, "*:torch");
udev_enumerate_add_match_sysname(enumerate, "*:flash");
udev_enumerate_scan_devices(enumerate);
struct udev_list_entry *devices = udev_enumerate_get_list_entry(enumerate);
struct udev_list_entry *entry = nullptr;
struct udev_device *device = nullptr;
udev_list_entry_foreach(entry, devices)
{
const char *path = udev_list_entry_get_name(entry);
if (path == nullptr) {
continue;
}
if (device != nullptr) {
udev_device_unref(device); // Use to free memory from previous loop iteration
}
device = udev_device_new_from_syspath(udev, path);
if (device == nullptr) {
continue;
}
qInfo() << "Found flashlight device : " << path;
const char *color = udev_device_get_sysattr_value(device, "color");
if (color == nullptr) {
continue;
}
qInfo() << "Flash color : " << color;
if (std::strcmp(color, "white") == 0) {
break;
}
}
if (device == nullptr) {
qWarning() << "No flashlight device found";
return;
}
const char *maxBrightness = udev_device_get_sysattr_value(device, "max_brightness");
if (maxBrightness == nullptr) {
qWarning() << "Failed to read max_brightness from udev device";
return;
}
qInfo() << "Flash maxBrightness : " << maxBrightness;
const char *brightness = udev_device_get_sysattr_value(device, "brightness");
if (brightness == nullptr) {
qWarning() << "Failed to read brightness from udev device";
return;
}
qInfo() << "Flash brightness : " << brightness;
m_maxBrightness = maxBrightness;
m_device = device;
m_isAvailable = true;
m_torchEnabled = std::strcmp(brightness, "0") != 0;
udev_enumerate_unref(enumerate);
udev_unref(udev);
}
```
### Info utile pour débugger KDE Plama Mobile depuis Postmarket OS
Le fichier de log se situe dans `~/.local/state/tinydm.log`

View file

@ -0,0 +1,159 @@
---
image_path: "https://postmarketos.org/logo.svg"
slug: pmbootstrap_own_paquet
title: Compiler un paquet Postmarket OS
date: 2024-02-18T00:00:00Z
description: Installation de pmbootstrap et compilation d'un paquet Postmarket OS
project_link: none
draft: true
tags:
- pmOS
- linux
---
## À propos de Postmarket OS
[Postmarket OS](https://postmarketos.org/) est une distribution basée sur [Alpine](https://www.alpinelinux.org/) conçut pour fonctionner sur téléphone, tablette
ou sur Raspberry PI.
La communauté autour du projet propose un ensemble d'outils comme `pmbootstrap` qui permet de configurer et d'installer Postmarket OS sur son téléphone.
On peut aussi l'utiliser pour compiler son propre paquet et l'installer sur son téléphone facilement.
## Configuration de notre environnement de travail
Avant de pouvoir l'utiliser, il faut d'abord l'installer depuis ce [lien](https://wiki.postmarketos.org/wiki/Pmbootstrap).
Une fois installé et configuré, il faut d'abord préparer son environnement de travail.
_Met à jour le repository [pmaports.git](https://wiki.postmarketos.org/wiki/Pmaports.git) cloné en local._
```bash
pmbootstrap pull
```
> Le repo pmaports.git stocke tous les paquets Alpine avec le fichier `APKBUILD` utilisé par le serveur de compilation.
>
> Le fonctionnement est similaire à `PKGBUILD` pour les utilisateurs de [Archlinux](https://archlinux.org/)
>
> Ce fichier contient toute la procédure pour préparer les sources, compiler le paquet depuis les sources, le numéro de version
> ainsi que la procédure pour vérifier si le paquet fonctionne correctement.
> Généralement on utilise les tests du projet comme les tests unitaires ou les tests fonctionnels.
_Met à jour le cache de la commande APK depuis l'environnement de travail_
```bash
pmbootstrap update
```
> L'environnement de travail se situe par défaut dans le dossier `$HOME/.local/var/pmbootstrap/`
_Supprime le dossier de la commande chroot_
```bash
pmbootstrap zap
```
> La commande chroot permet de changer la racine Linux.
> Par exemple, on peut faire `chroot $HOME/mon_dossier` et à partir de ce moment-là, `/` pointera vers `$HOME/mon_dossier` dans notre shell actuel.
>
> C'est très utilisé par pmbootstrap pour configurer le système Alpine.
> Ça évite de devoir faire une VM ou un container Linux juste pour changer quelque fichier.
>
> Dans notre cas, il correspond au système de notre téléphone pour le configuré avant de l'installer ou de le tester sur notre appareil.
>
> Par défaut, il se situe dans le dossier `$HOME/.local/var/pmbootstrap/cache_git/pmaports/`
_[Optionnel] Changer la branche du repo [pmaports.git](https://wiki.postmarketos.org/wiki/Pmaports.git)_
```bash
git -C $workdir checkout [branch]
```
> `$workdir` par défaut se situe dans le dossier `$HOME/.local/var/pmbootstrap/cache_git/pmaports/`
>
> Exemple de branche utile : `kde-nightly`
## Compilation de notre paquet Alpine
Pour compiler le paquet, on utilise la commande `pmbootstrap build [paquet_name]`.
_Exemple de commande_
```bash
pmbootstrap \
-mp https://nightly.postmarketos.org/plasma-mobile/paquets/ \
-mp http://mirror.postmarketos.org/postmarketos/ \
--details-to-stdout \
-j 32 \
-t 3600 -v \
build plasma-mobile \
--src $home/plasma-mobile/ \
--arch aarch64 \
-i \
-n
```
Dans cet exemple, j'ai utilisé les arguments suivants:
* `-mp` : Permet de définir un repository Alpine pour installer les paquets.
> Dans l'exemple, j'utilise deux repos
>
> `https://nightly.postmarketos.org/plasma-mobile/paquets/` : Contient la version en cours de développement de KDE Plasma Mobile
>
> `http://mirror.postmarketos.org/postmarketos/` : Le miroir officiel de Postmarket OS
* `--details-to-stdout` : Affiche les logs stocké dans le fichier dans la console
* `-j N` : Défini le nombre core utilisé pour la compilation
> Dans mon cas, 32 core sur mon CPU.
* `-t [En seconde]` : Le nombre de secondes sans nouveau log dans le fichier avant d'abandonner la compilation
> Changé par 3600 secondes, car plasma-mobile est assez long à compilé et il ne génère aucun log.
* `-v` : Mode verbeux pour les logs dans le fichier
* `--src` : Change les sources du paquet. Par défaut ce sont les sources définies dans le fichier `APKBUILD`
> Pour ma part, je souhaite utiliser mon propre code pour tester
* `--arch [arch]` : L'architecture CPU du téléphone
> Pour ma part, mon téléphone est en arm64v8 donc `aarch64`
* `-n` : Permet d'éviter de compiler les dépendances du paquet.
> En général, ce n'est pas recommandé par Alpine, mais dans mon cas, je souhaite utiliser les dépendances depuis le repo
> miroir officiel de Postmarket OS.
* `-i` : Permet de dire de compiler uniquement les dépendances du paquet défini dans le fichier `APKBUILD`
> Dans mon cas, il vient en complément de l'option `-n`, ça me permet de m'assurer de ne rien build.
> Sans cette option, il risque de compiler les sous-dépendances du paquet comme le noyau Linux.
Pour plus d'informations, il suffit de taper la commande
```bash
pmbootstrap build --help
```
Et pour avoir les arguments généraux
```bash
pmbootstrap --help
```
## Envoie du paquet sur le téléphone
Une fois le paquet compilé, il suffit de demander à `pmbootstrap` de l'envoyer sur notre téléphone via la connexion SSH.
Avec `pmbootstrap`, on utilise la commande `sideload` comme dans l'exemple ci-dessous.
```bash
pmbootstrap sideload plasma-mobile \
--host [SSH HOST] \
--port [SSH PORT] \
--user [SSH USER] \
--arch [ARCH] \
--install-key
```
On a les arguments suivants :
* `--host [SSH HOST]` (Ex: 192.168.1.1)
* `--port [SSH PORT]` (Ex: 22)
* `--user [SSH USER]` (Ex: 192.168.1.1)
* `--arch [ARCH]` : Permet de modifier la valeur définie pour le téléphone (Ex : aarch64)
* `--install-key` : Permet d'installer la clef utilisée pour la vérification des paquets de la machine actuelle.
> Tout gestionnaire de paquet comme APK, vérifie si le paquet est valide par rapport à la signature électronique du mainteneur du paquet.
> Dans notre cas, la signature ne sera pas valide, car le paquet n'est pas compilé par le mainteneur original donc il suffit de rajouter notre signature.
Pour revenir en arrière, il suffit de taper la commande ci-dessous depuis le téléphone ou depuis la connexion SSH
```bash
sudo apk upgrade -a
```
> APK va réinstaller les paquets depuis les repos officiels.
En cas de problème liée à des conflits de fichier, on peut utiliser cette commande
```bash
sudo apk fix --force
```
> Cette commande va forcer APK à écraser les fichiers en conflit.

View file

@ -1,78 +0,0 @@
---
image_path: "https://upload.wikimedia.org/wikipedia/commons/thumb/1/11/Test-Logo.svg/783px-Test-Logo.svg.png?20150906031702"
slug: test_layout
title: Testing layout
date: 2023-11-26T00:00:00Z
description: Testing the layout of the site.
project_link: none
draft: true
tags:
- test
---
# Heading 1
## Heading 2
### Heading 3
#### Heading 4
##### Heading 5
###### Heading 6
This is a paragraph tag. It's used `for` displaying text content.
[Click me to visit Example website!](https://www.example.com)
Unordered list
* Item 1
* Item 2
* Item 3
Ordered list
1. Item 1
2. Item 2
3. Item 3
> It's probably important that images look okay here by default as well:
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/1/11/Test-Logo.svg/783px-Test-Logo.svg.png?20150906031702">
### Code Blocks
```python
def hello_world():
print("Hello World!")
```
```rust
fn main() {
println!("Hello World!");
}
```
```javascript
function helloWorld() {
console.log("Hello World!");
}
```
```ruby
def hello_world
puts "Hello World!"
end
```
```dockerfile
FROM rust
RUN cargo build --release
CMD ["./target/release/hello_world"]
```
```mermaid
graph TD;
A-->B;
A-->C;
B-->D;
C-->D;
```

721
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,5 @@
mod post;
pub use post::{Post, PostMetadata};
cfg_if::cfg_if! {
if #[cfg(feature = "ssr")] {
use std::collections::HashMap;
@ -16,8 +14,10 @@ cfg_if::cfg_if! {
impl Data {
#[allow(dead_code)] // Use in main.rs
pub fn new() -> anyhow::Result<Self> {
let posts = crate::app::utils::data_src::get_all::<Post>("posts")?
.into_iter()
let mut posts = crate::app::utils::data_src::get_all::<Post>("posts")?;
posts.sort_by(|post, post2| post2.metadata.date.cmp(&post.metadata.date));
let posts = posts.into_iter()
.map(Arc::new)
.collect::<Vec<_>>();
@ -47,4 +47,6 @@ cfg_if::cfg_if! {
}
}
}
pub use post::{Post, PostMetadata};

View file

@ -38,7 +38,7 @@ cfg_if::cfg_if! {
let matter = Matter::<YAML>::new();
let mut post_data = matter
.parse_with_struct::<PostMetadata>(&content)
.ok_or_else(|| PostDeserializationError::InvalidFrontMatter)?;
.ok_or(PostDeserializationError::InvalidFrontMatter)?;
let content = post_data.content;

View file

@ -11,42 +11,39 @@ use crate::app::{
pub async fn get_posts(
tag: Option<String>
) -> Result<Vec<Post>, ServerFnError> {
leptos_actix::extract(
|data: actix_web::web::Data<crate::app::models::Data>| async move {
let data = data.into_inner();
let default = vec![];
let posts = match tag {
Some(tag) => data.posts_by_tag.get(&tag).unwrap_or(&default),
None => &data.posts
};
posts.iter()
.map(|post| {
Post {
metadata: post.metadata.clone(),
content: post.content.clone(),
}
})
.collect::<Vec<_>, >()
},
).await
let data : actix_web::web::Data<crate::app::models::Data> = leptos_actix::extract().await?;
let data = data.into_inner();
let default = vec![];
let posts = match tag {
Some(tag) => data.posts_by_tag.get(&tag).unwrap_or(&default),
None => &data.posts
};
Ok(
posts.iter()
.map(|post| {
Post {
metadata: post.metadata.clone(),
content: post.content.clone(),
}
})
.collect::<Vec<_>, >()
)
}
#[server]
pub async fn get_post(
slug: String
) -> Result<Post, ServerFnError> {
leptos_actix::extract(
|data: actix_web::web::Data<crate::app::models::Data>| async move {
let data = data.into_inner();
data.posts_by_slug.get(&slug)
.and_then(|post| Some(Post {
metadata: post.metadata.clone(),
content: post.content.clone(),
}))
},
)
.await
.and_then(|post| post.ok_or_else(|| ServerFnError::ServerError("Post not found".to_string())))
let data : actix_web::web::Data<crate::app::models::Data> = leptos_actix::extract().await?;
let data = data.into_inner();
data.posts_by_slug.get(&slug).map(|post| Post {
metadata: post.metadata.clone(),
content: post.content.clone(),
})
.ok_or(ServerFnError::ServerError("Post not found".to_string()))
}
#[component]
@ -130,7 +127,7 @@ pub fn PostList() -> impl IntoView {
};
let filter_view = move || {
tag().and_then(|tag| Some(view! {
tag().map(|tag| Some(view! {
<div class="mx-auto max-w-3xl mb-5">
Tag sélectionné : <A class="tag" href="/posts".to_string()>{tag}<leptos_icons::Icon icon=icondata::IoClose class="scale-125 ml-1 inline" /></A>
</div>