Coverage for heritrace/routes/main.py: 100%
74 statements
« prev ^ index » next coverage.py v7.6.12, created at 2025-06-24 11:39 +0000
« prev ^ index » next coverage.py v7.6.12, created at 2025-06-24 11:39 +0000
1import json
2import time
4from flask import (Blueprint, current_app, redirect, render_template, request,
5 url_for)
6from flask_login import login_required
7from heritrace.extensions import get_sparql
8from heritrace.utils.shacl_utils import determine_shape_for_classes
9from heritrace.utils.sparql_utils import (get_available_classes,
10 get_catalog_data,
11 get_deleted_entities_with_filtering,
12 get_sortable_properties)
13from SPARQLWrapper import JSON
15main_bp = Blueprint("main", __name__)
18@main_bp.route("/")
19def index():
20 return render_template("index.jinja")
23@main_bp.route("/catalogue")
24@login_required
25def catalogue():
26 page = int(request.args.get("page", 1))
27 per_page = int(request.args.get("per_page", 50))
28 selected_class = request.args.get("class")
29 sort_property = request.args.get("sort_property")
30 sort_direction = request.args.get("sort_direction", "ASC")
31 selected_shape = request.args.get("shape")
33 available_classes = get_available_classes()
35 if not selected_class and available_classes:
36 selected_class = available_classes[0]["uri"]
38 if not selected_shape and selected_class:
39 selected_shape = determine_shape_for_classes([selected_class])
41 catalog_data = get_catalog_data(
42 selected_class,
43 page,
44 per_page,
45 sort_property,
46 sort_direction,
47 selected_shape
48 )
50 return render_template(
51 "catalogue.jinja",
52 available_classes=available_classes,
53 selected_class=selected_class,
54 selected_shape=selected_shape,
55 page=page,
56 total_entity_pages=catalog_data["total_pages"],
57 per_page=per_page,
58 allowed_per_page=[50, 100, 200, 500],
59 sortable_properties=json.dumps(catalog_data["sortable_properties"]),
60 current_sort_property=catalog_data["sort_property"],
61 current_sort_direction=catalog_data["sort_direction"],
62 initial_entities=catalog_data["entities"],
63 )
66@main_bp.route("/time-vault")
67@login_required
68def time_vault():
69 """
70 Render the Time Vault page, which displays a list of deleted entities.
71 """
72 initial_page = request.args.get("page", 1, type=int)
73 initial_per_page = request.args.get("per_page", 50, type=int)
74 sort_property = request.args.get("sort_property", "deletionTime")
75 sort_direction = request.args.get("sort_direction", "DESC")
76 selected_class = request.args.get("class")
77 selected_shape = request.args.get("shape")
79 allowed_per_page = [50, 100, 200, 500]
81 initial_entities, available_classes, selected_class, selected_shape, sortable_properties, total_count = (
82 get_deleted_entities_with_filtering(
83 initial_page,
84 initial_per_page,
85 sort_property,
86 sort_direction,
87 selected_class,
88 selected_shape
89 )
90 )
92 sortable_properties = [
93 {"property": "deletionTime", "displayName": "Deletion Time", "sortType": "date"}
94 ]
96 if selected_class is not None:
97 entity_key = (selected_class, selected_shape)
98 sortable_properties.extend(
99 get_sortable_properties(entity_key)
100 )
102 sortable_properties = json.dumps(sortable_properties)
104 return render_template(
105 "time_vault.jinja",
106 available_classes=available_classes,
107 selected_class=selected_class,
108 selected_shape=selected_shape,
109 page=initial_page,
110 total_entity_pages=(total_count + initial_per_page - 1) // initial_per_page if total_count > 0 else 0,
111 per_page=initial_per_page,
112 allowed_per_page=allowed_per_page,
113 sortable_properties=sortable_properties,
114 current_sort_property=sort_property,
115 current_sort_direction=sort_direction,
116 initial_entities=initial_entities,
117 )
120@main_bp.route("/dataset-endpoint", methods=["POST"])
121@login_required
122def sparql_proxy():
123 query = request.form.get("query")
125 # Use SPARQLWrapper instead of direct requests
126 sparql_wrapper = get_sparql()
127 sparql_wrapper.setQuery(query)
128 sparql_wrapper.setReturnFormat(JSON)
130 # Implement retry mechanism
131 max_retries = 3
132 retry_delay = 1 # seconds
134 for attempt in range(max_retries):
135 try:
136 results = sparql_wrapper.query().convert()
137 return json.dumps(results), 200, {"Content-Type": "application/sparql-results+json"}
138 except Exception as e:
139 if attempt < max_retries - 1:
140 time.sleep(retry_delay)
141 retry_delay *= 2 # Exponential backoff
142 else:
143 current_app.logger.error(f"All SPARQL query attempts failed for query: {query}")
144 return json.dumps({"error": str(e)}), 500, {"Content-Type": "application/json"}
147@main_bp.route("/endpoint")
148@login_required
149def endpoint():
150 from heritrace.extensions import dataset_endpoint
152 return render_template("endpoint.jinja", dataset_endpoint=dataset_endpoint)
155@main_bp.route("/search")
156@login_required
157def search():
158 subject = request.args.get("q")
159 return redirect(url_for("entity.about", subject=subject))