This commit is contained in:
parent
82c334b131
commit
b0c9d319ef
@ -745,7 +745,7 @@ def create_app(config: AppConfig = CONFIG) -> Flask:
|
|||||||
}
|
}
|
||||||
|
|
||||||
def build_full_graph_payload(
|
def build_full_graph_payload(
|
||||||
max_nodes: int, *, highlight_id: Optional[str] = None
|
max_nodes: Optional[int], *, highlight_id: Optional[str] = None
|
||||||
) -> Dict[str, Any]:
|
) -> Dict[str, Any]:
|
||||||
"""
|
"""
|
||||||
Attempt to render the entire reference graph by gathering every video that
|
Attempt to render the entire reference graph by gathering every video that
|
||||||
@ -776,7 +776,8 @@ def create_app(config: AppConfig = CONFIG) -> Flask:
|
|||||||
nodes: Dict[str, Dict[str, Any]] = {}
|
nodes: Dict[str, Dict[str, Any]] = {}
|
||||||
links: List[Dict[str, Any]] = []
|
links: List[Dict[str, Any]] = []
|
||||||
link_seen: Set[Tuple[str, str, str]] = set()
|
link_seen: Set[Tuple[str, str, str]] = set()
|
||||||
batch_size = min(500, max(50, max_nodes * 2))
|
node_limit = max_nodes if max_nodes and max_nodes > 0 else None
|
||||||
|
batch_size = 500 if node_limit is None else min(500, max(50, node_limit * 2))
|
||||||
truncated = False
|
truncated = False
|
||||||
|
|
||||||
def ensure_node(node_id: Optional[str], doc: Optional[Dict[str, Any]] = None) -> bool:
|
def ensure_node(node_id: Optional[str], doc: Optional[Dict[str, Any]] = None) -> bool:
|
||||||
@ -799,7 +800,7 @@ def create_app(config: AppConfig = CONFIG) -> Flask:
|
|||||||
if not existing.get("date") and doc.get("date"):
|
if not existing.get("date") and doc.get("date"):
|
||||||
existing["date"] = doc.get("date")
|
existing["date"] = doc.get("date")
|
||||||
return True
|
return True
|
||||||
if len(nodes) >= max_nodes:
|
if node_limit is not None and len(nodes) >= node_limit:
|
||||||
return False
|
return False
|
||||||
channel_name = None
|
channel_name = None
|
||||||
channel_id = None
|
channel_id = None
|
||||||
@ -836,7 +837,7 @@ def create_app(config: AppConfig = CONFIG) -> Flask:
|
|||||||
if not hits:
|
if not hits:
|
||||||
break
|
break
|
||||||
for hit in hits:
|
for hit in hits:
|
||||||
if len(nodes) >= max_nodes:
|
if node_limit is not None and len(nodes) >= node_limit:
|
||||||
truncated = True
|
truncated = True
|
||||||
stop_fetch = True
|
stop_fetch = True
|
||||||
break
|
break
|
||||||
@ -996,14 +997,17 @@ def create_app(config: AppConfig = CONFIG) -> Flask:
|
|||||||
depth = 1
|
depth = 1
|
||||||
depth = max(0, min(depth, 3))
|
depth = max(0, min(depth, 3))
|
||||||
|
|
||||||
|
if full_graph:
|
||||||
|
max_nodes = None
|
||||||
|
else:
|
||||||
try:
|
try:
|
||||||
max_nodes = int(request.args.get("max_nodes", "200"))
|
max_nodes = int(request.args.get("max_nodes", "200"))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
max_nodes = 200
|
max_nodes = 200
|
||||||
max_nodes = max(10, min(max_nodes, 800 if full_graph else 400))
|
max_nodes = max(10, min(max_nodes, 400))
|
||||||
|
|
||||||
if full_graph:
|
if full_graph:
|
||||||
payload = build_full_graph_payload(max_nodes, highlight_id=video_id or None)
|
payload = build_full_graph_payload(None, highlight_id=video_id or None)
|
||||||
else:
|
else:
|
||||||
payload = build_graph_payload(video_id, depth, max_nodes)
|
payload = build_graph_payload(video_id, depth, max_nodes)
|
||||||
if not payload["nodes"]:
|
if not payload["nodes"]:
|
||||||
@ -1011,7 +1015,9 @@ def create_app(config: AppConfig = CONFIG) -> Flask:
|
|||||||
jsonify({"error": f"Video '{video_id}' was not found in the index."}),
|
jsonify({"error": f"Video '{video_id}' was not found in the index."}),
|
||||||
404,
|
404,
|
||||||
)
|
)
|
||||||
payload["meta"]["max_nodes"] = max_nodes
|
payload["meta"]["max_nodes"] = (
|
||||||
|
len(payload["nodes"]) if full_graph else max_nodes
|
||||||
|
)
|
||||||
return jsonify(payload)
|
return jsonify(payload)
|
||||||
|
|
||||||
@app.route("/api/years")
|
@app.route("/api/years")
|
||||||
|
|||||||
@ -135,6 +135,7 @@
|
|||||||
let currentMaxNodes = sanitizeMaxNodes(maxNodesInput.value);
|
let currentMaxNodes = sanitizeMaxNodes(maxNodesInput.value);
|
||||||
let currentSimulation = null;
|
let currentSimulation = null;
|
||||||
let currentFullGraph = false;
|
let currentFullGraph = false;
|
||||||
|
let previousMaxNodesValue = maxNodesInput ? maxNodesInput.value : "200";
|
||||||
|
|
||||||
function setStatus(message, isError = false) {
|
function setStatus(message, isError = false) {
|
||||||
if (!statusEl) return;
|
if (!statusEl) return;
|
||||||
@ -165,6 +166,18 @@
|
|||||||
if (depthInput) {
|
if (depthInput) {
|
||||||
depthInput.disabled = enabled;
|
depthInput.disabled = enabled;
|
||||||
}
|
}
|
||||||
|
if (maxNodesInput) {
|
||||||
|
if (enabled) {
|
||||||
|
previousMaxNodesValue = maxNodesInput.value || previousMaxNodesValue || "200";
|
||||||
|
maxNodesInput.value = "0";
|
||||||
|
maxNodesInput.disabled = true;
|
||||||
|
} else {
|
||||||
|
if (maxNodesInput.disabled) {
|
||||||
|
maxNodesInput.value = previousMaxNodesValue || "200";
|
||||||
|
}
|
||||||
|
maxNodesInput.disabled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (videoInput) {
|
if (videoInput) {
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
videoInput.removeAttribute("required");
|
videoInput.removeAttribute("required");
|
||||||
@ -181,10 +194,11 @@
|
|||||||
}
|
}
|
||||||
if (fullGraphMode) {
|
if (fullGraphMode) {
|
||||||
params.set("full_graph", "1");
|
params.set("full_graph", "1");
|
||||||
|
params.set("max_nodes", "0");
|
||||||
} else {
|
} else {
|
||||||
params.set("depth", String(depth));
|
params.set("depth", String(depth));
|
||||||
}
|
|
||||||
params.set("max_nodes", String(maxNodes));
|
params.set("max_nodes", String(maxNodes));
|
||||||
|
}
|
||||||
const response = await fetch(`/api/graph?${params.toString()}`);
|
const response = await fetch(`/api/graph?${params.toString()}`);
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
const errorPayload = await response.json().catch(() => ({}));
|
const errorPayload = await response.json().catch(() => ({}));
|
||||||
@ -445,8 +459,8 @@
|
|||||||
setStatus("Please enter a video ID.", true);
|
setStatus("Please enter a video ID.", true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const safeDepth = wantsFull ? 0 : sanitizeDepth(depth);
|
const safeDepth = wantsFull ? currentDepth || 1 : sanitizeDepth(depth);
|
||||||
const safeMaxNodes = sanitizeMaxNodes(maxNodes);
|
const safeMaxNodes = wantsFull ? 0 : sanitizeMaxNodes(maxNodes);
|
||||||
|
|
||||||
if (updateInputs) {
|
if (updateInputs) {
|
||||||
videoInput.value = sanitizedId;
|
videoInput.value = sanitizedId;
|
||||||
@ -630,11 +644,12 @@
|
|||||||
if (fullGraphMode) {
|
if (fullGraphMode) {
|
||||||
next.searchParams.set("full_graph", "1");
|
next.searchParams.set("full_graph", "1");
|
||||||
next.searchParams.delete("depth");
|
next.searchParams.delete("depth");
|
||||||
|
next.searchParams.set("max_nodes", "0");
|
||||||
} else {
|
} else {
|
||||||
next.searchParams.set("depth", String(depth));
|
next.searchParams.set("depth", String(depth));
|
||||||
next.searchParams.delete("full_graph");
|
next.searchParams.delete("full_graph");
|
||||||
}
|
|
||||||
next.searchParams.set("max_nodes", String(maxNodes));
|
next.searchParams.set("max_nodes", String(maxNodes));
|
||||||
|
}
|
||||||
if (labelSize && labelSize !== "normal") {
|
if (labelSize && labelSize !== "normal") {
|
||||||
next.searchParams.set("label_size", labelSize);
|
next.searchParams.set("label_size", labelSize);
|
||||||
} else {
|
} else {
|
||||||
@ -647,7 +662,11 @@
|
|||||||
const params = new URLSearchParams(window.location.search);
|
const params = new URLSearchParams(window.location.search);
|
||||||
const videoId = sanitizeId(params.get("video_id"));
|
const videoId = sanitizeId(params.get("video_id"));
|
||||||
const depth = sanitizeDepth(params.get("depth") || "");
|
const depth = sanitizeDepth(params.get("depth") || "");
|
||||||
const maxNodes = sanitizeMaxNodes(params.get("max_nodes") || "");
|
const rawMaxNodes = params.get("max_nodes");
|
||||||
|
let maxNodes = sanitizeMaxNodes(rawMaxNodes || "");
|
||||||
|
if (rawMaxNodes && rawMaxNodes.trim() === "0") {
|
||||||
|
maxNodes = 0;
|
||||||
|
}
|
||||||
const labelSizeParam = params.get("label_size");
|
const labelSizeParam = params.get("label_size");
|
||||||
const fullGraphParam = params.get("full_graph");
|
const fullGraphParam = params.get("full_graph");
|
||||||
const viewFull =
|
const viewFull =
|
||||||
@ -656,7 +675,7 @@
|
|||||||
videoInput.value = videoId;
|
videoInput.value = videoId;
|
||||||
}
|
}
|
||||||
depthInput.value = String(depth);
|
depthInput.value = String(depth);
|
||||||
maxNodesInput.value = String(maxNodes);
|
maxNodesInput.value = String(viewFull ? 0 : maxNodes);
|
||||||
if (fullGraphToggle) {
|
if (fullGraphToggle) {
|
||||||
fullGraphToggle.checked = !!viewFull;
|
fullGraphToggle.checked = !!viewFull;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user