feat: Implement comprehensive database schema with new models, CRUD operations, and documentation for host metrics, Docker management, and terminal sessions, while removing old test files.
Tests / Backend Tests (Python) (3.10) (push) Has been cancelled
Tests / Backend Tests (Python) (3.11) (push) Has been cancelled
Tests / Backend Tests (Python) (3.12) (push) Has been cancelled
Tests / Frontend Tests (JS) (push) Has been cancelled
Tests / Integration Tests (push) Has been cancelled
Tests / All Tests Passed (push) Has been cancelled
Tests / Backend Tests (Python) (3.10) (push) Has been cancelled
Tests / Backend Tests (Python) (3.11) (push) Has been cancelled
Tests / Backend Tests (Python) (3.12) (push) Has been cancelled
Tests / Frontend Tests (JS) (push) Has been cancelled
Tests / Integration Tests (push) Has been cancelled
Tests / All Tests Passed (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,716 @@
|
||||
# Documentation du Modèle de Données (Base de Données)
|
||||
|
||||
Cette documentation a été générée automatiquement à partir des modèles SQLAlchemy.
|
||||
|
||||
## 1. Diagramme Entité-Association (ERD)
|
||||
|
||||
Le schéma ci-dessous montre l'architecture des tables et leurs relations :
|
||||
|
||||
```mermaid
|
||||
erDiagram
|
||||
alerts {
|
||||
INTEGER id PK
|
||||
INTEGER user_id FK "nullable"
|
||||
VARCHAR category
|
||||
VARCHAR level "nullable"
|
||||
VARCHAR title "nullable"
|
||||
TEXT message
|
||||
VARCHAR source "nullable"
|
||||
JSON details "nullable"
|
||||
DATETIME read_at "nullable"
|
||||
DATETIME created_at
|
||||
}
|
||||
app_settings {
|
||||
VARCHAR key PK
|
||||
TEXT value "nullable"
|
||||
DATETIME created_at
|
||||
DATETIME updated_at
|
||||
}
|
||||
bootstrap_status {
|
||||
INTEGER id PK
|
||||
VARCHAR host_id FK
|
||||
VARCHAR status
|
||||
VARCHAR automation_user "nullable"
|
||||
DATETIME last_attempt "nullable"
|
||||
TEXT error_message "nullable"
|
||||
DATETIME created_at
|
||||
}
|
||||
container_customizations {
|
||||
INTEGER id PK
|
||||
INTEGER user_id FK "nullable"
|
||||
VARCHAR host_id FK
|
||||
VARCHAR container_id
|
||||
VARCHAR icon_key "nullable"
|
||||
VARCHAR icon_color "nullable"
|
||||
VARCHAR bg_color "nullable"
|
||||
DATETIME created_at
|
||||
DATETIME updated_at
|
||||
}
|
||||
docker_alerts {
|
||||
INTEGER id PK
|
||||
VARCHAR host_id FK
|
||||
VARCHAR container_name
|
||||
VARCHAR severity
|
||||
VARCHAR state
|
||||
TEXT message "nullable"
|
||||
DATETIME opened_at
|
||||
DATETIME closed_at "nullable"
|
||||
DATETIME acknowledged_at "nullable"
|
||||
VARCHAR acknowledged_by "nullable"
|
||||
DATETIME last_notified_at "nullable"
|
||||
}
|
||||
docker_containers {
|
||||
INTEGER id PK
|
||||
VARCHAR host_id FK
|
||||
VARCHAR container_id
|
||||
VARCHAR name
|
||||
VARCHAR image "nullable"
|
||||
VARCHAR state
|
||||
VARCHAR status "nullable"
|
||||
VARCHAR health "nullable"
|
||||
DATETIME created_at "nullable"
|
||||
JSON ports "nullable"
|
||||
JSON labels "nullable"
|
||||
VARCHAR compose_project "nullable"
|
||||
DATETIME last_update_at
|
||||
}
|
||||
docker_images {
|
||||
INTEGER id PK
|
||||
VARCHAR host_id FK
|
||||
VARCHAR image_id
|
||||
JSON repo_tags "nullable"
|
||||
BIGINT size "nullable"
|
||||
DATETIME created "nullable"
|
||||
DATETIME last_update_at
|
||||
}
|
||||
docker_volumes {
|
||||
INTEGER id PK
|
||||
VARCHAR host_id FK
|
||||
VARCHAR name
|
||||
VARCHAR driver "nullable"
|
||||
TEXT mountpoint "nullable"
|
||||
VARCHAR scope "nullable"
|
||||
DATETIME last_update_at
|
||||
}
|
||||
favorite_containers {
|
||||
INTEGER id PK
|
||||
INTEGER user_id FK "nullable"
|
||||
INTEGER docker_container_id FK
|
||||
INTEGER group_id FK "nullable"
|
||||
DATETIME created_at
|
||||
}
|
||||
favorite_groups {
|
||||
INTEGER id PK
|
||||
INTEGER user_id FK "nullable"
|
||||
VARCHAR name
|
||||
INTEGER sort_order
|
||||
VARCHAR color "nullable"
|
||||
VARCHAR icon_key "nullable"
|
||||
DATETIME created_at
|
||||
DATETIME updated_at
|
||||
}
|
||||
host_metrics {
|
||||
INTEGER id PK
|
||||
VARCHAR host_id FK
|
||||
VARCHAR metric_type
|
||||
INTEGER cpu_count "nullable"
|
||||
VARCHAR cpu_model "nullable"
|
||||
INTEGER cpu_cores "nullable"
|
||||
INTEGER cpu_threads "nullable"
|
||||
INTEGER cpu_threads_per_core "nullable"
|
||||
INTEGER cpu_sockets "nullable"
|
||||
FLOAT cpu_mhz "nullable"
|
||||
FLOAT cpu_max_mhz "nullable"
|
||||
FLOAT cpu_min_mhz "nullable"
|
||||
FLOAT cpu_load_1m "nullable"
|
||||
FLOAT cpu_load_5m "nullable"
|
||||
FLOAT cpu_load_15m "nullable"
|
||||
FLOAT cpu_usage_percent "nullable"
|
||||
FLOAT cpu_temperature "nullable"
|
||||
INTEGER memory_total_mb "nullable"
|
||||
INTEGER memory_used_mb "nullable"
|
||||
INTEGER memory_free_mb "nullable"
|
||||
FLOAT memory_usage_percent "nullable"
|
||||
INTEGER swap_total_mb "nullable"
|
||||
INTEGER swap_used_mb "nullable"
|
||||
FLOAT swap_usage_percent "nullable"
|
||||
JSON disk_info "nullable"
|
||||
JSON disk_devices
|
||||
FLOAT disk_root_total_gb "nullable"
|
||||
FLOAT disk_root_used_gb "nullable"
|
||||
FLOAT disk_root_usage_percent "nullable"
|
||||
JSON lvm_info "nullable"
|
||||
JSON zfs_info "nullable"
|
||||
JSON storage_details "nullable"
|
||||
VARCHAR os_name "nullable"
|
||||
VARCHAR os_version "nullable"
|
||||
VARCHAR kernel_version "nullable"
|
||||
VARCHAR hostname "nullable"
|
||||
INTEGER uptime_seconds "nullable"
|
||||
VARCHAR uptime_human "nullable"
|
||||
JSON network_info "nullable"
|
||||
JSON raw_data "nullable"
|
||||
VARCHAR collection_source "nullable"
|
||||
INTEGER collection_duration_ms "nullable"
|
||||
TEXT error_message "nullable"
|
||||
DATETIME collected_at
|
||||
DATETIME created_at
|
||||
}
|
||||
hosts {
|
||||
VARCHAR id PK
|
||||
VARCHAR name
|
||||
VARCHAR ip_address
|
||||
VARCHAR status
|
||||
VARCHAR ansible_group "nullable"
|
||||
DATETIME last_seen "nullable"
|
||||
BOOLEAN reachable
|
||||
DATETIME created_at
|
||||
DATETIME updated_at
|
||||
DATETIME deleted_at "nullable"
|
||||
BOOLEAN docker_enabled
|
||||
VARCHAR docker_version "nullable"
|
||||
VARCHAR docker_status "nullable"
|
||||
DATETIME docker_last_collect_at "nullable"
|
||||
}
|
||||
logs {
|
||||
INTEGER id PK
|
||||
VARCHAR level
|
||||
VARCHAR source "nullable"
|
||||
TEXT message
|
||||
JSON details "nullable"
|
||||
VARCHAR host_id "nullable"
|
||||
VARCHAR task_id "nullable"
|
||||
VARCHAR schedule_id "nullable"
|
||||
DATETIME created_at
|
||||
}
|
||||
playbook_lint_results {
|
||||
INTEGER id PK
|
||||
VARCHAR filename
|
||||
INTEGER quality_score
|
||||
INTEGER total_issues
|
||||
INTEGER errors_count
|
||||
INTEGER warnings_count
|
||||
INTEGER execution_time_ms
|
||||
TEXT issues_json "nullable"
|
||||
TEXT raw_output "nullable"
|
||||
DATETIME created_at
|
||||
DATETIME updated_at
|
||||
}
|
||||
schedule_runs {
|
||||
INTEGER id PK
|
||||
VARCHAR schedule_id FK
|
||||
VARCHAR task_id FK "nullable"
|
||||
VARCHAR status
|
||||
DATETIME started_at
|
||||
DATETIME completed_at "nullable"
|
||||
FLOAT duration "nullable"
|
||||
INTEGER hosts_impacted "nullable"
|
||||
TEXT error_message "nullable"
|
||||
TEXT output "nullable"
|
||||
DATETIME created_at
|
||||
}
|
||||
schedules {
|
||||
VARCHAR id PK
|
||||
VARCHAR name
|
||||
TEXT description "nullable"
|
||||
VARCHAR playbook
|
||||
VARCHAR target_type "nullable"
|
||||
VARCHAR target
|
||||
JSON extra_vars "nullable"
|
||||
VARCHAR schedule_type
|
||||
DATETIME schedule_time "nullable"
|
||||
VARCHAR recurrence_type "nullable"
|
||||
VARCHAR recurrence_time "nullable"
|
||||
TEXT recurrence_days "nullable"
|
||||
VARCHAR cron_expression "nullable"
|
||||
VARCHAR timezone "nullable"
|
||||
DATETIME start_at "nullable"
|
||||
DATETIME end_at "nullable"
|
||||
BOOLEAN enabled
|
||||
TEXT tags "nullable"
|
||||
DATETIME next_run "nullable"
|
||||
DATETIME last_run "nullable"
|
||||
VARCHAR last_status "nullable"
|
||||
INTEGER retry_on_failure "nullable"
|
||||
INTEGER timeout "nullable"
|
||||
VARCHAR notification_type "nullable"
|
||||
INTEGER run_count "nullable"
|
||||
INTEGER success_count "nullable"
|
||||
INTEGER failure_count "nullable"
|
||||
DATETIME created_at
|
||||
DATETIME updated_at
|
||||
DATETIME deleted_at "nullable"
|
||||
}
|
||||
tasks {
|
||||
VARCHAR id PK
|
||||
VARCHAR action
|
||||
VARCHAR target
|
||||
VARCHAR status
|
||||
VARCHAR playbook "nullable"
|
||||
DATETIME started_at "nullable"
|
||||
DATETIME completed_at "nullable"
|
||||
TEXT error_message "nullable"
|
||||
JSON result_data "nullable"
|
||||
DATETIME created_at
|
||||
}
|
||||
terminal_command_logs {
|
||||
INTEGER id PK
|
||||
DATETIME created_at
|
||||
VARCHAR host_id FK
|
||||
INTEGER user_id FK "nullable"
|
||||
VARCHAR terminal_session_id "nullable"
|
||||
TEXT command
|
||||
VARCHAR command_hash
|
||||
VARCHAR source
|
||||
BOOLEAN is_pinned
|
||||
BOOLEAN is_blocked
|
||||
VARCHAR blocked_reason "nullable"
|
||||
VARCHAR username "nullable"
|
||||
VARCHAR host_name "nullable"
|
||||
}
|
||||
terminal_sessions {
|
||||
VARCHAR id PK
|
||||
VARCHAR host_id
|
||||
VARCHAR host_name
|
||||
VARCHAR host_ip
|
||||
INTEGER user_id "nullable"
|
||||
VARCHAR username "nullable"
|
||||
VARCHAR token_hash
|
||||
INTEGER ttyd_port
|
||||
INTEGER ttyd_pid "nullable"
|
||||
VARCHAR mode
|
||||
VARCHAR status
|
||||
VARCHAR reason_closed "nullable"
|
||||
DATETIME created_at
|
||||
DATETIME last_seen_at
|
||||
DATETIME expires_at
|
||||
DATETIME closed_at "nullable"
|
||||
}
|
||||
users {
|
||||
INTEGER id PK
|
||||
VARCHAR username
|
||||
VARCHAR email "nullable"
|
||||
VARCHAR hashed_password
|
||||
VARCHAR role
|
||||
BOOLEAN is_active
|
||||
BOOLEAN is_superuser
|
||||
VARCHAR display_name "nullable"
|
||||
DATETIME created_at
|
||||
DATETIME updated_at
|
||||
DATETIME last_login "nullable"
|
||||
DATETIME password_changed_at "nullable"
|
||||
DATETIME deleted_at "nullable"
|
||||
}
|
||||
users ||--o{ alerts : "user_id"
|
||||
hosts ||--o{ bootstrap_status : "host_id"
|
||||
users ||--o{ container_customizations : "user_id"
|
||||
hosts ||--o{ container_customizations : "host_id"
|
||||
hosts ||--o{ docker_alerts : "host_id"
|
||||
hosts ||--o{ docker_containers : "host_id"
|
||||
hosts ||--o{ docker_images : "host_id"
|
||||
hosts ||--o{ docker_volumes : "host_id"
|
||||
users ||--o{ favorite_containers : "user_id"
|
||||
docker_containers ||--o{ favorite_containers : "docker_container_id"
|
||||
favorite_groups ||--o{ favorite_containers : "group_id"
|
||||
users ||--o{ favorite_groups : "user_id"
|
||||
hosts ||--o{ host_metrics : "host_id"
|
||||
schedules ||--o{ schedule_runs : "schedule_id"
|
||||
tasks ||--o{ schedule_runs : "task_id"
|
||||
hosts ||--o{ terminal_command_logs : "host_id"
|
||||
users ||--o{ terminal_command_logs : "user_id"
|
||||
```
|
||||
|
||||
## 2. Dictionnaire de Données (Tables)
|
||||
|
||||
### Table : `alerts`
|
||||
|
||||
|
||||
| Colonne | Type | Clé Primaire | Clé Étrangère | Nullable | Défaut |
|
||||
|---------|------|--------------|---------------|----------|--------|
|
||||
| `id` | `INTEGER` | ✅ Oui | - | **Non** | - |
|
||||
| `user_id` | `INTEGER` | - | 🔗 `users.id` | Oui | - |
|
||||
| `category` | `VARCHAR(50)` | - | - | **Non** | - |
|
||||
| `level` | `VARCHAR(20)` | - | - | Oui | - |
|
||||
| `title` | `VARCHAR(255)` | - | - | Oui | - |
|
||||
| `message` | `TEXT` | - | - | **Non** | - |
|
||||
| `source` | `VARCHAR(50)` | - | - | Oui | - |
|
||||
| `details` | `JSON` | - | - | Oui | - |
|
||||
| `read_at` | `DATETIME` | - | - | Oui | - |
|
||||
| `created_at` | `DATETIME` | - | - | **Non** | `now()` |
|
||||
|
||||
|
||||
### Table : `app_settings`
|
||||
|
||||
|
||||
| Colonne | Type | Clé Primaire | Clé Étrangère | Nullable | Défaut |
|
||||
|---------|------|--------------|---------------|----------|--------|
|
||||
| `key` | `VARCHAR(100)` | ✅ Oui | - | **Non** | - |
|
||||
| `value` | `TEXT` | - | - | Oui | - |
|
||||
| `created_at` | `DATETIME` | - | - | **Non** | `now()` |
|
||||
| `updated_at` | `DATETIME` | - | - | **Non** | `now()` |
|
||||
|
||||
|
||||
### Table : `bootstrap_status`
|
||||
|
||||
|
||||
| Colonne | Type | Clé Primaire | Clé Étrangère | Nullable | Défaut |
|
||||
|---------|------|--------------|---------------|----------|--------|
|
||||
| `id` | `INTEGER` | ✅ Oui | - | **Non** | - |
|
||||
| `host_id` | `VARCHAR(50)` | - | 🔗 `hosts.id` | **Non** | - |
|
||||
| `status` | `VARCHAR(50)` | - | - | **Non** | - |
|
||||
| `automation_user` | `VARCHAR(50)` | - | - | Oui | - |
|
||||
| `last_attempt` | `DATETIME` | - | - | Oui | - |
|
||||
| `error_message` | `TEXT` | - | - | Oui | - |
|
||||
| `created_at` | `DATETIME` | - | - | **Non** | `now()` |
|
||||
|
||||
|
||||
### Table : `container_customizations`
|
||||
|
||||
|
||||
| Colonne | Type | Clé Primaire | Clé Étrangère | Nullable | Défaut |
|
||||
|---------|------|--------------|---------------|----------|--------|
|
||||
| `id` | `INTEGER` | ✅ Oui | - | **Non** | - |
|
||||
| `user_id` | `INTEGER` | - | 🔗 `users.id` | Oui | - |
|
||||
| `host_id` | `VARCHAR(50)` | - | 🔗 `hosts.id` | **Non** | - |
|
||||
| `container_id` | `VARCHAR(64)` | - | - | **Non** | - |
|
||||
| `icon_key` | `VARCHAR(100)` | - | - | Oui | - |
|
||||
| `icon_color` | `VARCHAR(20)` | - | - | Oui | - |
|
||||
| `bg_color` | `VARCHAR(20)` | - | - | Oui | - |
|
||||
| `created_at` | `DATETIME` | - | - | **Non** | `now()` |
|
||||
| `updated_at` | `DATETIME` | - | - | **Non** | `now()` |
|
||||
|
||||
|
||||
### Table : `docker_alerts`
|
||||
|
||||
|
||||
| Colonne | Type | Clé Primaire | Clé Étrangère | Nullable | Défaut |
|
||||
|---------|------|--------------|---------------|----------|--------|
|
||||
| `id` | `INTEGER` | ✅ Oui | - | **Non** | - |
|
||||
| `host_id` | `VARCHAR(50)` | - | 🔗 `hosts.id` | **Non** | - |
|
||||
| `container_name` | `VARCHAR(255)` | - | - | **Non** | - |
|
||||
| `severity` | `VARCHAR(20)` | - | - | **Non** | `warning` |
|
||||
| `state` | `VARCHAR(20)` | - | - | **Non** | `open` |
|
||||
| `message` | `TEXT` | - | - | Oui | - |
|
||||
| `opened_at` | `DATETIME` | - | - | **Non** | `now()` |
|
||||
| `closed_at` | `DATETIME` | - | - | Oui | - |
|
||||
| `acknowledged_at` | `DATETIME` | - | - | Oui | - |
|
||||
| `acknowledged_by` | `VARCHAR(100)` | - | - | Oui | - |
|
||||
| `last_notified_at` | `DATETIME` | - | - | Oui | - |
|
||||
|
||||
|
||||
### Table : `docker_containers`
|
||||
|
||||
|
||||
| Colonne | Type | Clé Primaire | Clé Étrangère | Nullable | Défaut |
|
||||
|---------|------|--------------|---------------|----------|--------|
|
||||
| `id` | `INTEGER` | ✅ Oui | - | **Non** | - |
|
||||
| `host_id` | `VARCHAR(50)` | - | 🔗 `hosts.id` | **Non** | - |
|
||||
| `container_id` | `VARCHAR(64)` | - | - | **Non** | - |
|
||||
| `name` | `VARCHAR(255)` | - | - | **Non** | - |
|
||||
| `image` | `VARCHAR(255)` | - | - | Oui | - |
|
||||
| `state` | `VARCHAR(20)` | - | - | **Non** | `unknown` |
|
||||
| `status` | `VARCHAR(255)` | - | - | Oui | - |
|
||||
| `health` | `VARCHAR(20)` | - | - | Oui | - |
|
||||
| `created_at` | `DATETIME` | - | - | Oui | - |
|
||||
| `ports` | `JSON` | - | - | Oui | - |
|
||||
| `labels` | `JSON` | - | - | Oui | - |
|
||||
| `compose_project` | `VARCHAR(255)` | - | - | Oui | - |
|
||||
| `last_update_at` | `DATETIME` | - | - | **Non** | `now()` |
|
||||
|
||||
|
||||
### Table : `docker_images`
|
||||
|
||||
|
||||
| Colonne | Type | Clé Primaire | Clé Étrangère | Nullable | Défaut |
|
||||
|---------|------|--------------|---------------|----------|--------|
|
||||
| `id` | `INTEGER` | ✅ Oui | - | **Non** | - |
|
||||
| `host_id` | `VARCHAR(50)` | - | 🔗 `hosts.id` | **Non** | - |
|
||||
| `image_id` | `VARCHAR(64)` | - | - | **Non** | - |
|
||||
| `repo_tags` | `JSON` | - | - | Oui | - |
|
||||
| `size` | `BIGINT` | - | - | Oui | - |
|
||||
| `created` | `DATETIME` | - | - | Oui | - |
|
||||
| `last_update_at` | `DATETIME` | - | - | **Non** | `now()` |
|
||||
|
||||
|
||||
### Table : `docker_volumes`
|
||||
|
||||
|
||||
| Colonne | Type | Clé Primaire | Clé Étrangère | Nullable | Défaut |
|
||||
|---------|------|--------------|---------------|----------|--------|
|
||||
| `id` | `INTEGER` | ✅ Oui | - | **Non** | - |
|
||||
| `host_id` | `VARCHAR(50)` | - | 🔗 `hosts.id` | **Non** | - |
|
||||
| `name` | `VARCHAR(255)` | - | - | **Non** | - |
|
||||
| `driver` | `VARCHAR(50)` | - | - | Oui | - |
|
||||
| `mountpoint` | `TEXT` | - | - | Oui | - |
|
||||
| `scope` | `VARCHAR(20)` | - | - | Oui | - |
|
||||
| `last_update_at` | `DATETIME` | - | - | **Non** | `now()` |
|
||||
|
||||
|
||||
### Table : `favorite_containers`
|
||||
|
||||
|
||||
| Colonne | Type | Clé Primaire | Clé Étrangère | Nullable | Défaut |
|
||||
|---------|------|--------------|---------------|----------|--------|
|
||||
| `id` | `INTEGER` | ✅ Oui | - | **Non** | - |
|
||||
| `user_id` | `INTEGER` | - | 🔗 `users.id` | Oui | - |
|
||||
| `docker_container_id` | `INTEGER` | - | 🔗 `docker_containers.id` | **Non** | - |
|
||||
| `group_id` | `INTEGER` | - | 🔗 `favorite_groups.id` | Oui | - |
|
||||
| `created_at` | `DATETIME` | - | - | **Non** | `now()` |
|
||||
|
||||
|
||||
### Table : `favorite_groups`
|
||||
|
||||
|
||||
| Colonne | Type | Clé Primaire | Clé Étrangère | Nullable | Défaut |
|
||||
|---------|------|--------------|---------------|----------|--------|
|
||||
| `id` | `INTEGER` | ✅ Oui | - | **Non** | - |
|
||||
| `user_id` | `INTEGER` | - | 🔗 `users.id` | Oui | - |
|
||||
| `name` | `VARCHAR(100)` | - | - | **Non** | - |
|
||||
| `sort_order` | `INTEGER` | - | - | **Non** | `0` |
|
||||
| `color` | `VARCHAR(20)` | - | - | Oui | - |
|
||||
| `icon_key` | `VARCHAR(100)` | - | - | Oui | - |
|
||||
| `created_at` | `DATETIME` | - | - | **Non** | `now()` |
|
||||
| `updated_at` | `DATETIME` | - | - | **Non** | `now()` |
|
||||
|
||||
|
||||
### Table : `host_metrics`
|
||||
|
||||
|
||||
| Colonne | Type | Clé Primaire | Clé Étrangère | Nullable | Défaut |
|
||||
|---------|------|--------------|---------------|----------|--------|
|
||||
| `id` | `INTEGER` | ✅ Oui | - | **Non** | - |
|
||||
| `host_id` | `VARCHAR(50)` | - | 🔗 `hosts.id` | **Non** | - |
|
||||
| `metric_type` | `VARCHAR(50)` | - | - | **Non** | - |
|
||||
| `cpu_count` | `INTEGER` | - | - | Oui | - |
|
||||
| `cpu_model` | `VARCHAR(200)` | - | - | Oui | - |
|
||||
| `cpu_cores` | `INTEGER` | - | - | Oui | - |
|
||||
| `cpu_threads` | `INTEGER` | - | - | Oui | - |
|
||||
| `cpu_threads_per_core` | `INTEGER` | - | - | Oui | - |
|
||||
| `cpu_sockets` | `INTEGER` | - | - | Oui | - |
|
||||
| `cpu_mhz` | `FLOAT` | - | - | Oui | - |
|
||||
| `cpu_max_mhz` | `FLOAT` | - | - | Oui | - |
|
||||
| `cpu_min_mhz` | `FLOAT` | - | - | Oui | - |
|
||||
| `cpu_load_1m` | `FLOAT` | - | - | Oui | - |
|
||||
| `cpu_load_5m` | `FLOAT` | - | - | Oui | - |
|
||||
| `cpu_load_15m` | `FLOAT` | - | - | Oui | - |
|
||||
| `cpu_usage_percent` | `FLOAT` | - | - | Oui | - |
|
||||
| `cpu_temperature` | `FLOAT` | - | - | Oui | - |
|
||||
| `memory_total_mb` | `INTEGER` | - | - | Oui | - |
|
||||
| `memory_used_mb` | `INTEGER` | - | - | Oui | - |
|
||||
| `memory_free_mb` | `INTEGER` | - | - | Oui | - |
|
||||
| `memory_usage_percent` | `FLOAT` | - | - | Oui | - |
|
||||
| `swap_total_mb` | `INTEGER` | - | - | Oui | - |
|
||||
| `swap_used_mb` | `INTEGER` | - | - | Oui | - |
|
||||
| `swap_usage_percent` | `FLOAT` | - | - | Oui | - |
|
||||
| `disk_info` | `JSON` | - | - | Oui | - |
|
||||
| `disk_devices` | `JSON` | - | - | **Non** | - |
|
||||
| `disk_root_total_gb` | `FLOAT` | - | - | Oui | - |
|
||||
| `disk_root_used_gb` | `FLOAT` | - | - | Oui | - |
|
||||
| `disk_root_usage_percent` | `FLOAT` | - | - | Oui | - |
|
||||
| `lvm_info` | `JSON` | - | - | Oui | - |
|
||||
| `zfs_info` | `JSON` | - | - | Oui | - |
|
||||
| `storage_details` | `JSON` | - | - | Oui | - |
|
||||
| `os_name` | `VARCHAR(100)` | - | - | Oui | - |
|
||||
| `os_version` | `VARCHAR(100)` | - | - | Oui | - |
|
||||
| `kernel_version` | `VARCHAR(100)` | - | - | Oui | - |
|
||||
| `hostname` | `VARCHAR(200)` | - | - | Oui | - |
|
||||
| `uptime_seconds` | `INTEGER` | - | - | Oui | - |
|
||||
| `uptime_human` | `VARCHAR(100)` | - | - | Oui | - |
|
||||
| `network_info` | `JSON` | - | - | Oui | - |
|
||||
| `raw_data` | `JSON` | - | - | Oui | - |
|
||||
| `collection_source` | `VARCHAR(100)` | - | - | Oui | - |
|
||||
| `collection_duration_ms` | `INTEGER` | - | - | Oui | - |
|
||||
| `error_message` | `TEXT` | - | - | Oui | - |
|
||||
| `collected_at` | `DATETIME` | - | - | **Non** | `now()` |
|
||||
| `created_at` | `DATETIME` | - | - | **Non** | `now()` |
|
||||
|
||||
|
||||
### Table : `hosts`
|
||||
|
||||
|
||||
| Colonne | Type | Clé Primaire | Clé Étrangère | Nullable | Défaut |
|
||||
|---------|------|--------------|---------------|----------|--------|
|
||||
| `id` | `VARCHAR(50)` | ✅ Oui | - | **Non** | - |
|
||||
| `name` | `VARCHAR(255)` | - | - | **Non** | - |
|
||||
| `ip_address` | `VARCHAR(50)` | - | - | **Non** | - |
|
||||
| `status` | `VARCHAR(50)` | - | - | **Non** | `'unknown'` |
|
||||
| `ansible_group` | `VARCHAR(50)` | - | - | Oui | - |
|
||||
| `last_seen` | `DATETIME` | - | - | Oui | - |
|
||||
| `reachable` | `BOOLEAN` | - | - | **Non** | `0` |
|
||||
| `created_at` | `DATETIME` | - | - | **Non** | `now()` |
|
||||
| `updated_at` | `DATETIME` | - | - | **Non** | `now()` |
|
||||
| `deleted_at` | `DATETIME` | - | - | Oui | - |
|
||||
| `docker_enabled` | `BOOLEAN` | - | - | **Non** | `0` |
|
||||
| `docker_version` | `VARCHAR(50)` | - | - | Oui | - |
|
||||
| `docker_status` | `VARCHAR(20)` | - | - | Oui | - |
|
||||
| `docker_last_collect_at` | `DATETIME` | - | - | Oui | - |
|
||||
|
||||
|
||||
### Table : `logs`
|
||||
|
||||
|
||||
| Colonne | Type | Clé Primaire | Clé Étrangère | Nullable | Défaut |
|
||||
|---------|------|--------------|---------------|----------|--------|
|
||||
| `id` | `INTEGER` | ✅ Oui | - | **Non** | - |
|
||||
| `level` | `VARCHAR(50)` | - | - | **Non** | - |
|
||||
| `source` | `VARCHAR(255)` | - | - | Oui | - |
|
||||
| `message` | `TEXT` | - | - | **Non** | - |
|
||||
| `details` | `JSON` | - | - | Oui | - |
|
||||
| `host_id` | `VARCHAR(50)` | - | - | Oui | - |
|
||||
| `task_id` | `VARCHAR(50)` | - | - | Oui | - |
|
||||
| `schedule_id` | `VARCHAR(50)` | - | - | Oui | - |
|
||||
| `created_at` | `DATETIME` | - | - | **Non** | `now()` |
|
||||
|
||||
|
||||
### Table : `playbook_lint_results`
|
||||
|
||||
|
||||
| Colonne | Type | Clé Primaire | Clé Étrangère | Nullable | Défaut |
|
||||
|---------|------|--------------|---------------|----------|--------|
|
||||
| `id` | `INTEGER` | ✅ Oui | - | **Non** | - |
|
||||
| `filename` | `VARCHAR(255)` | - | - | **Non** | - |
|
||||
| `quality_score` | `INTEGER` | - | - | **Non** | `100` |
|
||||
| `total_issues` | `INTEGER` | - | - | **Non** | `0` |
|
||||
| `errors_count` | `INTEGER` | - | - | **Non** | `0` |
|
||||
| `warnings_count` | `INTEGER` | - | - | **Non** | `0` |
|
||||
| `execution_time_ms` | `INTEGER` | - | - | **Non** | `0` |
|
||||
| `issues_json` | `TEXT` | - | - | Oui | - |
|
||||
| `raw_output` | `TEXT` | - | - | Oui | - |
|
||||
| `created_at` | `DATETIME` | - | - | **Non** | *(auto generate)* |
|
||||
| `updated_at` | `DATETIME` | - | - | **Non** | *(auto generate)* |
|
||||
|
||||
|
||||
### Table : `schedule_runs`
|
||||
|
||||
|
||||
| Colonne | Type | Clé Primaire | Clé Étrangère | Nullable | Défaut |
|
||||
|---------|------|--------------|---------------|----------|--------|
|
||||
| `id` | `INTEGER` | ✅ Oui | - | **Non** | - |
|
||||
| `schedule_id` | `VARCHAR(50)` | - | 🔗 `schedules.id` | **Non** | - |
|
||||
| `task_id` | `VARCHAR(50)` | - | 🔗 `tasks.id` | Oui | - |
|
||||
| `status` | `VARCHAR(50)` | - | - | **Non** | - |
|
||||
| `started_at` | `DATETIME` | - | - | **Non** | - |
|
||||
| `completed_at` | `DATETIME` | - | - | Oui | - |
|
||||
| `duration` | `FLOAT` | - | - | Oui | - |
|
||||
| `hosts_impacted` | `INTEGER` | - | - | Oui | `0` |
|
||||
| `error_message` | `TEXT` | - | - | Oui | - |
|
||||
| `output` | `TEXT` | - | - | Oui | - |
|
||||
| `created_at` | `DATETIME` | - | - | **Non** | `now()` |
|
||||
|
||||
|
||||
### Table : `schedules`
|
||||
|
||||
|
||||
| Colonne | Type | Clé Primaire | Clé Étrangère | Nullable | Défaut |
|
||||
|---------|------|--------------|---------------|----------|--------|
|
||||
| `id` | `VARCHAR(50)` | ✅ Oui | - | **Non** | - |
|
||||
| `name` | `VARCHAR(255)` | - | - | **Non** | - |
|
||||
| `description` | `TEXT` | - | - | Oui | - |
|
||||
| `playbook` | `VARCHAR(255)` | - | - | **Non** | - |
|
||||
| `target_type` | `VARCHAR(50)` | - | - | Oui | `group` |
|
||||
| `target` | `VARCHAR(255)` | - | - | **Non** | - |
|
||||
| `extra_vars` | `JSON` | - | - | Oui | - |
|
||||
| `schedule_type` | `VARCHAR(50)` | - | - | **Non** | - |
|
||||
| `schedule_time` | `DATETIME` | - | - | Oui | - |
|
||||
| `recurrence_type` | `VARCHAR(50)` | - | - | Oui | - |
|
||||
| `recurrence_time` | `VARCHAR(50)` | - | - | Oui | - |
|
||||
| `recurrence_days` | `TEXT` | - | - | Oui | - |
|
||||
| `cron_expression` | `VARCHAR(100)` | - | - | Oui | - |
|
||||
| `timezone` | `VARCHAR(100)` | - | - | Oui | `America/Montreal` |
|
||||
| `start_at` | `DATETIME` | - | - | Oui | - |
|
||||
| `end_at` | `DATETIME` | - | - | Oui | - |
|
||||
| `enabled` | `BOOLEAN` | - | - | **Non** | `True` |
|
||||
| `tags` | `TEXT` | - | - | Oui | - |
|
||||
| `next_run` | `DATETIME` | - | - | Oui | - |
|
||||
| `last_run` | `DATETIME` | - | - | Oui | - |
|
||||
| `last_status` | `VARCHAR(50)` | - | - | Oui | `never` |
|
||||
| `retry_on_failure` | `INTEGER` | - | - | Oui | `0` |
|
||||
| `timeout` | `INTEGER` | - | - | Oui | `3600` |
|
||||
| `notification_type` | `VARCHAR(50)` | - | - | Oui | `all` |
|
||||
| `run_count` | `INTEGER` | - | - | Oui | `0` |
|
||||
| `success_count` | `INTEGER` | - | - | Oui | `0` |
|
||||
| `failure_count` | `INTEGER` | - | - | Oui | `0` |
|
||||
| `created_at` | `DATETIME` | - | - | **Non** | `now()` |
|
||||
| `updated_at` | `DATETIME` | - | - | **Non** | `now()` |
|
||||
| `deleted_at` | `DATETIME` | - | - | Oui | - |
|
||||
|
||||
|
||||
### Table : `tasks`
|
||||
|
||||
|
||||
| Colonne | Type | Clé Primaire | Clé Étrangère | Nullable | Défaut |
|
||||
|---------|------|--------------|---------------|----------|--------|
|
||||
| `id` | `VARCHAR(50)` | ✅ Oui | - | **Non** | - |
|
||||
| `action` | `VARCHAR(100)` | - | - | **Non** | - |
|
||||
| `target` | `VARCHAR(255)` | - | - | **Non** | - |
|
||||
| `status` | `VARCHAR(50)` | - | - | **Non** | `'pending'` |
|
||||
| `playbook` | `VARCHAR(255)` | - | - | Oui | - |
|
||||
| `started_at` | `DATETIME` | - | - | Oui | - |
|
||||
| `completed_at` | `DATETIME` | - | - | Oui | - |
|
||||
| `error_message` | `TEXT` | - | - | Oui | - |
|
||||
| `result_data` | `JSON` | - | - | Oui | - |
|
||||
| `created_at` | `DATETIME` | - | - | **Non** | `now()` |
|
||||
|
||||
|
||||
### Table : `terminal_command_logs`
|
||||
|
||||
|
||||
| Colonne | Type | Clé Primaire | Clé Étrangère | Nullable | Défaut |
|
||||
|---------|------|--------------|---------------|----------|--------|
|
||||
| `id` | `INTEGER` | ✅ Oui | - | **Non** | - |
|
||||
| `created_at` | `DATETIME` | - | - | **Non** | `now()` |
|
||||
| `host_id` | `VARCHAR(50)` | - | 🔗 `hosts.id` | **Non** | - |
|
||||
| `user_id` | `INTEGER` | - | 🔗 `users.id` | Oui | - |
|
||||
| `terminal_session_id` | `VARCHAR(64)` | - | - | Oui | - |
|
||||
| `command` | `TEXT` | - | - | **Non** | - |
|
||||
| `command_hash` | `VARCHAR(64)` | - | - | **Non** | - |
|
||||
| `source` | `VARCHAR(20)` | - | - | **Non** | `'terminal'` |
|
||||
| `is_pinned` | `BOOLEAN` | - | - | **Non** | `0` |
|
||||
| `is_blocked` | `BOOLEAN` | - | - | **Non** | `0` |
|
||||
| `blocked_reason` | `VARCHAR(255)` | - | - | Oui | - |
|
||||
| `username` | `VARCHAR(100)` | - | - | Oui | - |
|
||||
| `host_name` | `VARCHAR(100)` | - | - | Oui | - |
|
||||
|
||||
|
||||
### Table : `terminal_sessions`
|
||||
|
||||
|
||||
| Colonne | Type | Clé Primaire | Clé Étrangère | Nullable | Défaut |
|
||||
|---------|------|--------------|---------------|----------|--------|
|
||||
| `id` | `VARCHAR(50)` | ✅ Oui | - | **Non** | - |
|
||||
| `host_id` | `VARCHAR(50)` | - | - | **Non** | - |
|
||||
| `host_name` | `VARCHAR(255)` | - | - | **Non** | - |
|
||||
| `host_ip` | `VARCHAR(50)` | - | - | **Non** | - |
|
||||
| `user_id` | `INTEGER` | - | - | Oui | - |
|
||||
| `username` | `VARCHAR(50)` | - | - | Oui | - |
|
||||
| `token_hash` | `VARCHAR(128)` | - | - | **Non** | - |
|
||||
| `ttyd_port` | `INTEGER` | - | - | **Non** | - |
|
||||
| `ttyd_pid` | `INTEGER` | - | - | Oui | - |
|
||||
| `mode` | `VARCHAR(20)` | - | - | **Non** | `'embedded'` |
|
||||
| `status` | `VARCHAR(20)` | - | - | **Non** | `'active'` |
|
||||
| `reason_closed` | `VARCHAR(30)` | - | - | Oui | - |
|
||||
| `created_at` | `DATETIME` | - | - | **Non** | `now()` |
|
||||
| `last_seen_at` | `DATETIME` | - | - | **Non** | `now()` |
|
||||
| `expires_at` | `DATETIME` | - | - | **Non** | - |
|
||||
| `closed_at` | `DATETIME` | - | - | Oui | - |
|
||||
|
||||
|
||||
### Table : `users`
|
||||
|
||||
|
||||
| Colonne | Type | Clé Primaire | Clé Étrangère | Nullable | Défaut |
|
||||
|---------|------|--------------|---------------|----------|--------|
|
||||
| `id` | `INTEGER` | ✅ Oui | - | **Non** | - |
|
||||
| `username` | `VARCHAR(50)` | - | - | **Non** | - |
|
||||
| `email` | `VARCHAR(255)` | - | - | Oui | - |
|
||||
| `hashed_password` | `VARCHAR(255)` | - | - | **Non** | - |
|
||||
| `role` | `VARCHAR(20)` | - | - | **Non** | `'admin'` |
|
||||
| `is_active` | `BOOLEAN` | - | - | **Non** | `1` |
|
||||
| `is_superuser` | `BOOLEAN` | - | - | **Non** | `0` |
|
||||
| `display_name` | `VARCHAR(100)` | - | - | Oui | - |
|
||||
| `created_at` | `DATETIME` | - | - | **Non** | `now()` |
|
||||
| `updated_at` | `DATETIME` | - | - | **Non** | `now()` |
|
||||
| `last_login` | `DATETIME` | - | - | Oui | - |
|
||||
| `password_changed_at` | `DATETIME` | - | - | Oui | - |
|
||||
| `deleted_at` | `DATETIME` | - | - | Oui | - |
|
||||
|
||||
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 676 KiB |
@@ -0,0 +1,655 @@
|
||||
import React, { useState, useMemo } from "react";
|
||||
|
||||
const SCHEMA = {
|
||||
alerts: {
|
||||
group: "Notifications",
|
||||
description: "Alertes système générées pour les utilisateurs",
|
||||
columns: [
|
||||
{ name: "id", type: "INTEGER", pk: true, fk: null, nullable: false, default: null },
|
||||
{ name: "user_id", type: "INTEGER", pk: false, fk: "users.id", nullable: true, default: null },
|
||||
{ name: "category", type: "VARCHAR(50)", pk: false, fk: null, nullable: false, default: null },
|
||||
{ name: "level", type: "VARCHAR(20)", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "title", type: "VARCHAR(255)", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "message", type: "TEXT", pk: false, fk: null, nullable: false, default: null },
|
||||
{ name: "source", type: "VARCHAR(50)", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "details", type: "JSON", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "read_at", type: "DATETIME", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "created_at", type: "DATETIME", pk: false, fk: null, nullable: false, default: "now()" },
|
||||
]
|
||||
},
|
||||
app_settings: {
|
||||
group: "Système",
|
||||
description: "Paramètres globaux de l'application",
|
||||
columns: [
|
||||
{ name: "key", type: "VARCHAR(100)", pk: true, fk: null, nullable: false, default: null },
|
||||
{ name: "value", type: "TEXT", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "created_at", type: "DATETIME", pk: false, fk: null, nullable: false, default: "now()" },
|
||||
{ name: "updated_at", type: "DATETIME", pk: false, fk: null, nullable: false, default: "now()" },
|
||||
]
|
||||
},
|
||||
bootstrap_status: {
|
||||
group: "Hôtes",
|
||||
description: "État du bootstrapping Ansible par hôte",
|
||||
columns: [
|
||||
{ name: "id", type: "INTEGER", pk: true, fk: null, nullable: false, default: null },
|
||||
{ name: "host_id", type: "VARCHAR(50)", pk: false, fk: "hosts.id", nullable: false, default: null },
|
||||
{ name: "status", type: "VARCHAR(50)", pk: false, fk: null, nullable: false, default: null },
|
||||
{ name: "automation_user", type: "VARCHAR(50)", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "last_attempt", type: "DATETIME", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "error_message", type: "TEXT", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "created_at", type: "DATETIME", pk: false, fk: null, nullable: false, default: "now()" },
|
||||
]
|
||||
},
|
||||
container_customizations: {
|
||||
group: "Docker",
|
||||
description: "Personnalisations visuelles de conteneurs par utilisateur",
|
||||
columns: [
|
||||
{ name: "id", type: "INTEGER", pk: true, fk: null, nullable: false, default: null },
|
||||
{ name: "user_id", type: "INTEGER", pk: false, fk: "users.id", nullable: true, default: null },
|
||||
{ name: "host_id", type: "VARCHAR(50)", pk: false, fk: "hosts.id", nullable: false, default: null },
|
||||
{ name: "container_id", type: "VARCHAR(64)", pk: false, fk: null, nullable: false, default: null },
|
||||
{ name: "icon_key", type: "VARCHAR(100)", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "icon_color", type: "VARCHAR(20)", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "bg_color", type: "VARCHAR(20)", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "created_at", type: "DATETIME", pk: false, fk: null, nullable: false, default: "now()" },
|
||||
{ name: "updated_at", type: "DATETIME", pk: false, fk: null, nullable: false, default: "now()" },
|
||||
]
|
||||
},
|
||||
docker_alerts: {
|
||||
group: "Docker",
|
||||
description: "Alertes liées aux conteneurs Docker",
|
||||
columns: [
|
||||
{ name: "id", type: "INTEGER", pk: true, fk: null, nullable: false, default: null },
|
||||
{ name: "host_id", type: "VARCHAR(50)", pk: false, fk: "hosts.id", nullable: false, default: null },
|
||||
{ name: "container_name", type: "VARCHAR(255)", pk: false, fk: null, nullable: false, default: null },
|
||||
{ name: "severity", type: "VARCHAR(20)", pk: false, fk: null, nullable: false, default: "warning" },
|
||||
{ name: "state", type: "VARCHAR(20)", pk: false, fk: null, nullable: false, default: "open" },
|
||||
{ name: "message", type: "TEXT", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "opened_at", type: "DATETIME", pk: false, fk: null, nullable: false, default: "now()" },
|
||||
{ name: "closed_at", type: "DATETIME", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "acknowledged_at", type: "DATETIME", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "acknowledged_by", type: "VARCHAR(100)", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "last_notified_at", type: "DATETIME", pk: false, fk: null, nullable: true, default: null },
|
||||
]
|
||||
},
|
||||
docker_containers: {
|
||||
group: "Docker",
|
||||
description: "Inventaire des conteneurs Docker par hôte",
|
||||
columns: [
|
||||
{ name: "id", type: "INTEGER", pk: true, fk: null, nullable: false, default: null },
|
||||
{ name: "host_id", type: "VARCHAR(50)", pk: false, fk: "hosts.id", nullable: false, default: null },
|
||||
{ name: "container_id", type: "VARCHAR(64)", pk: false, fk: null, nullable: false, default: null },
|
||||
{ name: "name", type: "VARCHAR(255)", pk: false, fk: null, nullable: false, default: null },
|
||||
{ name: "image", type: "VARCHAR(255)", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "state", type: "VARCHAR(20)", pk: false, fk: null, nullable: false, default: "unknown" },
|
||||
{ name: "status", type: "VARCHAR(255)", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "health", type: "VARCHAR(20)", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "created_at", type: "DATETIME", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "ports", type: "JSON", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "labels", type: "JSON", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "compose_project", type: "VARCHAR(255)", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "last_update_at", type: "DATETIME", pk: false, fk: null, nullable: false, default: "now()" },
|
||||
]
|
||||
},
|
||||
docker_images: {
|
||||
group: "Docker",
|
||||
description: "Images Docker disponibles sur les hôtes",
|
||||
columns: [
|
||||
{ name: "id", type: "INTEGER", pk: true, fk: null, nullable: false, default: null },
|
||||
{ name: "host_id", type: "VARCHAR(50)", pk: false, fk: "hosts.id", nullable: false, default: null },
|
||||
{ name: "image_id", type: "VARCHAR(64)", pk: false, fk: null, nullable: false, default: null },
|
||||
{ name: "repo_tags", type: "JSON", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "size", type: "BIGINT", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "created", type: "DATETIME", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "last_update_at", type: "DATETIME", pk: false, fk: null, nullable: false, default: "now()" },
|
||||
]
|
||||
},
|
||||
docker_volumes: {
|
||||
group: "Docker",
|
||||
description: "Volumes Docker par hôte",
|
||||
columns: [
|
||||
{ name: "id", type: "INTEGER", pk: true, fk: null, nullable: false, default: null },
|
||||
{ name: "host_id", type: "VARCHAR(50)", pk: false, fk: "hosts.id", nullable: false, default: null },
|
||||
{ name: "name", type: "VARCHAR(255)", pk: false, fk: null, nullable: false, default: null },
|
||||
{ name: "driver", type: "VARCHAR(50)", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "mountpoint", type: "TEXT", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "scope", type: "VARCHAR(20)", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "last_update_at", type: "DATETIME", pk: false, fk: null, nullable: false, default: "now()" },
|
||||
]
|
||||
},
|
||||
favorite_containers: {
|
||||
group: "Utilisateurs",
|
||||
description: "Conteneurs favoris par utilisateur et groupe",
|
||||
columns: [
|
||||
{ name: "id", type: "INTEGER", pk: true, fk: null, nullable: false, default: null },
|
||||
{ name: "user_id", type: "INTEGER", pk: false, fk: "users.id", nullable: true, default: null },
|
||||
{ name: "docker_container_id", type: "INTEGER", pk: false, fk: "docker_containers.id", nullable: false, default: null },
|
||||
{ name: "group_id", type: "INTEGER", pk: false, fk: "favorite_groups.id", nullable: true, default: null },
|
||||
{ name: "created_at", type: "DATETIME", pk: false, fk: null, nullable: false, default: "now()" },
|
||||
]
|
||||
},
|
||||
favorite_groups: {
|
||||
group: "Utilisateurs",
|
||||
description: "Groupes de favoris définis par l'utilisateur",
|
||||
columns: [
|
||||
{ name: "id", type: "INTEGER", pk: true, fk: null, nullable: false, default: null },
|
||||
{ name: "user_id", type: "INTEGER", pk: false, fk: "users.id", nullable: true, default: null },
|
||||
{ name: "name", type: "VARCHAR(100)", pk: false, fk: null, nullable: false, default: null },
|
||||
{ name: "sort_order", type: "INTEGER", pk: false, fk: null, nullable: false, default: "0" },
|
||||
{ name: "color", type: "VARCHAR(20)", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "icon_key", type: "VARCHAR(100)", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "created_at", type: "DATETIME", pk: false, fk: null, nullable: false, default: "now()" },
|
||||
{ name: "updated_at", type: "DATETIME", pk: false, fk: null, nullable: false, default: "now()" },
|
||||
]
|
||||
},
|
||||
host_metrics: {
|
||||
group: "Hôtes",
|
||||
description: "Métriques système collectées par hôte (CPU, RAM, disque, réseau…)",
|
||||
columns: [
|
||||
{ name: "id", type: "INTEGER", pk: true, fk: null, nullable: false, default: null },
|
||||
{ name: "host_id", type: "VARCHAR(50)", pk: false, fk: "hosts.id", nullable: false, default: null },
|
||||
{ name: "metric_type", type: "VARCHAR(50)", pk: false, fk: null, nullable: false, default: null },
|
||||
{ name: "cpu_count", type: "INTEGER", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "cpu_model", type: "VARCHAR(200)", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "cpu_cores", type: "INTEGER", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "cpu_threads", type: "INTEGER", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "cpu_threads_per_core", type: "INTEGER", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "cpu_sockets", type: "INTEGER", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "cpu_mhz", type: "FLOAT", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "cpu_max_mhz", type: "FLOAT", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "cpu_min_mhz", type: "FLOAT", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "cpu_load_1m", type: "FLOAT", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "cpu_load_5m", type: "FLOAT", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "cpu_load_15m", type: "FLOAT", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "cpu_usage_percent", type: "FLOAT", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "cpu_temperature", type: "FLOAT", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "memory_total_mb", type: "INTEGER", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "memory_used_mb", type: "INTEGER", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "memory_free_mb", type: "INTEGER", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "memory_usage_percent", type: "FLOAT", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "swap_total_mb", type: "INTEGER", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "swap_used_mb", type: "INTEGER", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "swap_usage_percent", type: "FLOAT", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "disk_info", type: "JSON", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "disk_devices", type: "JSON", pk: false, fk: null, nullable: false, default: null },
|
||||
{ name: "disk_root_total_gb", type: "FLOAT", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "disk_root_used_gb", type: "FLOAT", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "disk_root_usage_percent", type: "FLOAT", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "lvm_info", type: "JSON", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "zfs_info", type: "JSON", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "storage_details", type: "JSON", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "os_name", type: "VARCHAR(100)", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "os_version", type: "VARCHAR(100)", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "kernel_version", type: "VARCHAR(100)", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "hostname", type: "VARCHAR(200)", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "uptime_seconds", type: "INTEGER", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "uptime_human", type: "VARCHAR(100)", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "network_info", type: "JSON", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "raw_data", type: "JSON", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "collection_source", type: "VARCHAR(100)", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "collection_duration_ms", type: "INTEGER", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "error_message", type: "TEXT", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "collected_at", type: "DATETIME", pk: false, fk: null, nullable: false, default: "now()" },
|
||||
{ name: "created_at", type: "DATETIME", pk: false, fk: null, nullable: false, default: "now()" },
|
||||
]
|
||||
},
|
||||
hosts: {
|
||||
group: "Hôtes",
|
||||
description: "Inventaire des serveurs/hôtes gérés",
|
||||
columns: [
|
||||
{ name: "id", type: "VARCHAR(50)", pk: true, fk: null, nullable: false, default: null },
|
||||
{ name: "name", type: "VARCHAR(255)", pk: false, fk: null, nullable: false, default: null },
|
||||
{ name: "ip_address", type: "VARCHAR(50)", pk: false, fk: null, nullable: false, default: null },
|
||||
{ name: "status", type: "VARCHAR(50)", pk: false, fk: null, nullable: false, default: "'unknown'" },
|
||||
{ name: "ansible_group", type: "VARCHAR(50)", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "last_seen", type: "DATETIME", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "reachable", type: "BOOLEAN", pk: false, fk: null, nullable: false, default: "0" },
|
||||
{ name: "created_at", type: "DATETIME", pk: false, fk: null, nullable: false, default: "now()" },
|
||||
{ name: "updated_at", type: "DATETIME", pk: false, fk: null, nullable: false, default: "now()" },
|
||||
{ name: "deleted_at", type: "DATETIME", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "docker_enabled", type: "BOOLEAN", pk: false, fk: null, nullable: false, default: "0" },
|
||||
{ name: "docker_version", type: "VARCHAR(50)", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "docker_status", type: "VARCHAR(20)", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "docker_last_collect_at", type: "DATETIME", pk: false, fk: null, nullable: true, default: null },
|
||||
]
|
||||
},
|
||||
logs: {
|
||||
group: "Système",
|
||||
description: "Journal applicatif général",
|
||||
columns: [
|
||||
{ name: "id", type: "INTEGER", pk: true, fk: null, nullable: false, default: null },
|
||||
{ name: "level", type: "VARCHAR(50)", pk: false, fk: null, nullable: false, default: null },
|
||||
{ name: "source", type: "VARCHAR(255)", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "message", type: "TEXT", pk: false, fk: null, nullable: false, default: null },
|
||||
{ name: "details", type: "JSON", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "host_id", type: "VARCHAR(50)", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "task_id", type: "VARCHAR(50)", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "schedule_id", type: "VARCHAR(50)", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "created_at", type: "DATETIME", pk: false, fk: null, nullable: false, default: "now()" },
|
||||
]
|
||||
},
|
||||
playbook_lint_results: {
|
||||
group: "Ansible",
|
||||
description: "Résultats d'analyse de qualité des playbooks Ansible",
|
||||
columns: [
|
||||
{ name: "id", type: "INTEGER", pk: true, fk: null, nullable: false, default: null },
|
||||
{ name: "filename", type: "VARCHAR(255)", pk: false, fk: null, nullable: false, default: null },
|
||||
{ name: "quality_score", type: "INTEGER", pk: false, fk: null, nullable: false, default: "100" },
|
||||
{ name: "total_issues", type: "INTEGER", pk: false, fk: null, nullable: false, default: "0" },
|
||||
{ name: "errors_count", type: "INTEGER", pk: false, fk: null, nullable: false, default: "0" },
|
||||
{ name: "warnings_count", type: "INTEGER", pk: false, fk: null, nullable: false, default: "0" },
|
||||
{ name: "execution_time_ms", type: "INTEGER", pk: false, fk: null, nullable: false, default: "0" },
|
||||
{ name: "issues_json", type: "TEXT", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "raw_output", type: "TEXT", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "created_at", type: "DATETIME", pk: false, fk: null, nullable: false, default: "auto" },
|
||||
{ name: "updated_at", type: "DATETIME", pk: false, fk: null, nullable: false, default: "auto" },
|
||||
]
|
||||
},
|
||||
schedule_runs: {
|
||||
group: "Ansible",
|
||||
description: "Historique des exécutions de planifications",
|
||||
columns: [
|
||||
{ name: "id", type: "INTEGER", pk: true, fk: null, nullable: false, default: null },
|
||||
{ name: "schedule_id", type: "VARCHAR(50)", pk: false, fk: "schedules.id", nullable: false, default: null },
|
||||
{ name: "task_id", type: "VARCHAR(50)", pk: false, fk: "tasks.id", nullable: true, default: null },
|
||||
{ name: "status", type: "VARCHAR(50)", pk: false, fk: null, nullable: false, default: null },
|
||||
{ name: "started_at", type: "DATETIME", pk: false, fk: null, nullable: false, default: null },
|
||||
{ name: "completed_at", type: "DATETIME", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "duration", type: "FLOAT", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "hosts_impacted", type: "INTEGER", pk: false, fk: null, nullable: true, default: "0" },
|
||||
{ name: "error_message", type: "TEXT", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "output", type: "TEXT", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "created_at", type: "DATETIME", pk: false, fk: null, nullable: false, default: "now()" },
|
||||
]
|
||||
},
|
||||
schedules: {
|
||||
group: "Ansible",
|
||||
description: "Planifications d'exécution de playbooks",
|
||||
columns: [
|
||||
{ name: "id", type: "VARCHAR(50)", pk: true, fk: null, nullable: false, default: null },
|
||||
{ name: "name", type: "VARCHAR(255)", pk: false, fk: null, nullable: false, default: null },
|
||||
{ name: "description", type: "TEXT", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "playbook", type: "VARCHAR(255)", pk: false, fk: null, nullable: false, default: null },
|
||||
{ name: "target_type", type: "VARCHAR(50)", pk: false, fk: null, nullable: true, default: "group" },
|
||||
{ name: "target", type: "VARCHAR(255)", pk: false, fk: null, nullable: false, default: null },
|
||||
{ name: "extra_vars", type: "JSON", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "schedule_type", type: "VARCHAR(50)", pk: false, fk: null, nullable: false, default: null },
|
||||
{ name: "schedule_time", type: "DATETIME", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "recurrence_type", type: "VARCHAR(50)", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "recurrence_time", type: "VARCHAR(50)", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "recurrence_days", type: "TEXT", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "cron_expression", type: "VARCHAR(100)", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "timezone", type: "VARCHAR(100)", pk: false, fk: null, nullable: true, default: "America/Montreal" },
|
||||
{ name: "start_at", type: "DATETIME", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "end_at", type: "DATETIME", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "enabled", type: "BOOLEAN", pk: false, fk: null, nullable: false, default: "True" },
|
||||
{ name: "tags", type: "TEXT", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "next_run", type: "DATETIME", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "last_run", type: "DATETIME", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "last_status", type: "VARCHAR(50)", pk: false, fk: null, nullable: true, default: "never" },
|
||||
{ name: "retry_on_failure", type: "INTEGER", pk: false, fk: null, nullable: true, default: "0" },
|
||||
{ name: "timeout", type: "INTEGER", pk: false, fk: null, nullable: true, default: "3600" },
|
||||
{ name: "notification_type", type: "VARCHAR(50)", pk: false, fk: null, nullable: true, default: "all" },
|
||||
{ name: "run_count", type: "INTEGER", pk: false, fk: null, nullable: true, default: "0" },
|
||||
{ name: "success_count", type: "INTEGER", pk: false, fk: null, nullable: true, default: "0" },
|
||||
{ name: "failure_count", type: "INTEGER", pk: false, fk: null, nullable: true, default: "0" },
|
||||
{ name: "created_at", type: "DATETIME", pk: false, fk: null, nullable: false, default: "now()" },
|
||||
{ name: "updated_at", type: "DATETIME", pk: false, fk: null, nullable: false, default: "now()" },
|
||||
{ name: "deleted_at", type: "DATETIME", pk: false, fk: null, nullable: true, default: null },
|
||||
]
|
||||
},
|
||||
tasks: {
|
||||
group: "Ansible",
|
||||
description: "Tâches Ansible déclenchées manuellement ou via planification",
|
||||
columns: [
|
||||
{ name: "id", type: "VARCHAR(50)", pk: true, fk: null, nullable: false, default: null },
|
||||
{ name: "action", type: "VARCHAR(100)", pk: false, fk: null, nullable: false, default: null },
|
||||
{ name: "target", type: "VARCHAR(255)", pk: false, fk: null, nullable: false, default: null },
|
||||
{ name: "status", type: "VARCHAR(50)", pk: false, fk: null, nullable: false, default: "'pending'" },
|
||||
{ name: "playbook", type: "VARCHAR(255)", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "started_at", type: "DATETIME", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "completed_at", type: "DATETIME", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "error_message", type: "TEXT", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "result_data", type: "JSON", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "created_at", type: "DATETIME", pk: false, fk: null, nullable: false, default: "now()" },
|
||||
]
|
||||
},
|
||||
terminal_command_logs: {
|
||||
group: "Terminal",
|
||||
description: "Journal des commandes exécutées dans le terminal",
|
||||
columns: [
|
||||
{ name: "id", type: "INTEGER", pk: true, fk: null, nullable: false, default: null },
|
||||
{ name: "created_at", type: "DATETIME", pk: false, fk: null, nullable: false, default: "now()" },
|
||||
{ name: "host_id", type: "VARCHAR(50)", pk: false, fk: "hosts.id", nullable: false, default: null },
|
||||
{ name: "user_id", type: "INTEGER", pk: false, fk: "users.id", nullable: true, default: null },
|
||||
{ name: "terminal_session_id", type: "VARCHAR(64)", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "command", type: "TEXT", pk: false, fk: null, nullable: false, default: null },
|
||||
{ name: "command_hash", type: "VARCHAR(64)", pk: false, fk: null, nullable: false, default: null },
|
||||
{ name: "source", type: "VARCHAR(20)", pk: false, fk: null, nullable: false, default: "'terminal'" },
|
||||
{ name: "is_pinned", type: "BOOLEAN", pk: false, fk: null, nullable: false, default: "0" },
|
||||
{ name: "is_blocked", type: "BOOLEAN", pk: false, fk: null, nullable: false, default: "0" },
|
||||
{ name: "blocked_reason", type: "VARCHAR(255)", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "username", type: "VARCHAR(100)", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "host_name", type: "VARCHAR(100)", pk: false, fk: null, nullable: true, default: null },
|
||||
]
|
||||
},
|
||||
terminal_sessions: {
|
||||
group: "Terminal",
|
||||
description: "Sessions de terminal actives ou fermées",
|
||||
columns: [
|
||||
{ name: "id", type: "VARCHAR(50)", pk: true, fk: null, nullable: false, default: null },
|
||||
{ name: "host_id", type: "VARCHAR(50)", pk: false, fk: null, nullable: false, default: null },
|
||||
{ name: "host_name", type: "VARCHAR(255)", pk: false, fk: null, nullable: false, default: null },
|
||||
{ name: "host_ip", type: "VARCHAR(50)", pk: false, fk: null, nullable: false, default: null },
|
||||
{ name: "user_id", type: "INTEGER", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "username", type: "VARCHAR(50)", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "token_hash", type: "VARCHAR(128)", pk: false, fk: null, nullable: false, default: null },
|
||||
{ name: "ttyd_port", type: "INTEGER", pk: false, fk: null, nullable: false, default: null },
|
||||
{ name: "ttyd_pid", type: "INTEGER", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "mode", type: "VARCHAR(20)", pk: false, fk: null, nullable: false, default: "'embedded'" },
|
||||
{ name: "status", type: "VARCHAR(20)", pk: false, fk: null, nullable: false, default: "'active'" },
|
||||
{ name: "reason_closed", type: "VARCHAR(30)", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "created_at", type: "DATETIME", pk: false, fk: null, nullable: false, default: "now()" },
|
||||
{ name: "last_seen_at", type: "DATETIME", pk: false, fk: null, nullable: false, default: "now()" },
|
||||
{ name: "expires_at", type: "DATETIME", pk: false, fk: null, nullable: false, default: null },
|
||||
{ name: "closed_at", type: "DATETIME", pk: false, fk: null, nullable: true, default: null },
|
||||
]
|
||||
},
|
||||
users: {
|
||||
group: "Utilisateurs",
|
||||
description: "Comptes utilisateurs de l'application",
|
||||
columns: [
|
||||
{ name: "id", type: "INTEGER", pk: true, fk: null, nullable: false, default: null },
|
||||
{ name: "username", type: "VARCHAR(50)", pk: false, fk: null, nullable: false, default: null },
|
||||
{ name: "email", type: "VARCHAR(255)", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "hashed_password", type: "VARCHAR(255)", pk: false, fk: null, nullable: false, default: null },
|
||||
{ name: "role", type: "VARCHAR(20)", pk: false, fk: null, nullable: false, default: "'admin'" },
|
||||
{ name: "is_active", type: "BOOLEAN", pk: false, fk: null, nullable: false, default: "1" },
|
||||
{ name: "is_superuser", type: "BOOLEAN", pk: false, fk: null, nullable: false, default: "0" },
|
||||
{ name: "display_name", type: "VARCHAR(100)", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "created_at", type: "DATETIME", pk: false, fk: null, nullable: false, default: "now()" },
|
||||
{ name: "updated_at", type: "DATETIME", pk: false, fk: null, nullable: false, default: "now()" },
|
||||
{ name: "last_login", type: "DATETIME", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "password_changed_at", type: "DATETIME", pk: false, fk: null, nullable: true, default: null },
|
||||
{ name: "deleted_at", type: "DATETIME", pk: false, fk: null, nullable: true, default: null },
|
||||
]
|
||||
},
|
||||
};
|
||||
|
||||
const GROUP_COLORS = {
|
||||
"Hôtes": { bg: "#0f172a", accent: "#38bdf8", badge: "#0369a1", badgeText: "#e0f2fe" },
|
||||
"Docker": { bg: "#0a1628", accent: "#22d3ee", badge: "#0e7490", badgeText: "#cffafe" },
|
||||
"Ansible": { bg: "#1a0a2e", accent: "#a78bfa", badge: "#6d28d9", badgeText: "#ede9fe" },
|
||||
"Utilisateurs": { bg: "#0f1f0f", accent: "#4ade80", badge: "#15803d", badgeText: "#dcfce7" },
|
||||
"Terminal": { bg: "#1a1400", accent: "#fbbf24", badge: "#b45309", badgeText: "#fef3c7" },
|
||||
"Notifications": { bg: "#1a0a0a", accent: "#f87171", badge: "#b91c1c", badgeText: "#fee2e2" },
|
||||
"Système": { bg: "#111827", accent: "#94a3b8", badge: "#475569", badgeText: "#f1f5f9" },
|
||||
};
|
||||
|
||||
const TYPE_COLOR = (t) => {
|
||||
if (t.startsWith("VARCHAR") || t === "TEXT") return "#7dd3fc";
|
||||
if (t === "INTEGER" || t === "BIGINT" || t === "FLOAT") return "#86efac";
|
||||
if (t === "DATETIME") return "#fcd34d";
|
||||
if (t === "BOOLEAN") return "#f9a8d4";
|
||||
if (t === "JSON") return "#c4b5fd";
|
||||
return "#e2e8f0";
|
||||
};
|
||||
|
||||
const GROUPS = [...new Set(Object.values(SCHEMA).map(t => t.group))];
|
||||
|
||||
export default function App() {
|
||||
const [search, setSearch] = useState("");
|
||||
const [activeGroup, setActiveGroup] = useState("Tous");
|
||||
const [selectedTable, setSelectedTable] = useState(null);
|
||||
const [colSearch, setColSearch] = useState("");
|
||||
|
||||
const tableNames = useMemo(() => Object.keys(SCHEMA).sort(), []);
|
||||
|
||||
const filtered = useMemo(() => {
|
||||
return tableNames.filter(name => {
|
||||
const matchGroup = activeGroup === "Tous" || SCHEMA[name].group === activeGroup;
|
||||
const matchSearch = name.toLowerCase().includes(search.toLowerCase()) ||
|
||||
SCHEMA[name].description.toLowerCase().includes(search.toLowerCase());
|
||||
return matchGroup && matchSearch;
|
||||
});
|
||||
}, [tableNames, search, activeGroup]);
|
||||
|
||||
const tableData = selectedTable ? SCHEMA[selectedTable] : null;
|
||||
const groupColor = tableData ? GROUP_COLORS[tableData.group] : null;
|
||||
|
||||
const filteredCols = useMemo(() => {
|
||||
if (!tableData) return [];
|
||||
return tableData.columns.filter(c =>
|
||||
c.name.toLowerCase().includes(colSearch.toLowerCase()) ||
|
||||
c.type.toLowerCase().includes(colSearch.toLowerCase())
|
||||
);
|
||||
}, [tableData, colSearch]);
|
||||
|
||||
const grouped = useMemo(() => {
|
||||
const g = {};
|
||||
GROUPS.forEach(grp => {
|
||||
const tables = filtered.filter(n => SCHEMA[n].group === grp);
|
||||
if (tables.length) g[grp] = tables;
|
||||
});
|
||||
return g;
|
||||
}, [filtered]);
|
||||
|
||||
return (
|
||||
<div style={{ display: "flex", height: "100vh", background: "#0d1117", fontFamily: "'JetBrains Mono', 'Fira Code', monospace", color: "#c9d1d9", overflow: "hidden" }}>
|
||||
<style>{`
|
||||
@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@300;400;600;700&display=swap');
|
||||
::-webkit-scrollbar { width: 6px; height: 6px; }
|
||||
::-webkit-scrollbar-track { background: #161b22; }
|
||||
::-webkit-scrollbar-thumb { background: #30363d; border-radius: 3px; }
|
||||
::-webkit-scrollbar-thumb:hover { background: #484f58; }
|
||||
.table-item { transition: background 0.15s, border-color 0.15s; }
|
||||
.table-item:hover { background: #21262d !important; }
|
||||
.col-row:hover { background: #1c2128 !important; }
|
||||
.group-btn { transition: all 0.15s; }
|
||||
.group-btn:hover { filter: brightness(1.2); }
|
||||
`}</style>
|
||||
|
||||
{/* SIDEBAR */}
|
||||
<div style={{ width: 280, background: "#161b22", borderRight: "1px solid #21262d", display: "flex", flexDirection: "column", flexShrink: 0 }}>
|
||||
{/* Header */}
|
||||
<div style={{ padding: "20px 16px 16px", borderBottom: "1px solid #21262d" }}>
|
||||
<div style={{ fontSize: 11, color: "#58a6ff", fontWeight: 700, letterSpacing: 3, marginBottom: 6, textTransform: "uppercase" }}>Schema Explorer</div>
|
||||
<div style={{ fontSize: 12, color: "#484f58" }}>{tableNames.length} tables · SQLAlchemy</div>
|
||||
</div>
|
||||
|
||||
{/* Search */}
|
||||
<div style={{ padding: "12px 12px 8px" }}>
|
||||
<div style={{ position: "relative" }}>
|
||||
<span style={{ position: "absolute", left: 10, top: "50%", transform: "translateY(-50%)", color: "#484f58", fontSize: 13 }}>⌕</span>
|
||||
<input
|
||||
value={search}
|
||||
onChange={e => setSearch(e.target.value)}
|
||||
placeholder="Rechercher une table…"
|
||||
style={{ width: "100%", background: "#0d1117", border: "1px solid #30363d", borderRadius: 6, padding: "7px 10px 7px 30px", color: "#c9d1d9", fontSize: 12, outline: "none", boxSizing: "border-box" }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Groups filter */}
|
||||
<div style={{ padding: "0 12px 10px", display: "flex", flexWrap: "wrap", gap: 5 }}>
|
||||
{["Tous", ...GROUPS].map(g => {
|
||||
const isActive = activeGroup === g;
|
||||
const gc = GROUP_COLORS[g];
|
||||
return (
|
||||
<button key={g} className="group-btn" onClick={() => setActiveGroup(g)} style={{
|
||||
fontSize: 10, padding: "3px 8px", borderRadius: 4, cursor: "pointer", border: "none", fontFamily: "inherit", fontWeight: 600,
|
||||
background: isActive ? (gc ? gc.badge : "#21262d") : "#0d1117",
|
||||
color: isActive ? (gc ? gc.badgeText : "#c9d1d9") : "#58616a",
|
||||
letterSpacing: 0.5
|
||||
}}>
|
||||
{g}
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
{/* Table list */}
|
||||
<div style={{ flex: 1, overflowY: "auto", padding: "0 8px 16px" }}>
|
||||
{Object.keys(grouped).map(grp => {
|
||||
const gc = GROUP_COLORS[grp];
|
||||
return (
|
||||
<div key={grp} style={{ marginBottom: 8 }}>
|
||||
<div style={{ fontSize: 10, color: gc.accent, fontWeight: 700, letterSpacing: 2, textTransform: "uppercase", padding: "8px 8px 4px" }}>
|
||||
{grp}
|
||||
</div>
|
||||
{grouped[grp].map(name => {
|
||||
const isSelected = selectedTable === name;
|
||||
return (
|
||||
<div key={name} className="table-item" onClick={() => { setSelectedTable(name); setColSearch(""); }} style={{
|
||||
padding: "8px 10px", borderRadius: 6, cursor: "pointer", marginBottom: 2,
|
||||
background: isSelected ? "#1f2d3d" : "transparent",
|
||||
border: isSelected ? `1px solid ${gc.accent}44` : "1px solid transparent",
|
||||
}}>
|
||||
<div style={{ display: "flex", alignItems: "center", gap: 7 }}>
|
||||
<span style={{ color: isSelected ? gc.accent : "#484f58", fontSize: 12 }}>⬡</span>
|
||||
<span style={{ fontSize: 12, color: isSelected ? "#e6edf3" : "#8b949e", fontWeight: isSelected ? 600 : 400 }}>{name}</span>
|
||||
<span style={{ marginLeft: "auto", fontSize: 10, color: "#484f58" }}>{SCHEMA[name].columns.length}</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
{filtered.length === 0 && (
|
||||
<div style={{ padding: 20, color: "#484f58", fontSize: 12, textAlign: "center" }}>Aucune table trouvée</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* MAIN CONTENT */}
|
||||
<div style={{ flex: 1, display: "flex", flexDirection: "column", overflow: "hidden" }}>
|
||||
{selectedTable && tableData ? (
|
||||
<>
|
||||
{/* Table header */}
|
||||
<div style={{ padding: "20px 28px 16px", borderBottom: "1px solid #21262d", background: "#161b22" }}>
|
||||
<div style={{ display: "flex", alignItems: "center", gap: 12, marginBottom: 6 }}>
|
||||
<span style={{ fontSize: 22, color: groupColor.accent }}>⬡</span>
|
||||
<h1 style={{ margin: 0, fontSize: 22, fontWeight: 700, color: "#e6edf3", letterSpacing: 1 }}>{selectedTable}</h1>
|
||||
<span style={{ fontSize: 11, padding: "2px 10px", borderRadius: 4, fontWeight: 700, background: groupColor.badge, color: groupColor.badgeText }}>
|
||||
{tableData.group}
|
||||
</span>
|
||||
</div>
|
||||
<p style={{ margin: 0, fontSize: 13, color: "#8b949e" }}>{tableData.description}</p>
|
||||
|
||||
{/* Stats row */}
|
||||
<div style={{ display: "flex", gap: 20, marginTop: 12 }}>
|
||||
{[
|
||||
{ label: "Colonnes", val: tableData.columns.length },
|
||||
{ label: "Clés primaires", val: tableData.columns.filter(c => c.pk).length },
|
||||
{ label: "Clés étrangères", val: tableData.columns.filter(c => c.fk).length },
|
||||
{ label: "Nullable", val: tableData.columns.filter(c => c.nullable).length },
|
||||
].map(s => (
|
||||
<div key={s.label} style={{ background: "#0d1117", border: "1px solid #21262d", borderRadius: 8, padding: "6px 14px", textAlign: "center" }}>
|
||||
<div style={{ fontSize: 18, fontWeight: 700, color: groupColor.accent }}>{s.val}</div>
|
||||
<div style={{ fontSize: 10, color: "#484f58", letterSpacing: 1 }}>{s.label}</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Column search */}
|
||||
<div style={{ padding: "12px 28px 0", background: "#0d1117" }}>
|
||||
<div style={{ position: "relative", maxWidth: 340 }}>
|
||||
<span style={{ position: "absolute", left: 10, top: "50%", transform: "translateY(-50%)", color: "#484f58", fontSize: 13 }}>⌕</span>
|
||||
<input
|
||||
value={colSearch}
|
||||
onChange={e => setColSearch(e.target.value)}
|
||||
placeholder="Filtrer les colonnes…"
|
||||
style={{ width: "100%", background: "#161b22", border: "1px solid #30363d", borderRadius: 6, padding: "7px 10px 7px 30px", color: "#c9d1d9", fontSize: 12, outline: "none", boxSizing: "border-box" }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Columns table */}
|
||||
<div style={{ flex: 1, overflowY: "auto", padding: "12px 28px 28px", background: "#0d1117" }}>
|
||||
<table style={{ width: "100%", borderCollapse: "collapse", fontSize: 12 }}>
|
||||
<thead>
|
||||
<tr style={{ borderBottom: "2px solid #21262d" }}>
|
||||
{["Colonne", "Type", "Flags", "Défaut"].map(h => (
|
||||
<th key={h} style={{ textAlign: "left", padding: "8px 12px", color: "#484f58", fontWeight: 700, fontSize: 10, letterSpacing: 2, textTransform: "uppercase" }}>{h}</th>
|
||||
))}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{filteredCols.map((col, i) => (
|
||||
<tr key={col.name} className="col-row" style={{ borderBottom: "1px solid #161b22", background: i % 2 === 0 ? "transparent" : "#0a0f16" }}>
|
||||
<td style={{ padding: "10px 12px", fontWeight: col.pk ? 700 : 400 }}>
|
||||
<div style={{ display: "flex", alignItems: "center", gap: 7 }}>
|
||||
{col.pk && <span title="Clé primaire" style={{ fontSize: 11, color: "#f59e0b" }}>🔑</span>}
|
||||
{col.fk && !col.pk && <span title={`Clé étrangère → ${col.fk}`} style={{ fontSize: 11 }}>🔗</span>}
|
||||
{!col.pk && !col.fk && <span style={{ fontSize: 11, color: "#30363d" }}>·</span>}
|
||||
<span style={{ color: col.pk ? "#fbbf24" : col.fk ? "#60a5fa" : "#e6edf3" }}>{col.name}</span>
|
||||
</div>
|
||||
{col.fk && (
|
||||
<div style={{ fontSize: 10, color: "#484f58", marginLeft: 22, marginTop: 2 }}>→ {col.fk}</div>
|
||||
)}
|
||||
</td>
|
||||
<td style={{ padding: "10px 12px" }}>
|
||||
<span style={{ color: TYPE_COLOR(col.type), fontWeight: 600 }}>{col.type}</span>
|
||||
</td>
|
||||
<td style={{ padding: "10px 12px" }}>
|
||||
<div style={{ display: "flex", gap: 5, flexWrap: "wrap" }}>
|
||||
{!col.nullable && (
|
||||
<span style={{ fontSize: 10, padding: "1px 7px", borderRadius: 3, background: "#1c2e1c", color: "#4ade80", fontWeight: 600 }}>NOT NULL</span>
|
||||
)}
|
||||
{col.nullable && (
|
||||
<span style={{ fontSize: 10, padding: "1px 7px", borderRadius: 3, background: "#1c1c1c", color: "#484f58" }}>NULL</span>
|
||||
)}
|
||||
</div>
|
||||
</td>
|
||||
<td style={{ padding: "10px 12px" }}>
|
||||
{col.default ? (
|
||||
<code style={{ fontSize: 11, color: "#c4b5fd", background: "#1e1a2e", padding: "2px 7px", borderRadius: 3 }}>{col.default}</code>
|
||||
) : (
|
||||
<span style={{ color: "#30363d" }}>—</span>
|
||||
)}
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
{filteredCols.length === 0 && (
|
||||
<div style={{ padding: 40, textAlign: "center", color: "#484f58", fontSize: 12 }}>Aucune colonne trouvée</div>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
/* Welcome / overview */
|
||||
<div style={{ flex: 1, display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", padding: 40, gap: 32 }}>
|
||||
<div style={{ textAlign: "center" }}>
|
||||
<div style={{ fontSize: 48, marginBottom: 12 }}>⬡</div>
|
||||
<h2 style={{ margin: 0, fontSize: 24, color: "#e6edf3", fontWeight: 700 }}>Modèle de Données</h2>
|
||||
<p style={{ color: "#484f58", fontSize: 13, marginTop: 8 }}>Sélectionnez une table dans le panneau de gauche</p>
|
||||
</div>
|
||||
<div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(160px, 1fr))", gap: 12, maxWidth: 700, width: "100%" }}>
|
||||
{GROUPS.map(grp => {
|
||||
const gc = GROUP_COLORS[grp];
|
||||
const count = tableNames.filter(n => SCHEMA[n].group === grp).length;
|
||||
const firstTable = tableNames.find(n => SCHEMA[n].group === grp);
|
||||
return (
|
||||
<div key={grp} onClick={() => { setActiveGroup(grp); setSelectedTable(firstTable); setColSearch(""); }} style={{
|
||||
background: "#161b22", border: `1px solid ${gc.accent}33`, borderRadius: 10, padding: "16px 18px", cursor: "pointer",
|
||||
transition: "all 0.15s"
|
||||
}}
|
||||
onMouseEnter={e => e.currentTarget.style.borderColor = gc.accent}
|
||||
onMouseLeave={e => e.currentTarget.style.borderColor = gc.accent + "33"}
|
||||
>
|
||||
<div style={{ fontSize: 20, marginBottom: 8 }}>⬡</div>
|
||||
<div style={{ fontSize: 13, fontWeight: 700, color: gc.accent, marginBottom: 4 }}>{grp}</div>
|
||||
<div style={{ fontSize: 11, color: "#484f58" }}>{count} table{count > 1 ? "s" : ""}</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,311 @@
|
||||
erDiagram
|
||||
alerts {
|
||||
INTEGER id PK
|
||||
INTEGER user_id FK "nullable"
|
||||
VARCHAR category
|
||||
VARCHAR level "nullable"
|
||||
VARCHAR title "nullable"
|
||||
TEXT message
|
||||
VARCHAR source "nullable"
|
||||
JSON details "nullable"
|
||||
DATETIME read_at "nullable"
|
||||
DATETIME created_at
|
||||
}
|
||||
app_settings {
|
||||
VARCHAR key PK
|
||||
TEXT value "nullable"
|
||||
DATETIME created_at
|
||||
DATETIME updated_at
|
||||
}
|
||||
bootstrap_status {
|
||||
INTEGER id PK
|
||||
VARCHAR host_id FK
|
||||
VARCHAR status
|
||||
VARCHAR automation_user "nullable"
|
||||
DATETIME last_attempt "nullable"
|
||||
TEXT error_message "nullable"
|
||||
DATETIME created_at
|
||||
}
|
||||
container_customizations {
|
||||
INTEGER id PK
|
||||
INTEGER user_id FK "nullable"
|
||||
VARCHAR host_id FK
|
||||
VARCHAR container_id
|
||||
VARCHAR icon_key "nullable"
|
||||
VARCHAR icon_color "nullable"
|
||||
VARCHAR bg_color "nullable"
|
||||
DATETIME created_at
|
||||
DATETIME updated_at
|
||||
}
|
||||
docker_alerts {
|
||||
INTEGER id PK
|
||||
VARCHAR host_id FK
|
||||
VARCHAR container_name
|
||||
VARCHAR severity
|
||||
VARCHAR state
|
||||
TEXT message "nullable"
|
||||
DATETIME opened_at
|
||||
DATETIME closed_at "nullable"
|
||||
DATETIME acknowledged_at "nullable"
|
||||
VARCHAR acknowledged_by "nullable"
|
||||
DATETIME last_notified_at "nullable"
|
||||
}
|
||||
docker_containers {
|
||||
INTEGER id PK
|
||||
VARCHAR host_id FK
|
||||
VARCHAR container_id
|
||||
VARCHAR name
|
||||
VARCHAR image "nullable"
|
||||
VARCHAR state
|
||||
VARCHAR status "nullable"
|
||||
VARCHAR health "nullable"
|
||||
DATETIME created_at "nullable"
|
||||
JSON ports "nullable"
|
||||
JSON labels "nullable"
|
||||
VARCHAR compose_project "nullable"
|
||||
DATETIME last_update_at
|
||||
}
|
||||
docker_images {
|
||||
INTEGER id PK
|
||||
VARCHAR host_id FK
|
||||
VARCHAR image_id
|
||||
JSON repo_tags "nullable"
|
||||
BIGINT size "nullable"
|
||||
DATETIME created "nullable"
|
||||
DATETIME last_update_at
|
||||
}
|
||||
docker_volumes {
|
||||
INTEGER id PK
|
||||
VARCHAR host_id FK
|
||||
VARCHAR name
|
||||
VARCHAR driver "nullable"
|
||||
TEXT mountpoint "nullable"
|
||||
VARCHAR scope "nullable"
|
||||
DATETIME last_update_at
|
||||
}
|
||||
favorite_containers {
|
||||
INTEGER id PK
|
||||
INTEGER user_id FK "nullable"
|
||||
INTEGER docker_container_id FK
|
||||
INTEGER group_id FK "nullable"
|
||||
DATETIME created_at
|
||||
}
|
||||
favorite_groups {
|
||||
INTEGER id PK
|
||||
INTEGER user_id FK "nullable"
|
||||
VARCHAR name
|
||||
INTEGER sort_order
|
||||
VARCHAR color "nullable"
|
||||
VARCHAR icon_key "nullable"
|
||||
DATETIME created_at
|
||||
DATETIME updated_at
|
||||
}
|
||||
host_metrics {
|
||||
INTEGER id PK
|
||||
VARCHAR host_id FK
|
||||
VARCHAR metric_type
|
||||
INTEGER cpu_count "nullable"
|
||||
VARCHAR cpu_model "nullable"
|
||||
INTEGER cpu_cores "nullable"
|
||||
INTEGER cpu_threads "nullable"
|
||||
INTEGER cpu_threads_per_core "nullable"
|
||||
INTEGER cpu_sockets "nullable"
|
||||
FLOAT cpu_mhz "nullable"
|
||||
FLOAT cpu_max_mhz "nullable"
|
||||
FLOAT cpu_min_mhz "nullable"
|
||||
FLOAT cpu_load_1m "nullable"
|
||||
FLOAT cpu_load_5m "nullable"
|
||||
FLOAT cpu_load_15m "nullable"
|
||||
FLOAT cpu_usage_percent "nullable"
|
||||
FLOAT cpu_temperature "nullable"
|
||||
INTEGER memory_total_mb "nullable"
|
||||
INTEGER memory_used_mb "nullable"
|
||||
INTEGER memory_free_mb "nullable"
|
||||
FLOAT memory_usage_percent "nullable"
|
||||
INTEGER swap_total_mb "nullable"
|
||||
INTEGER swap_used_mb "nullable"
|
||||
FLOAT swap_usage_percent "nullable"
|
||||
JSON disk_info "nullable"
|
||||
JSON disk_devices
|
||||
FLOAT disk_root_total_gb "nullable"
|
||||
FLOAT disk_root_used_gb "nullable"
|
||||
FLOAT disk_root_usage_percent "nullable"
|
||||
JSON lvm_info "nullable"
|
||||
JSON zfs_info "nullable"
|
||||
JSON storage_details "nullable"
|
||||
VARCHAR os_name "nullable"
|
||||
VARCHAR os_version "nullable"
|
||||
VARCHAR kernel_version "nullable"
|
||||
VARCHAR hostname "nullable"
|
||||
INTEGER uptime_seconds "nullable"
|
||||
VARCHAR uptime_human "nullable"
|
||||
JSON network_info "nullable"
|
||||
JSON raw_data "nullable"
|
||||
VARCHAR collection_source "nullable"
|
||||
INTEGER collection_duration_ms "nullable"
|
||||
TEXT error_message "nullable"
|
||||
DATETIME collected_at
|
||||
DATETIME created_at
|
||||
}
|
||||
hosts {
|
||||
VARCHAR id PK
|
||||
VARCHAR name
|
||||
VARCHAR ip_address
|
||||
VARCHAR status
|
||||
VARCHAR ansible_group "nullable"
|
||||
DATETIME last_seen "nullable"
|
||||
BOOLEAN reachable
|
||||
DATETIME created_at
|
||||
DATETIME updated_at
|
||||
DATETIME deleted_at "nullable"
|
||||
BOOLEAN docker_enabled
|
||||
VARCHAR docker_version "nullable"
|
||||
VARCHAR docker_status "nullable"
|
||||
DATETIME docker_last_collect_at "nullable"
|
||||
}
|
||||
logs {
|
||||
INTEGER id PK
|
||||
VARCHAR level
|
||||
VARCHAR source "nullable"
|
||||
TEXT message
|
||||
JSON details "nullable"
|
||||
VARCHAR host_id "nullable"
|
||||
VARCHAR task_id "nullable"
|
||||
VARCHAR schedule_id "nullable"
|
||||
DATETIME created_at
|
||||
}
|
||||
playbook_lint_results {
|
||||
INTEGER id PK
|
||||
VARCHAR filename
|
||||
INTEGER quality_score
|
||||
INTEGER total_issues
|
||||
INTEGER errors_count
|
||||
INTEGER warnings_count
|
||||
INTEGER execution_time_ms
|
||||
TEXT issues_json "nullable"
|
||||
TEXT raw_output "nullable"
|
||||
DATETIME created_at
|
||||
DATETIME updated_at
|
||||
}
|
||||
schedule_runs {
|
||||
INTEGER id PK
|
||||
VARCHAR schedule_id FK
|
||||
VARCHAR task_id FK "nullable"
|
||||
VARCHAR status
|
||||
DATETIME started_at
|
||||
DATETIME completed_at "nullable"
|
||||
FLOAT duration "nullable"
|
||||
INTEGER hosts_impacted "nullable"
|
||||
TEXT error_message "nullable"
|
||||
TEXT output "nullable"
|
||||
DATETIME created_at
|
||||
}
|
||||
schedules {
|
||||
VARCHAR id PK
|
||||
VARCHAR name
|
||||
TEXT description "nullable"
|
||||
VARCHAR playbook
|
||||
VARCHAR target_type "nullable"
|
||||
VARCHAR target
|
||||
JSON extra_vars "nullable"
|
||||
VARCHAR schedule_type
|
||||
DATETIME schedule_time "nullable"
|
||||
VARCHAR recurrence_type "nullable"
|
||||
VARCHAR recurrence_time "nullable"
|
||||
TEXT recurrence_days "nullable"
|
||||
VARCHAR cron_expression "nullable"
|
||||
VARCHAR timezone "nullable"
|
||||
DATETIME start_at "nullable"
|
||||
DATETIME end_at "nullable"
|
||||
BOOLEAN enabled
|
||||
TEXT tags "nullable"
|
||||
DATETIME next_run "nullable"
|
||||
DATETIME last_run "nullable"
|
||||
VARCHAR last_status "nullable"
|
||||
INTEGER retry_on_failure "nullable"
|
||||
INTEGER timeout "nullable"
|
||||
VARCHAR notification_type "nullable"
|
||||
INTEGER run_count "nullable"
|
||||
INTEGER success_count "nullable"
|
||||
INTEGER failure_count "nullable"
|
||||
DATETIME created_at
|
||||
DATETIME updated_at
|
||||
DATETIME deleted_at "nullable"
|
||||
}
|
||||
tasks {
|
||||
VARCHAR id PK
|
||||
VARCHAR action
|
||||
VARCHAR target
|
||||
VARCHAR status
|
||||
VARCHAR playbook "nullable"
|
||||
DATETIME started_at "nullable"
|
||||
DATETIME completed_at "nullable"
|
||||
TEXT error_message "nullable"
|
||||
JSON result_data "nullable"
|
||||
DATETIME created_at
|
||||
}
|
||||
terminal_command_logs {
|
||||
INTEGER id PK
|
||||
DATETIME created_at
|
||||
VARCHAR host_id FK
|
||||
INTEGER user_id FK "nullable"
|
||||
VARCHAR terminal_session_id "nullable"
|
||||
TEXT command
|
||||
VARCHAR command_hash
|
||||
VARCHAR source
|
||||
BOOLEAN is_pinned
|
||||
BOOLEAN is_blocked
|
||||
VARCHAR blocked_reason "nullable"
|
||||
VARCHAR username "nullable"
|
||||
VARCHAR host_name "nullable"
|
||||
}
|
||||
terminal_sessions {
|
||||
VARCHAR id PK
|
||||
VARCHAR host_id
|
||||
VARCHAR host_name
|
||||
VARCHAR host_ip
|
||||
INTEGER user_id "nullable"
|
||||
VARCHAR username "nullable"
|
||||
VARCHAR token_hash
|
||||
INTEGER ttyd_port
|
||||
INTEGER ttyd_pid "nullable"
|
||||
VARCHAR mode
|
||||
VARCHAR status
|
||||
VARCHAR reason_closed "nullable"
|
||||
DATETIME created_at
|
||||
DATETIME last_seen_at
|
||||
DATETIME expires_at
|
||||
DATETIME closed_at "nullable"
|
||||
}
|
||||
users {
|
||||
INTEGER id PK
|
||||
VARCHAR username
|
||||
VARCHAR email "nullable"
|
||||
VARCHAR hashed_password
|
||||
VARCHAR role
|
||||
BOOLEAN is_active
|
||||
BOOLEAN is_superuser
|
||||
VARCHAR display_name "nullable"
|
||||
DATETIME created_at
|
||||
DATETIME updated_at
|
||||
DATETIME last_login "nullable"
|
||||
DATETIME password_changed_at "nullable"
|
||||
DATETIME deleted_at "nullable"
|
||||
}
|
||||
users ||--o{ alerts : "user_id"
|
||||
hosts ||--o{ bootstrap_status : "host_id"
|
||||
users ||--o{ container_customizations : "user_id"
|
||||
hosts ||--o{ container_customizations : "host_id"
|
||||
hosts ||--o{ docker_alerts : "host_id"
|
||||
hosts ||--o{ docker_containers : "host_id"
|
||||
hosts ||--o{ docker_images : "host_id"
|
||||
hosts ||--o{ docker_volumes : "host_id"
|
||||
users ||--o{ favorite_containers : "user_id"
|
||||
docker_containers ||--o{ favorite_containers : "docker_container_id"
|
||||
favorite_groups ||--o{ favorite_containers : "group_id"
|
||||
users ||--o{ favorite_groups : "user_id"
|
||||
hosts ||--o{ host_metrics : "host_id"
|
||||
schedules ||--o{ schedule_runs : "schedule_id"
|
||||
tasks ||--o{ schedule_runs : "task_id"
|
||||
hosts ||--o{ terminal_command_logs : "host_id"
|
||||
users ||--o{ terminal_command_logs : "user_id"
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.6 MiB |
@@ -0,0 +1,51 @@
|
||||
# 📊 Explorateur de Schéma Interactive
|
||||
|
||||
Ce répertoire contient un outil de documentation interactif permettant de visualiser et de naviguer dans le schéma de la base de données de l'application.
|
||||
|
||||
## 🔍 À propos de l'outil
|
||||
|
||||
Le fichier `database_schema_explorer.jsx` est une application React autonome qui :
|
||||
- Listes toutes les tables par catégorie (Docker, Ansible, Système, etc.).
|
||||
- Affiche les détails complets des colonnes (types, pk, fk, nullable, valeurs par défaut).
|
||||
- Propose une interface moderne avec recherche temps réel et filtrage par groupes.
|
||||
|
||||
## 🚀 Comment l'exécuter
|
||||
|
||||
### Méthode 1 : Zéro-Installation (La plus rapide pour consulter)
|
||||
Si vous ne souhaitez pas installer de nouvelles dépendances Node.js, ouvrez simplement le fichier suivant dans votre navigateur :
|
||||
|
||||
📄 `docs/database/standalone.html`
|
||||
|
||||
*Note : Cette méthode utilise des bibliothèques via CDN (React + Babel Standalone) pour transpiler le JSX à la volée directement dans le navigateur. C'est idéal pour une consultation ponctuelle.*
|
||||
|
||||
### Méthode 2 : Méthode Professionnelle (Vite)
|
||||
C'est la méthode recommandée pour un développement fluide avec Hot Module Replacement (HMR).
|
||||
|
||||
1. **Installer les dépendances** :
|
||||
```powershell
|
||||
npm install react react-dom
|
||||
npm install -D vite @vitejs/plugin-react
|
||||
```
|
||||
|
||||
2. **Lancer l'explorateur** :
|
||||
```powershell
|
||||
npx vite docs/database
|
||||
```
|
||||
|
||||
👉 L'application sera disponible sur `http://localhost:5173`.
|
||||
|
||||
## 🛠️ Configuration d'entrée
|
||||
|
||||
Un fichier `index.html` est présent dans ce répertoire pour servir de point d'entrée. Il charge dynamiquement le composant React et le monte dans la page.
|
||||
|
||||
## 💡 Astuce de Productivité
|
||||
|
||||
Vous pouvez ajouter un raccourci dans votre `package.json` pour un accès rapide :
|
||||
|
||||
```json
|
||||
"scripts": {
|
||||
"docs:db": "vite docs/database"
|
||||
}
|
||||
```
|
||||
|
||||
Cela vous permettra de lancer l'outil simplement avec : `npm run docs:db`.
|
||||
@@ -0,0 +1,22 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="icon" type="image/svg+xml" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>📊</text></svg>" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Base de données - Explorateur de Schéma</title>
|
||||
</head>
|
||||
<body style="margin: 0; background: #0d1117;">
|
||||
<div id="root"></div>
|
||||
<script type="module">
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom/client';
|
||||
import App from './database_schema_explorer.jsx';
|
||||
|
||||
// Rendu du composant principal
|
||||
ReactDOM.createRoot(document.getElementById('root')).render(
|
||||
React.createElement(React.StrictMode, null, React.createElement(App))
|
||||
);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,39 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="icon" type="image/svg+xml" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>📊</text></svg>" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Base de données - Explorateur de Schéma (CDN Mode)</title>
|
||||
|
||||
<script type="importmap">
|
||||
{
|
||||
"imports": {
|
||||
"react": "https://esm.sh/react@18",
|
||||
"react-dom": "https://esm.sh/react-dom@18",
|
||||
"react-dom/client": "https://esm.sh/react-dom@18/client"
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- Babel Standalone (Transpilation JSX) -->
|
||||
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
|
||||
</head>
|
||||
<body style="margin: 0; background: #0d1117;">
|
||||
<div id="root"></div>
|
||||
|
||||
<!-- Script principal utilisant Babel Standalone -->
|
||||
<script type="text/babel" data-type="module">
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom/client';
|
||||
import App from './database_schema_explorer.jsx';
|
||||
|
||||
const root = ReactDOM.createRoot(document.getElementById('root'));
|
||||
root.render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
</React.StrictMode>
|
||||
);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user