Petites améliorations de formulation et d'UI
This commit is contained in:
+3
-2
@@ -312,8 +312,9 @@ def toggle_navbar_collapse(n, is_open):
|
||||
)
|
||||
def _auth_nav(_):
|
||||
if current_user.is_authenticated:
|
||||
email = current_user.email
|
||||
display = email if len(email) <= 30 else email[:27] + "..."
|
||||
# email = current_user.email
|
||||
# display = email if len(email) <= 30 else email[:27] + "..."
|
||||
display = "★★★"
|
||||
return dbc.NavItem(dbc.NavLink(display, href="/compte/admin"))
|
||||
return dbc.NavItem(dbc.NavLink("Connexion", href="/connexion"))
|
||||
|
||||
|
||||
+5
-1
@@ -132,10 +132,14 @@ def get_sources_tables(source_path) -> html.Div:
|
||||
+ pl.lit('">')
|
||||
+ pl.col("nom")
|
||||
+ pl.lit("</a>")
|
||||
).alias("nom")
|
||||
).alias("nom"),
|
||||
)
|
||||
dff = dff.drop("url", "unique")
|
||||
dff = dff.sort(by=["nb_marchés"], descending=True)
|
||||
dff = dff.with_columns(
|
||||
pl.col("nb_marchés").map_elements(format_number, return_dtype=pl.String),
|
||||
pl.col("nb_acheteurs").map_elements(format_number, return_dtype=pl.String),
|
||||
)
|
||||
|
||||
columns = {
|
||||
"nom": "Nom de la source",
|
||||
|
||||
@@ -4,20 +4,8 @@ from dash import Input, Output, State, callback, html
|
||||
SECTIONS = [
|
||||
{"key": "presentation", "label": "Présentation", "href": "/a-propos/presentation"},
|
||||
{"key": "explorer", "label": "Explorer le projet", "href": "/a-propos/explorer"},
|
||||
{"key": "sources", "label": "Sources de données", "href": "/a-propos/sources"},
|
||||
{"key": "qualite", "label": "Qualité des données", "href": "/a-propos/qualite"},
|
||||
{
|
||||
"key": "donnees-brutes",
|
||||
"label": "Données brutes",
|
||||
"href": "/a-propos/donnees-brutes",
|
||||
},
|
||||
{"key": "contribuer", "label": "Contribuer", "href": "/a-propos/contribuer"},
|
||||
{"key": "contact", "label": "Contact", "href": "/a-propos/contact"},
|
||||
{
|
||||
"key": "mentions-legales",
|
||||
"label": "Mentions légales",
|
||||
"href": "/a-propos/mentions-legales",
|
||||
},
|
||||
{"key": "donnees", "label": "Données", "href": "/a-propos/donnees"},
|
||||
# {"key": "contribuer", "label": "Contribuer", "href": "/a-propos/contribuer"},
|
||||
{
|
||||
"key": "abonnement",
|
||||
"label": "Abonnement",
|
||||
@@ -28,6 +16,12 @@ SECTIONS = [
|
||||
"label": "Roadmap",
|
||||
"href": "/a-propos/roadmap",
|
||||
},
|
||||
{"key": "contact", "label": "Contact", "href": "/a-propos/contact"},
|
||||
{
|
||||
"key": "mentions-legales",
|
||||
"label": "Mentions légales",
|
||||
"href": "/a-propos/mentions-legales",
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
|
||||
@@ -11,6 +11,11 @@ register_page(
|
||||
image_url=META_CONTENT["image_url"],
|
||||
)
|
||||
|
||||
abonnement_features = dcc.Markdown("""
|
||||
- sauvegarde de vues dans la page Tableau
|
||||
- vote pour les fonctionnalités à développer en priorité (une fois la période d'essai terminée)
|
||||
""")
|
||||
|
||||
|
||||
def layout(**_):
|
||||
contenu = html.Div(
|
||||
@@ -18,42 +23,46 @@ def layout(**_):
|
||||
html.H2("Abonnement"),
|
||||
dcc.Markdown(
|
||||
"""
|
||||
L'accès aux fonctionnalités de base de colibre est gratuit et sans inscription.
|
||||
Un abonnement payant donne accès à des fonctionnalités supplémentaires qui nécessitent la création d'un compte.
|
||||
L'accès aux fonctionnalités de base de colibre est gratuit et sans inscription. Il est également possible de créer un compte gratuitement via le menu [Connexion](/connexion). Une fois le compte créé,
|
||||
il est possible de souscrire à un abonnement mensuel qui donne accès à des fonctionnalités supplémentaires. Cet abonnement s'adresse tant aux professionnel·les qu'aux particuliers.
|
||||
"""
|
||||
),
|
||||
html.H4("Fonctionnalités incluses"),
|
||||
dcc.Markdown(
|
||||
"""
|
||||
Les fonctionnalités accessibles aux abonnés évoluent au fil du développement du service.
|
||||
La liste à jour est visible depuis la [page d'abonnement](/compte/abonnement).
|
||||
Les fonctionnalités accessibles aux abonné·es évoluent au fil du développement du service.
|
||||
|
||||
Fonctionnalités réservées aux abonné·es :
|
||||
"""
|
||||
),
|
||||
abonnement_features,
|
||||
dcc.Markdown("""
|
||||
Les fonctionnalités en cours de développement et soumises au vote sont visibles dans la section [Roadmap](/a-propos/roadmap)."""),
|
||||
html.H4("Tarifs"),
|
||||
dcc.Markdown(
|
||||
"""
|
||||
Deux formules sont proposées :
|
||||
|
||||
- **Abonnement** — 20 € HT / mois (soit 24 € TTC)
|
||||
- **Abonnement de soutien** — 50 € HT / mois (soit 60 € TTC) — mêmes fonctionnalités, contribution renforcée au projet
|
||||
- **Abonnement de soutien ✊** — 50 € HT / mois (soit 60 € TTC) — mêmes fonctionnalités, contribution renforcée au projet
|
||||
|
||||
La TVA applicable est de 20 %. Les prix TTC sont affichés lors de la souscription.
|
||||
La TVA applicable en France est de 20 %.
|
||||
"""
|
||||
),
|
||||
html.H4("Période d'essai"),
|
||||
dcc.Markdown(
|
||||
"""
|
||||
Une période d'essai gratuite peut être proposée lors de la souscription.
|
||||
Une période d'essai gratuite est proposée lors de la souscription.
|
||||
Sa durée est indiquée avant validation. Aucun prélèvement n'est effectué pendant cette période.
|
||||
À son terme, l'abonnement est activé et facturé automatiquement.
|
||||
|
||||
La période d'essai est accordée une seule fois par utilisateur.
|
||||
La période d'essai est accordée une seule fois par compte.
|
||||
"""
|
||||
),
|
||||
html.H4("Facturation et paiement"),
|
||||
dcc.Markdown(
|
||||
"""
|
||||
L'abonnement est facturé mensuellement, à la date anniversaire de la souscription.
|
||||
L'abonnement est facturé mensuellement, à la date anniversaire de la souscription, et donne lieu à l'émission d'une facture visible sur le compte de l'abonné·e.
|
||||
Le paiement est traité par [Frisbii](https://www.frisbii.com), prestataire européen de paiement en ligne.
|
||||
Les coordonnées bancaires sont conservées exclusivement par Frisbii et ne sont pas transmises à colibre.
|
||||
"""
|
||||
@@ -65,15 +74,16 @@ L'abonnement peut être résilié à tout moment depuis l'espace [Mon compte](/c
|
||||
La résiliation prend effet à la fin de la période mensuelle en cours : l'accès aux fonctionnalités payantes est maintenu jusqu'à cette date, sans remboursement au prorata.
|
||||
"""
|
||||
),
|
||||
html.H4("Données personnelles"),
|
||||
html.H4("Données recueillies"),
|
||||
dcc.Markdown(
|
||||
"""
|
||||
La gestion de l'abonnement implique le traitement de données personnelles, réparties entre colibre et Frisbii (prestataire de paiement).
|
||||
La gestion de l'abonnement implique le traitement de données, réparties entre colibre et Frisbii (prestataire de paiement). Conformément au RGPD, colibre ne receuille que les données strictement nécessaire
|
||||
au bon fonctionnement du site et de la facturation.
|
||||
|
||||
**Données stockées par colibre :**
|
||||
|
||||
- Adresse e-mail (identification du compte)
|
||||
- Numéro SIRET (si renseigné, conservé pour pré-remplir les futures souscriptions)
|
||||
- Numéro SIRET (optionnel, si renseigné, conservé pour pré-remplir les futures souscriptions)
|
||||
|
||||
**Données stockées par Frisbii :**
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ from flask_login import current_user
|
||||
|
||||
from src.pages._compte_shell import account_guard, account_shell
|
||||
from src.subscriptions import db, plans
|
||||
from src.utils.frontend import format_date_french
|
||||
|
||||
register_page(
|
||||
__name__,
|
||||
@@ -129,7 +130,7 @@ def _explainer():
|
||||
|
||||
def _active_view(row):
|
||||
meta = plans.plan_meta(row["plan"]) or {"label": row["plan"]}
|
||||
end = row["current_period_end"]
|
||||
end = format_date_french(row["current_period_end"])
|
||||
blocks = [html.H3(meta["label"], className="mb-3")]
|
||||
|
||||
if row["status"] == "pending":
|
||||
@@ -167,7 +168,7 @@ def _active_view(row):
|
||||
dbc.Alert(f"Abonnement résilié, actif jusqu'au {end}.", color="warning")
|
||||
)
|
||||
else:
|
||||
blocks.append(html.P(f"Prochain renouvellement : {end}"))
|
||||
blocks.append(html.P(f"Prochaine facturation : {end}"))
|
||||
|
||||
if row["status"] in ("pending", "trial", "active"):
|
||||
blocks.append(
|
||||
@@ -182,7 +183,8 @@ def _active_view(row):
|
||||
return html.Div(blocks)
|
||||
|
||||
|
||||
def _resiliation_modal(end):
|
||||
def _resiliation_modal(end_raw):
|
||||
end = format_date_french(end_raw) if end_raw else None
|
||||
if end:
|
||||
body_text = (
|
||||
f"Êtes-vous sûr de vouloir mettre fin à votre abonnement ? "
|
||||
|
||||
@@ -121,6 +121,11 @@ def roadmap_content(
|
||||
body.append(dbc.ListGroup(_en_cours_items(issues["en_cours"]), className="mb-4"))
|
||||
can_vote = editable and balance is not None and balance > 0
|
||||
body.append(html.H3("Au vote"))
|
||||
body.append(
|
||||
html.P(
|
||||
"Les abonné·es votent pour les fonctionnalités à développer en priorité."
|
||||
)
|
||||
)
|
||||
body.append(
|
||||
html.Div(
|
||||
dbc.ListGroup(
|
||||
|
||||
@@ -1,6 +1,43 @@
|
||||
from datetime import datetime
|
||||
|
||||
from src.utils.data import DATA_SCHEMA
|
||||
|
||||
|
||||
def format_date_french(date_input) -> str:
|
||||
"""Format a date as 'jour mois' (e.g., '1er janvier', '15 décembre')."""
|
||||
if isinstance(date_input, str):
|
||||
try:
|
||||
date_obj = datetime.fromisoformat(date_input)
|
||||
except (ValueError, TypeError):
|
||||
return str(date_input)
|
||||
elif isinstance(date_input, datetime):
|
||||
date_obj = date_input
|
||||
else:
|
||||
return str(date_input)
|
||||
|
||||
day = date_obj.day
|
||||
month_names = [
|
||||
"janvier",
|
||||
"février",
|
||||
"mars",
|
||||
"avril",
|
||||
"mai",
|
||||
"juin",
|
||||
"juillet",
|
||||
"août",
|
||||
"septembre",
|
||||
"octobre",
|
||||
"novembre",
|
||||
"décembre",
|
||||
]
|
||||
month = month_names[date_obj.month - 1]
|
||||
|
||||
if day == 1:
|
||||
return f"1er {month}"
|
||||
else:
|
||||
return f"{day} {month}"
|
||||
|
||||
|
||||
def get_button_properties(height):
|
||||
if height > 65000:
|
||||
download_disabled = True
|
||||
|
||||
Reference in New Issue
Block a user