Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[CONFIG] Taxon sheet and config #3312

Open
wants to merge 7 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
136 changes: 71 additions & 65 deletions backend/geonature/core/gn_synthese/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@
VMTaxrefListForautocomplete,
)

from geonature import app
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Souvent, on passe plutôt par le current_app de flask


routes = Blueprint("gn_synthese", __name__)

Expand Down Expand Up @@ -957,81 +958,86 @@ def general_stats(permissions):
}
return data

## ############################################################################
## TAXON SHEET ROUTES
## ############################################################################

@routes.route("/taxon_stats/<int:cd_nom>", methods=["GET"])
@permissions.check_cruved_scope("R", get_scope=True, module_code="SYNTHESE")
@json_resp
def taxon_stats(scope, cd_nom):
"""Return stats for a specific taxon"""
if app.config["SYNTHESE"]["ENABLE_TAXON_SHEETS"]:

area_type = request.args.get("area_type")
@routes.route("/taxon_stats/<int:cd_nom>", methods=["GET"])
@permissions.check_cruved_scope("R", get_scope=True, module_code="SYNTHESE")
@json_resp
def taxon_stats(scope, cd_nom):
"""Return stats for a specific taxon"""

if not area_type:
raise BadRequest("Missing area_type parameter")
area_type = request.args.get("area_type")

# Ensure area_type is valid
valid_area_types = (
db.session.query(BibAreasTypes.type_code)
.distinct()
.filter(BibAreasTypes.type_code == area_type)
.scalar()
)
if not valid_area_types:
raise BadRequest("Invalid area_type")

# Subquery to fetch areas based on area_type
areas_subquery = (
select([LAreas.id_area])
.where(LAreas.id_type == BibAreasTypes.id_type)
.where(BibAreasTypes.type_code == area_type)
.alias("areas")
)
cd_ref = db.session.scalar(select(Taxref.cd_ref).where(Taxref.cd_nom == cd_nom))
taxref_cd_nom_list = db.session.scalars(select(Taxref.cd_nom).where(Taxref.cd_ref == cd_ref))
if not area_type:
raise BadRequest("Missing area_type parameter")

# Main query to fetch stats
query = (
select(
[
func.count(distinct(Synthese.id_synthese)).label("observation_count"),
func.count(distinct(Synthese.observers)).label("observer_count"),
func.count(distinct(areas_subquery.c.id_area)).label("area_count"),
func.min(Synthese.altitude_min).label("altitude_min"),
func.max(Synthese.altitude_max).label("altitude_max"),
func.min(Synthese.date_min).label("date_min"),
func.max(Synthese.date_max).label("date_max"),
]
# Ensure area_type is valid
valid_area_types = (
db.session.query(BibAreasTypes.type_code)
.distinct()
.filter(BibAreasTypes.type_code == area_type)
.scalar()
)
.select_from(
sa.join(
Synthese,
CorAreaSynthese,
Synthese.id_synthese == CorAreaSynthese.id_synthese,
if not valid_area_types:
raise BadRequest("Invalid area_type")

# Subquery to fetch areas based on area_type
areas_subquery = (
select([LAreas.id_area])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
select([LAreas.id_area])
select(LAreas.id_area)

.where(LAreas.id_type == BibAreasTypes.id_type)
.where(BibAreasTypes.type_code == area_type)
Comment on lines +992 to +993
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
.where(LAreas.id_type == BibAreasTypes.id_type)
.where(BibAreasTypes.type_code == area_type)
.where(LAreas.id_type == BibAreasTypes.id_type, BibAreasTypes.type_code == area_type)

.alias("areas")
)
cd_ref = db.session.scalar(select(Taxref.cd_ref).where(Taxref.cd_nom == cd_nom))
taxref_cd_nom_list = db.session.scalars(select(Taxref.cd_nom).where(Taxref.cd_ref == cd_ref))

# Main query to fetch stats
query = (
select(
[
func.count(distinct(Synthese.id_synthese)).label("observation_count"),
func.count(distinct(Synthese.observers)).label("observer_count"),
func.count(distinct(areas_subquery.c.id_area)).label("area_count"),
func.min(Synthese.altitude_min).label("altitude_min"),
func.max(Synthese.altitude_max).label("altitude_max"),
func.min(Synthese.date_min).label("date_min"),
func.max(Synthese.date_max).label("date_max"),
]
)
.join(areas_subquery, CorAreaSynthese.id_area == areas_subquery.c.id_area)
.join(LAreas, CorAreaSynthese.id_area == LAreas.id_area)
.join(BibAreasTypes, LAreas.id_type == BibAreasTypes.id_type)
.select_from(
sa.join(
Synthese,
CorAreaSynthese,
Synthese.id_synthese == CorAreaSynthese.id_synthese,
)
.join(areas_subquery, CorAreaSynthese.id_area == areas_subquery.c.id_area)
.join(LAreas, CorAreaSynthese.id_area == LAreas.id_area)
.join(BibAreasTypes, LAreas.id_type == BibAreasTypes.id_type)
)
.where(Synthese.cd_nom.in_(taxref_cd_nom_list))
)
.where(Synthese.cd_nom.in_(taxref_cd_nom_list))
)

synthese_query_obj = SyntheseQuery(Synthese, query, {})
synthese_query_obj.filter_query_with_cruved(g.current_user, scope)
result = DB.session.execute(synthese_query_obj.query)
synthese_stats = result.fetchone()

data = {
"cd_ref": cd_nom,
"observation_count": synthese_stats["observation_count"],
"observer_count": synthese_stats["observer_count"],
"area_count": synthese_stats["area_count"],
"altitude_min": synthese_stats["altitude_min"],
"altitude_max": synthese_stats["altitude_max"],
"date_min": synthese_stats["date_min"],
"date_max": synthese_stats["date_max"],
}
synthese_query_obj = SyntheseQuery(Synthese, query, {})
synthese_query_obj.filter_query_with_cruved(g.current_user, scope)
result = DB.session.execute(synthese_query_obj.query)
synthese_stats = result.fetchone()

data = {
"cd_ref": cd_nom,
"observation_count": synthese_stats["observation_count"],
"observer_count": synthese_stats["observer_count"],
"area_count": synthese_stats["area_count"],
"altitude_min": synthese_stats["altitude_min"],
"altitude_max": synthese_stats["altitude_max"],
"date_min": synthese_stats["date_min"],
"date_max": synthese_stats["date_max"],
}

return data
return data


@routes.route("/taxons_tree", methods=["GET"])
Expand Down
5 changes: 3 additions & 2 deletions backend/geonature/utils/config_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -279,8 +279,8 @@ class ExportObservationSchema(Schema):
class TaxonSheet(Schema):
# --------------------------------------------------------------------
# SYNTHESE - TAXON_SHEET
ENABLE_PROFILE = fields.Boolean(load_default=True)
ENABLE_TAXONOMY = fields.Boolean(load_default=True)
ENABLE_TAB_PROFILES = fields.Boolean(load_default=True)
edelclaux marked this conversation as resolved.
Show resolved Hide resolved
ENABLE_TAB_TAXONOMY = fields.Boolean(load_default=True)


class Synthese(Schema):
Expand Down Expand Up @@ -439,6 +439,7 @@ class Synthese(Schema):

# --------------------------------------------------------------------
# SYNTHESE - TAXON_SHEET
ENABLE_TAXON_SHEETS = fields.Boolean(load_default=True)
TAXON_SHEET = fields.Nested(TaxonSheet, load_default=TaxonSheet().load({}))

@pre_load
Expand Down
6 changes: 4 additions & 2 deletions config/default_config.toml.example
Original file line number Diff line number Diff line change
Expand Up @@ -441,12 +441,14 @@ MEDIA_CLEAN_CRONTAB = "0 1 * * *"
# Seulement les données de présence
cd_nomenclature_observation_status = ['Pr']

# Activer l'affichage des informations liées à la fiche taxon dans la synthèse
ENABLE_TAXON_SHEETS = true
[SYNTHESE.TAXON_SHEET]
# Options dédiées à la fiche taxon
# Permet d'activer ou non l'onglet "Profil"
ENABLE_PROFILE = true
ENABLE_TAB_PROFILES = true
edelclaux marked this conversation as resolved.
Show resolved Hide resolved
# Permet d'activer ou non l'onglet "Taxonomie"
ENABLE_TAXONOMY = true
ENABLE_TAB_TAXONOMY = true

# Gestion des demandes d'inscription
[ACCOUNT_MANAGEMENT]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ <h4 class="mr-auto gn-color">
<a
color="primary"
class="btn btn-xs align-self-start mr-2 link-infos"
*ngIf="selectedObsTaxonDetail && config.FRONTEND['ENABLE_PROFILES']"
*ngIf="selectedObsTaxonDetail && config.SYNTHESE.ENABLE_TAXON_SHEETS"
[routerLink]="['/synthese/taxon', selectedObsTaxonDetail?.cd_ref]"
target="_blank"
mat-stroked-button
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@
<a
class="Link"
[routerLink]="['taxon/' + row.cd_nom]"
*ngIf="row.hasOwnProperty('cd_nom'); else cellDefault"
*ngIf="config.SYNTHESE.ENABLE_TAXON_SHEETS && row.hasOwnProperty('cd_nom'); else cellDefault"
matTooltip="Afficher la fiche du taxon"
>
<ng-container *ngTemplateOutlet="cellDefault"></ng-container>
Expand Down
1 change: 1 addition & 0 deletions frontend/src/app/syntheseModule/synthese.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ const routes: Routes = [
{
path: 'taxon/:cd_ref',
component: TaxonSheetComponent,
canActivate: [RouteService],
canActivateChild: [RouteService],
children: [
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
RouterStateSnapshot,
Router,
CanActivateChild,
CanActivate
} from '@angular/router';
import { ConfigService } from '@geonature/services/config.service';
import { Observable } from 'rxjs';
Expand All @@ -28,21 +29,21 @@ export const ALL_TAXON_SHEET_ADVANCED_INFOS_ROUTES: Array<Tab> = [
{
label: 'Taxonomie',
path: 'taxonomy',
configEnabledField: 'ENABLE_TAXONOMY',
configEnabledField: 'ENABLE_TAB_TAXONOMY',
component: TabTaxonomyComponent,
},
{
label: 'Profil',
path: 'profile',
configEnabledField: 'ENABLE_PROFILE',
configEnabledField: 'ENABLE_TAB_PROFILES',
component: TabProfileComponent,
},
];

@Injectable({
providedIn: 'root',
})
export class RouteService implements CanActivateChild {
export class RouteService implements CanActivate, CanActivateChild {
readonly TAB_LINKS = [];
constructor(
private _config: ConfigService,
Expand All @@ -55,11 +56,19 @@ export class RouteService implements CanActivateChild {
);
}
}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
if(!this._config.SYNTHESE.ENABLE_TAXON_SHEETS){
this._router.navigate(['/404'], { skipLocationChange: true });
return false;
}

return true;
}

canActivateChild(
childRoute: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<boolean> | Promise<boolean> | boolean {
): boolean {
const targetedPath = childRoute.routeConfig.path;
if (this.TAB_LINKS.map((tab) => tab.path).includes(targetedPath)) {
return true;
Expand Down
Loading