index.community/backend/lib/backend_web/views/graph_view.ex

83 lines
2.2 KiB
Elixir

defmodule BackendWeb.GraphView do
use BackendWeb, :view
alias BackendWeb.GraphView
def render("index.json", %{nodes: nodes, edges: edges}) do
statuses_per_day =
nodes
|> Enum.map(fn %{statuses_per_day: statuses_per_day} -> statuses_per_day end)
|> Enum.filter(fn s -> s != nil end)
statuses_per_user_per_day =
nodes
|> Enum.filter(fn %{statuses_per_day: statuses_per_day, user_count: user_count} ->
statuses_per_day != nil and user_count != nil and user_count > 0
end)
|> Enum.map(fn %{statuses_per_day: statuses_per_day, user_count: user_count} ->
statuses_per_day / user_count
end)
%{
graph: %{
nodes: render_many(nodes, GraphView, "node.json", as: :node),
edges: render_many(edges, GraphView, "edge.json", as: :edge)
},
metadata: %{
ranges: %{
# Make sure that these keys match what's in the "node.json" render function.
statusesPerDay: [
Enum.min(statuses_per_day, fn -> nil end),
Enum.max(statuses_per_day, fn -> nil end)
],
statusesPerUserPerDay: [
Enum.min(statuses_per_user_per_day, fn -> nil end),
Enum.max(statuses_per_user_per_day, fn -> nil end)
]
}
}
}
end
def render("node.json", %{node: node}) do
size =
case node.user_count > 1 do
true -> :math.log(node.user_count)
false -> 1
end
statuses_per_user_per_day =
if node.statuses_per_day != nil and node.user_count != nil and node.user_count > 0 do
node.statuses_per_day / node.user_count
else
nil
end
# This is the format that cytoscape.js expects.
%{
data: %{
id: node.domain,
label: node.domain,
size: size,
type: node.type,
statusesPerDay: node.statuses_per_day,
statusesPerUserPerDay: statuses_per_user_per_day
},
position: %{
x: node.x,
y: node.y
}
}
end
def render("edge.json", %{edge: edge}) do
%{
data: %{
id: edge.id,
source: edge.source_domain,
target: edge.target_domain,
weight: edge.weight
}
}
end
end