Amélioration configuration Docusaurus et implémentation i18n
- Add language switcher to navbar for bilingual site (FR/EN) - Remove intro page, use presentation as entry point - Add example pages to all documentation categories - Configure categories with generated-index for page listings - Update footer and homepage links to reference presentation - Enhance configuration with best practices: - Add metadata and SEO keywords - Enable RSS/Atom feeds for blog - Configure sitemap generation - Add syntax highlighting for YAML, HCL, Docker - Enable Mermaid diagram support - Configure table of contents settings - Respect user color scheme preferences - Add last update metadata to docs - Fix deprecated onBrokenMarkdownLinks configuration - Create bilingual example pages with practical code examples - Update all i18n translations for consistency This update brings the site in line with Docusaurus 3.x best practices and provides a solid foundation for documentation growth.
This commit is contained in:
parent
fda75fdd28
commit
aba46f671c
13 changed files with 558 additions and 85 deletions
60
docs/homelab-actuel/exemple.md
Normal file
60
docs/homelab-actuel/exemple.md
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
---
|
||||
sidebar_position: 2
|
||||
---
|
||||
|
||||
# Exemple
|
||||
|
||||
Ceci est une page d'exemple dans la catégorie Homelab actuel.
|
||||
|
||||
## Description
|
||||
|
||||
Cette page démontre comment documenter un service ou une configuration du homelab actuel.
|
||||
|
||||
## Configuration Docker Compose
|
||||
|
||||
Exemple de configuration d'un service :
|
||||
|
||||
```yaml
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
exemple-service:
|
||||
image: nginx:latest
|
||||
container_name: exemple
|
||||
ports:
|
||||
- "8080:80"
|
||||
volumes:
|
||||
- ./config:/etc/nginx/conf.d
|
||||
restart: unless-stopped
|
||||
```
|
||||
|
||||
## Playbook Ansible
|
||||
|
||||
Exemple de déploiement avec Ansible :
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Déployer le service exemple
|
||||
hosts: homelab
|
||||
become: yes
|
||||
|
||||
tasks:
|
||||
- name: Copier le fichier docker-compose
|
||||
copy:
|
||||
src: docker-compose.yml
|
||||
dest: /opt/exemple/docker-compose.yml
|
||||
|
||||
- name: Démarrer le service
|
||||
command: docker-compose up -d
|
||||
args:
|
||||
chdir: /opt/exemple
|
||||
```
|
||||
|
||||
## Maintenance
|
||||
|
||||
Points importants pour la maintenance :
|
||||
|
||||
- Sauvegardes régulières
|
||||
- Mises à jour de l'image Docker
|
||||
- Surveillance des logs
|
||||
- Tests de restauration
|
||||
153
docs/homelab-futur/exemple.md
Normal file
153
docs/homelab-futur/exemple.md
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
---
|
||||
sidebar_position: 2
|
||||
---
|
||||
|
||||
# Exemple
|
||||
|
||||
Ceci est une page d'exemple dans la catégorie Futur Homelab.
|
||||
|
||||
## Description
|
||||
|
||||
Cette page démontre comment documenter les configurations et déploiements Kubernetes du futur homelab.
|
||||
|
||||
## Déploiement Kubernetes
|
||||
|
||||
Exemple de manifeste pour un déploiement :
|
||||
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: exemple-app
|
||||
namespace: production
|
||||
spec:
|
||||
replicas: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
app: exemple
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: exemple
|
||||
spec:
|
||||
containers:
|
||||
- name: app
|
||||
image: nginx:latest
|
||||
ports:
|
||||
- containerPort: 80
|
||||
resources:
|
||||
limits:
|
||||
cpu: 100m
|
||||
memory: 128Mi
|
||||
requests:
|
||||
cpu: 50m
|
||||
memory: 64Mi
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: exemple-service
|
||||
namespace: production
|
||||
spec:
|
||||
selector:
|
||||
app: exemple
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 80
|
||||
type: ClusterIP
|
||||
```
|
||||
|
||||
## Configuration OpenTofu
|
||||
|
||||
Exemple de ressource infrastructure :
|
||||
|
||||
```hcl
|
||||
resource "kubernetes_namespace" "production" {
|
||||
metadata {
|
||||
name = "production"
|
||||
labels = {
|
||||
environment = "production"
|
||||
managed-by = "opentofu"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource "kubernetes_deployment" "exemple" {
|
||||
metadata {
|
||||
name = "exemple-app"
|
||||
namespace = kubernetes_namespace.production.metadata[0].name
|
||||
}
|
||||
|
||||
spec {
|
||||
replicas = 3
|
||||
|
||||
selector {
|
||||
match_labels = {
|
||||
app = "exemple"
|
||||
}
|
||||
}
|
||||
|
||||
template {
|
||||
metadata {
|
||||
labels = {
|
||||
app = "exemple"
|
||||
}
|
||||
}
|
||||
|
||||
spec {
|
||||
container {
|
||||
image = "nginx:latest"
|
||||
name = "app"
|
||||
|
||||
resources {
|
||||
limits = {
|
||||
cpu = "100m"
|
||||
memory = "128Mi"
|
||||
}
|
||||
requests = {
|
||||
cpu = "50m"
|
||||
memory = "64Mi"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## GitOps avec ArgoCD
|
||||
|
||||
Configuration ArgoCD Application :
|
||||
|
||||
```yaml
|
||||
apiVersion: argoproj.io/v1alpha1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: exemple-app
|
||||
namespace: argocd
|
||||
spec:
|
||||
project: default
|
||||
source:
|
||||
repoURL: https://forgejo.tellserv.fr/Tellsanguis/k8s-manifests.git
|
||||
targetRevision: HEAD
|
||||
path: apps/exemple
|
||||
destination:
|
||||
server: https://kubernetes.default.svc
|
||||
namespace: production
|
||||
syncPolicy:
|
||||
automated:
|
||||
prune: true
|
||||
selfHeal: true
|
||||
syncOptions:
|
||||
- CreateNamespace=true
|
||||
```
|
||||
|
||||
## Observabilité
|
||||
|
||||
Points de surveillance pour ce service :
|
||||
|
||||
- Métriques Prometheus exposées sur `/metrics`
|
||||
- Logs agrégés dans Loki
|
||||
- Traces distribuées avec Tempo
|
||||
- Alertes configurées dans Prometheus AlertManager
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# Introduction
|
||||
|
||||
Bienvenue sur **TellServ Tech Blog** !
|
||||
|
||||
Ce blog technique documente mes recherches, réflexions et solutions aux défis techniques rencontrés dans mes projets. L'objectif est de :
|
||||
|
||||
- 📚 **Documenter** mes apprentissages et découvertes
|
||||
- 🔍 **Partager** mes analyses et solutions
|
||||
- 💡 **Démontrer** mes compétences techniques
|
||||
- 🤝 **Contribuer** à la communauté
|
||||
|
||||
## Structure du site
|
||||
|
||||
### Documentation
|
||||
|
||||
La section documentation contient des guides techniques approfondis, des tutoriels et des références pour mes projets.
|
||||
|
||||
### Blog
|
||||
|
||||
Le blog présente des articles sur :
|
||||
- Résolution de problèmes techniques
|
||||
- Analyse d'architectures
|
||||
- Retours d'expérience
|
||||
- Nouvelles technologies et outils
|
||||
|
||||
## À propos
|
||||
|
||||
Ce site est construit avec [Docusaurus](https://docusaurus.io/), hébergé sur Cloudflare Pages et le code source est disponible sur [GitHub](https://github.com/Tellsanguis/blog_technique) et [Forgejo](https://forgejo.tellserv.fr).
|
||||
34
docs/notions/exemple.md
Normal file
34
docs/notions/exemple.md
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
---
|
||||
sidebar_position: 2
|
||||
---
|
||||
|
||||
# Exemple
|
||||
|
||||
Ceci est une page d'exemple dans la catégorie Notions.
|
||||
|
||||
## Description
|
||||
|
||||
Cette page démontre comment structurer du contenu dans une catégorie. Elle peut contenir :
|
||||
|
||||
- Des explications détaillées
|
||||
- Des exemples de code
|
||||
- Des diagrammes
|
||||
- Des références
|
||||
|
||||
## Utilisation
|
||||
|
||||
Vous pouvez dupliquer cette page pour créer de nouveaux articles dans cette catégorie.
|
||||
|
||||
### Configuration
|
||||
|
||||
Pour ajouter une nouvelle page, créez un fichier `.md` dans le dossier `docs/notions/` avec le front matter approprié :
|
||||
|
||||
```yaml
|
||||
---
|
||||
sidebar_position: 3
|
||||
---
|
||||
```
|
||||
|
||||
### Contenu
|
||||
|
||||
Le contenu peut être écrit en Markdown ou MDX pour inclure des composants React personnalisés.
|
||||
|
|
@ -1,7 +1,3 @@
|
|||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# Présentation
|
||||
|
||||
Présentation à venir.
|
||||
|
|
|
|||
|
|
@ -14,8 +14,11 @@ const config: Config = {
|
|||
projectName: 'blog_technique',
|
||||
|
||||
onBrokenLinks: 'throw',
|
||||
onBrokenAnchors: 'warn',
|
||||
|
||||
markdown: {
|
||||
format: 'mdx',
|
||||
mermaid: true,
|
||||
hooks: {
|
||||
onBrokenMarkdownLinks: 'warn',
|
||||
},
|
||||
|
|
@ -45,9 +48,18 @@ const config: Config = {
|
|||
docs: {
|
||||
sidebarPath: './sidebars.ts',
|
||||
editUrl: 'https://github.com/Tellsanguis/blog_technique/tree/main/',
|
||||
showLastUpdateAuthor: true,
|
||||
showLastUpdateTime: true,
|
||||
},
|
||||
blog: {
|
||||
showReadingTime: true,
|
||||
feedOptions: {
|
||||
type: ['rss', 'atom'],
|
||||
title: 'TellServ Tech Blog',
|
||||
description: 'Recherches et réflexions sur les défis techniques',
|
||||
copyright: `Copyright © ${new Date().getFullYear()} TellServ.`,
|
||||
language: 'fr',
|
||||
},
|
||||
editUrl: 'https://github.com/Tellsanguis/blog_technique/tree/main/',
|
||||
blogSidebarTitle: 'Articles récents',
|
||||
blogSidebarCount: 'ALL',
|
||||
|
|
@ -55,12 +67,28 @@ const config: Config = {
|
|||
theme: {
|
||||
customCss: './src/css/custom.css',
|
||||
},
|
||||
sitemap: {
|
||||
lastmod: 'date',
|
||||
changefreq: 'weekly',
|
||||
priority: 0.5,
|
||||
ignorePatterns: ['/tags/**'],
|
||||
filename: 'sitemap.xml',
|
||||
},
|
||||
} satisfies Preset.Options,
|
||||
],
|
||||
],
|
||||
|
||||
themeConfig: {
|
||||
image: 'img/docusaurus-social-card.jpg',
|
||||
metadata: [
|
||||
{name: 'keywords', content: 'homelab, kubernetes, docker, devops, opentofu, ansible, k3s, infrastructure as code'},
|
||||
{name: 'author', content: 'TellServ'},
|
||||
],
|
||||
colorMode: {
|
||||
defaultMode: 'light',
|
||||
disableSwitch: false,
|
||||
respectPrefersColorScheme: true,
|
||||
},
|
||||
navbar: {
|
||||
title: 'TellServ Tech Blog',
|
||||
logo: {
|
||||
|
|
@ -75,6 +103,10 @@ const config: Config = {
|
|||
label: 'Documentation',
|
||||
},
|
||||
{to: '/blog', label: 'Blog', position: 'left'},
|
||||
{
|
||||
type: 'localeDropdown',
|
||||
position: 'right',
|
||||
},
|
||||
{
|
||||
href: 'https://github.com/Tellsanguis/blog_technique',
|
||||
label: 'GitHub',
|
||||
|
|
@ -89,8 +121,8 @@ const config: Config = {
|
|||
title: 'Documentation',
|
||||
items: [
|
||||
{
|
||||
label: 'Introduction',
|
||||
to: '/docs/intro',
|
||||
label: 'Présentation',
|
||||
to: '/docs/presentation',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
@ -122,6 +154,11 @@ const config: Config = {
|
|||
prism: {
|
||||
theme: prismThemes.github,
|
||||
darkTheme: prismThemes.dracula,
|
||||
additionalLanguages: ['bash', 'yaml', 'hcl', 'docker'],
|
||||
},
|
||||
tableOfContents: {
|
||||
minHeadingLevel: 2,
|
||||
maxHeadingLevel: 5,
|
||||
},
|
||||
} satisfies Preset.ThemeConfig,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,60 @@
|
|||
---
|
||||
sidebar_position: 2
|
||||
---
|
||||
|
||||
# Example
|
||||
|
||||
This is an example page in the Current Homelab category.
|
||||
|
||||
## Description
|
||||
|
||||
This page demonstrates how to document a service or configuration of the current homelab.
|
||||
|
||||
## Docker Compose Configuration
|
||||
|
||||
Example service configuration:
|
||||
|
||||
```yaml
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
example-service:
|
||||
image: nginx:latest
|
||||
container_name: example
|
||||
ports:
|
||||
- "8080:80"
|
||||
volumes:
|
||||
- ./config:/etc/nginx/conf.d
|
||||
restart: unless-stopped
|
||||
```
|
||||
|
||||
## Ansible Playbook
|
||||
|
||||
Deployment example with Ansible:
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Deploy example service
|
||||
hosts: homelab
|
||||
become: yes
|
||||
|
||||
tasks:
|
||||
- name: Copy docker-compose file
|
||||
copy:
|
||||
src: docker-compose.yml
|
||||
dest: /opt/example/docker-compose.yml
|
||||
|
||||
- name: Start the service
|
||||
command: docker-compose up -d
|
||||
args:
|
||||
chdir: /opt/example
|
||||
```
|
||||
|
||||
## Maintenance
|
||||
|
||||
Important maintenance points:
|
||||
|
||||
- Regular backups
|
||||
- Docker image updates
|
||||
- Log monitoring
|
||||
- Restore testing
|
||||
|
|
@ -0,0 +1,153 @@
|
|||
---
|
||||
sidebar_position: 2
|
||||
---
|
||||
|
||||
# Example
|
||||
|
||||
This is an example page in the Future Homelab category.
|
||||
|
||||
## Description
|
||||
|
||||
This page demonstrates how to document Kubernetes configurations and deployments for the future homelab.
|
||||
|
||||
## Kubernetes Deployment
|
||||
|
||||
Example deployment manifest:
|
||||
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: example-app
|
||||
namespace: production
|
||||
spec:
|
||||
replicas: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
app: example
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: example
|
||||
spec:
|
||||
containers:
|
||||
- name: app
|
||||
image: nginx:latest
|
||||
ports:
|
||||
- containerPort: 80
|
||||
resources:
|
||||
limits:
|
||||
cpu: 100m
|
||||
memory: 128Mi
|
||||
requests:
|
||||
cpu: 50m
|
||||
memory: 64Mi
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: example-service
|
||||
namespace: production
|
||||
spec:
|
||||
selector:
|
||||
app: example
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 80
|
||||
type: ClusterIP
|
||||
```
|
||||
|
||||
## OpenTofu Configuration
|
||||
|
||||
Example infrastructure resource:
|
||||
|
||||
```hcl
|
||||
resource "kubernetes_namespace" "production" {
|
||||
metadata {
|
||||
name = "production"
|
||||
labels = {
|
||||
environment = "production"
|
||||
managed-by = "opentofu"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource "kubernetes_deployment" "example" {
|
||||
metadata {
|
||||
name = "example-app"
|
||||
namespace = kubernetes_namespace.production.metadata[0].name
|
||||
}
|
||||
|
||||
spec {
|
||||
replicas = 3
|
||||
|
||||
selector {
|
||||
match_labels = {
|
||||
app = "example"
|
||||
}
|
||||
}
|
||||
|
||||
template {
|
||||
metadata {
|
||||
labels = {
|
||||
app = "example"
|
||||
}
|
||||
}
|
||||
|
||||
spec {
|
||||
container {
|
||||
image = "nginx:latest"
|
||||
name = "app"
|
||||
|
||||
resources {
|
||||
limits = {
|
||||
cpu = "100m"
|
||||
memory = "128Mi"
|
||||
}
|
||||
requests = {
|
||||
cpu = "50m"
|
||||
memory = "64Mi"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## GitOps with ArgoCD
|
||||
|
||||
ArgoCD Application configuration:
|
||||
|
||||
```yaml
|
||||
apiVersion: argoproj.io/v1alpha1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: example-app
|
||||
namespace: argocd
|
||||
spec:
|
||||
project: default
|
||||
source:
|
||||
repoURL: https://forgejo.tellserv.fr/Tellsanguis/k8s-manifests.git
|
||||
targetRevision: HEAD
|
||||
path: apps/example
|
||||
destination:
|
||||
server: https://kubernetes.default.svc
|
||||
namespace: production
|
||||
syncPolicy:
|
||||
automated:
|
||||
prune: true
|
||||
selfHeal: true
|
||||
syncOptions:
|
||||
- CreateNamespace=true
|
||||
```
|
||||
|
||||
## Observability
|
||||
|
||||
Monitoring points for this service:
|
||||
|
||||
- Prometheus metrics exposed on `/metrics`
|
||||
- Logs aggregated in Loki
|
||||
- Distributed traces with Tempo
|
||||
- Alerts configured in Prometheus AlertManager
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# Introduction
|
||||
|
||||
Welcome to **TellServ Tech Blog**!
|
||||
|
||||
This technical blog documents my research, thoughts and solutions to technical challenges encountered in my projects. The goal is to:
|
||||
|
||||
- 📚 **Document** my learnings and discoveries
|
||||
- 🔍 **Share** my analyses and solutions
|
||||
- 💡 **Demonstrate** my technical skills
|
||||
- 🤝 **Contribute** to the community
|
||||
|
||||
## Site Structure
|
||||
|
||||
### Documentation
|
||||
|
||||
The documentation section contains in-depth technical guides, tutorials and references for my projects.
|
||||
|
||||
### Blog
|
||||
|
||||
The blog features articles on:
|
||||
- Technical problem solving
|
||||
- Architecture analysis
|
||||
- Experience feedback
|
||||
- New technologies and tools
|
||||
|
||||
## About
|
||||
|
||||
This site is built with [Docusaurus](https://docusaurus.io/), hosted on Cloudflare Pages and the source code is available on [GitHub](https://github.com/Tellsanguis/blog_technique) and [Forgejo](https://forgejo.tellserv.fr).
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
---
|
||||
sidebar_position: 2
|
||||
---
|
||||
|
||||
# Example
|
||||
|
||||
This is an example page in the Concepts category.
|
||||
|
||||
## Description
|
||||
|
||||
This page demonstrates how to structure content in a category. It can contain:
|
||||
|
||||
- Detailed explanations
|
||||
- Code examples
|
||||
- Diagrams
|
||||
- References
|
||||
|
||||
## Usage
|
||||
|
||||
You can duplicate this page to create new articles in this category.
|
||||
|
||||
### Configuration
|
||||
|
||||
To add a new page, create a `.md` file in the `docs/notions/` folder with the appropriate front matter:
|
||||
|
||||
```yaml
|
||||
---
|
||||
sidebar_position: 3
|
||||
---
|
||||
```
|
||||
|
||||
### Content
|
||||
|
||||
Content can be written in Markdown or MDX to include custom React components.
|
||||
|
|
@ -1,7 +1,3 @@
|
|||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# About Me
|
||||
|
||||
Coming soon.
|
||||
|
|
|
|||
34
sidebars.ts
34
sidebars.ts
|
|
@ -2,34 +2,48 @@ import type {SidebarsConfig} from '@docusaurus/plugin-content-docs';
|
|||
|
||||
const sidebars: SidebarsConfig = {
|
||||
tutorialSidebar: [
|
||||
'intro',
|
||||
'presentation',
|
||||
{
|
||||
type: 'category',
|
||||
label: 'Notions',
|
||||
link: {
|
||||
type: 'doc',
|
||||
id: 'notions/index',
|
||||
type: 'generated-index',
|
||||
title: 'Notions',
|
||||
description: 'Concepts et notions techniques fondamentales utilisées dans mes projets.',
|
||||
slug: '/category/notions',
|
||||
},
|
||||
items: [],
|
||||
items: [
|
||||
'notions/index',
|
||||
'notions/exemple',
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'category',
|
||||
label: 'Homelab actuel - Docker Compose & Ansible',
|
||||
link: {
|
||||
type: 'doc',
|
||||
id: 'homelab-actuel/index',
|
||||
type: 'generated-index',
|
||||
title: 'Homelab actuel - Docker Compose & Ansible',
|
||||
description: 'Documentation de mon infrastructure homelab actuelle, basée sur Docker Compose et Ansible.',
|
||||
slug: '/category/homelab-actuel',
|
||||
},
|
||||
items: [],
|
||||
items: [
|
||||
'homelab-actuel/index',
|
||||
'homelab-actuel/exemple',
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'category',
|
||||
label: 'Futur Homelab - OpenTofu, K3S, Ansible & DevOps',
|
||||
link: {
|
||||
type: 'doc',
|
||||
id: 'homelab-futur/index',
|
||||
type: 'generated-index',
|
||||
title: 'Futur Homelab - OpenTofu, K3S, Ansible & DevOps',
|
||||
description: 'Documentation de la migration vers une infrastructure moderne basée sur Kubernetes et les pratiques DevOps.',
|
||||
slug: '/category/homelab-futur',
|
||||
},
|
||||
items: [],
|
||||
items: [
|
||||
'homelab-futur/index',
|
||||
'homelab-futur/exemple',
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ function HomepageHeader() {
|
|||
<div className={styles.buttons}>
|
||||
<Link
|
||||
className="button button--secondary button--lg"
|
||||
to="/docs/intro">
|
||||
to="/docs/presentation">
|
||||
Découvrir la documentation
|
||||
</Link>
|
||||
<Link
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue