From 2e61b706023f3bb833b7a93c3336ec81a7b189d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tao=20Bojl=C3=A9n?= <2803708-taobojlen@users.noreply.gitlab.com> Date: Thu, 18 Jul 2019 20:05:16 +0000 Subject: [PATCH] Hide insular instances --- backend/lib/backend/api.ex | 34 ++------ backend/lib/backend/scheduler.ex | 15 ++-- .../lib/backend_web/views/instance_view.ex | 2 - frontend/src/components/CytoscapeGraph.tsx | 35 +++++++- frontend/src/components/Sidebar.tsx | 82 +++++++++++++----- .../space/fediverse/graph/GraphBuilder.class | Bin 8570 -> 8379 bytes .../space/fediverse/graph/GraphBuilder.java | 25 +++--- netlify.toml | 3 + 8 files changed, 121 insertions(+), 75 deletions(-) diff --git a/backend/lib/backend/api.ex b/backend/lib/backend/api.ex index be436d3..6e5c217 100644 --- a/backend/lib/backend/api.ex +++ b/backend/lib/backend/api.ex @@ -17,51 +17,27 @@ defmodule Backend.Api do @doc """ Returns a list of instances that - * have at least one successful crawl * have a user count (required to give the instance a size on the graph) + * have x and y coordinates """ @spec list_nodes() :: [Instance.t()] def list_nodes() do - crawl_subquery = - Crawl - |> select([c], %{ - instance_domain: c.instance_domain, - crawl_count: count(c.id) - }) - |> where([c], is_nil(c.error)) - |> group_by([c], c.instance_domain) - Instance - |> join(:inner, [i], c in subquery(crawl_subquery), on: i.domain == c.instance_domain) - |> where( - [i, c], - c.crawl_count > 0 and not is_nil(i.user_count) and not is_nil(i.x) and not is_nil(i.y) - ) + |> where([i], not is_nil(i.x) and not is_nil(i.y) and not is_nil(i.user_count)) |> select([c], [:domain, :user_count, :x, :y]) |> Repo.all() end @spec list_edges() :: [Edge.t()] def list_edges() do - crawl_subquery = - Crawl - |> select([c], %{ - instance_domain: c.instance_domain, - crawl_count: count(c.id) - }) - |> where([c], is_nil(c.error)) - |> group_by([c], c.instance_domain) - Edge - |> join(:inner, [e], c1 in subquery(crawl_subquery), on: e.source_domain == c1.instance_domain) - |> join(:inner, [e], c2 in subquery(crawl_subquery), on: e.target_domain == c2.instance_domain) |> join(:inner, [e], i1 in Instance, on: e.source_domain == i1.domain) |> join(:inner, [e], i2 in Instance, on: e.target_domain == i2.domain) |> select([e], [:id, :source_domain, :target_domain, :weight]) |> where( - [e, c1, c2, i1, i2], - c1.crawl_count > 0 and c2.crawl_count > 0 and not is_nil(i1.x) and not is_nil(i1.y) and - not is_nil(i2.x) and not is_nil(i2.y) and e.source_domain != e.target_domain + [e, i1, i2], + not is_nil(i1.x) and not is_nil(i1.y) and + not is_nil(i2.x) and not is_nil(i2.y) ) |> Repo.all() end diff --git a/backend/lib/backend/scheduler.ex b/backend/lib/backend/scheduler.ex index ea88070..d19e5f6 100644 --- a/backend/lib/backend/scheduler.ex +++ b/backend/lib/backend/scheduler.ex @@ -60,10 +60,6 @@ defmodule Backend.Scheduler do interactions: min(c.interactions_seen) }) |> Repo.all() - |> (fn o -> - Logger.info(inspect(o)) - o - end).() |> Enum.map(fn %{domain: domain, mentions: mentions, interactions: interactions} -> %{ domain: domain, @@ -82,7 +78,8 @@ defmodule Backend.Scheduler do @doc """ This function aggregates statistics from the interactions in the database. - It calculates the strength of edges between nodes. + It calculates the strength of edges between nodes. Self-edges are not generated. + Edges are only generated if both instances have been succesfully crawled. """ def generate_edges() do now = get_now() @@ -98,12 +95,13 @@ defmodule Backend.Scheduler do interactions = CrawlInteraction - |> join(:left, [ci], c_source in subquery(crawls_subquery), + |> join(:inner, [ci], c_source in subquery(crawls_subquery), on: ci.source_domain == c_source.instance_domain ) - |> join(:left, [ci], c_target in subquery(crawls_subquery), + |> join(:inner, [ci], c_target in subquery(crawls_subquery), on: ci.target_domain == c_target.instance_domain ) + |> where([ci], ci.source_domain != ci.target_domain) |> group_by([ci], [ci.source_domain, ci.target_domain]) |> select([ci, c_source, c_target], %{ source_domain: ci.source_domain, @@ -130,9 +128,8 @@ defmodule Backend.Scheduler do mentions: mentions, source_statuses_seen: source_statuses_seen, target_statuses_seen: target_statuses_seen - } = x, + }, acc -> - Logger.info(inspect(x)) key = get_interaction_key(source_domain, target_domain) # target_statuses_seen might be nil if that instance was never crawled. default to 0. diff --git a/backend/lib/backend_web/views/instance_view.ex b/backend/lib/backend_web/views/instance_view.ex index 108ca69..dd808e5 100644 --- a/backend/lib/backend_web/views/instance_view.ex +++ b/backend/lib/backend_web/views/instance_view.ex @@ -16,8 +16,6 @@ defmodule BackendWeb.InstanceView do end def render("instance_detail.json", %{instance: instance, crawl: crawl}) do - Logger.info("keys: #{inspect(instance)}") - [status, last_updated] = case crawl do nil -> diff --git a/frontend/src/components/CytoscapeGraph.tsx b/frontend/src/components/CytoscapeGraph.tsx index 06a225c..0be272c 100644 --- a/frontend/src/components/CytoscapeGraph.tsx +++ b/frontend/src/components/CytoscapeGraph.tsx @@ -128,7 +128,23 @@ class GraphImpl extends React.Component { this.cy = cytoscape({ autoungrabify: false, container: this.cytoscapeDiv.current, - elements: graph, + elements: { + edges: graph.edges.map(e => ({ + ...e, + data: { + ...e.data, + weight: Math.min(Math.max(e.data.weight * 100, 2), 10) + }, + selectable: false + })), + nodes: graph.nodes.map(n => ({ + ...n, + data: { + ...n.data, + size: Math.min(Math.max(n.data.size * 10, 10), 80) + } + })) + }, layout: { name: "preset" }, @@ -144,7 +160,22 @@ class GraphImpl extends React.Component { { selector: "node", style: { - "background-color": DEFAULT_NODE_COLOR + "background-color": DEFAULT_NODE_COLOR, + height: "data(size)", + label: "data(id)", + width: "data(size)" + } + }, + { + selector: "edge", + style: { + width: "data(weight)" + } + }, + { + selector: "label", + style: { + color: DEFAULT_NODE_COLOR } } ] diff --git a/frontend/src/components/Sidebar.tsx b/frontend/src/components/Sidebar.tsx index 0b52abe..61af731 100644 --- a/frontend/src/components/Sidebar.tsx +++ b/frontend/src/components/Sidebar.tsx @@ -5,10 +5,12 @@ import * as React from "react"; import { connect } from "react-redux"; import { Dispatch } from "redux"; import sanitize from "sanitize-html"; +import styled from "styled-components"; import { AnchorButton, Button, + Callout, Card, Classes, Code, @@ -40,12 +42,24 @@ interface ISidebarProps { } interface ISidebarState { isOpen: boolean; + neighbors?: string[]; + isProcessingNeighbors: boolean; } class SidebarImpl extends React.Component { constructor(props: ISidebarProps) { super(props); const isOpen = window.innerWidth >= 900 ? true : false; - this.state = { isOpen }; + this.state = { isOpen, isProcessingNeighbors: false }; + } + + public componentDidMount() { + this.processEdgesToFindNeighbors(); + } + + public componentDidUpdate(prevProps: ISidebarProps, prevState: ISidebarState) { + if (prevProps.instanceName !== this.props.instanceName) { + this.processEdgesToFindNeighbors(); + } } public render() { @@ -71,8 +85,26 @@ class SidebarImpl extends React.Component { this.setState({ isOpen: !this.state.isOpen }); }; + private processEdgesToFindNeighbors = () => { + const { graph, instanceName } = this.props; + if (!graph || !instanceName) { + return; + } + this.setState({ isProcessingNeighbors: true }); + const edges = graph.edges.filter(e => [e.data.source, e.data.target].indexOf(instanceName!) > -1); + const neighbors: any[] = []; + edges.forEach(e => { + if (e.data.source === instanceName) { + neighbors.push({ neighbor: e.data.target, weight: e.data.weight }); + } else { + neighbors.push({ neighbor: e.data.source, weight: e.data.weight }); + } + }); + this.setState({ neighbors, isProcessingNeighbors: false }); + }; + private renderSidebarContents = () => { - if (this.props.isLoadingInstanceDetails) { + if (this.props.isLoadingInstanceDetails || this.state.isProcessingNeighbors) { return this.renderLoadingState(); } else if (!this.props.instanceDetails) { return this.renderEmptyState(); @@ -82,12 +114,6 @@ class SidebarImpl extends React.Component { return this.renderMissingDataState(); } else if (this.props.instanceLoadError) { return ; - } else if ( - this.props.graph && - this.props.instanceName && - this.props.graph.nodes.map(n => n.data.id).indexOf(this.props.instanceName) < 0 - ) { - return this.renderQuietInstanceState(); } return (
@@ -123,9 +149,20 @@ class SidebarImpl extends React.Component { ); } + + const hasNeighbors = this.state.neighbors && this.state.neighbors.length > 0; + + const insularCallout = hasNeighbors ? ( + undefined + ) : ( + +

This instance doesn't have any neighbors that we know of, so it's hidden from the graph.

+
+ ); return (

{content}

+ {insularCallout}
); @@ -318,22 +355,21 @@ class SidebarImpl extends React.Component { }; private renderMissingDataState = () => { + const FillDiv = styled.div` + width: 100%; + height: 100%; + `; return ( - - ); - }; - - private renderQuietInstanceState = () => { - return ( - + + + + {this.props.instanceDetails && this.props.instanceDetails.status} + + ); }; diff --git a/gephi/bin/main/space/fediverse/graph/GraphBuilder.class b/gephi/bin/main/space/fediverse/graph/GraphBuilder.class index b5339a6988d4c084c52144c67f9be03206e40fd1..94f50194975ade07acd6c0e1b7e98678231b7162 100644 GIT binary patch literal 8379 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 Umle816q|zqh&;tpq{-9&2gEKJOaK4? literal 8570 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 0 AND i.user_count IS NOT NULL"); - - private static final String edgeQuery = String.join("", "SELECT", " e.source_domain AS source,", - " e.target_domain AS target,", " e.weight AS weight", " FROM edges e"); + private static final String edgeQuery = new StringBuilder().append("SELECT e.source_domain AS source,") + .append(" e.target_domain AS target, e.weight AS weight FROM edges e").toString(); public static void main(String[] args) { + // System.out.println("Node query: " + nodeQuery); + // System.out.println("Edge query: " + edgeQuery); // Init project & workspace; required to do things w/ gephi ProjectController pc = Lookup.getDefault().lookup(ProjectController.class); @@ -114,7 +112,14 @@ public class GraphBuilder { } throw new RuntimeException(e); } - // Update + // Remove all x and y + try { + PreparedStatement delStatement = conn.prepareStatement("UPDATE instances SET x=NULL, y=NULL"); + delStatement.executeUpdate(); + } catch (SQLException e) { + throw new RuntimeException(e); + } + // Update to new x's and y's UndirectedGraph graph = graphModel.getUndirectedGraph(); for (Node node : graph.getNodes()) { String id = node.getId().toString(); diff --git a/netlify.toml b/netlify.toml index 4438afa..635f69d 100644 --- a/netlify.toml +++ b/netlify.toml @@ -7,3 +7,6 @@ [context.branch-deploy.environment] REACT_APP_STAGING = "true" + +[context.deploy-preview.environment] + REACT_APP_STAGING = "true" \ No newline at end of file