Skip to content

Commit

Permalink
Added network page
Browse files Browse the repository at this point in the history
  • Loading branch information
ddxv committed Feb 11, 2024
1 parent 15bc2d7 commit 057de18
Show file tree
Hide file tree
Showing 8 changed files with 197 additions and 0 deletions.
76 changes: 76 additions & 0 deletions backend/api_app/controllers/networks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
"""API endoipoints for app networks.
/networks/ returns list of top networks.
"""

from typing import Self

from litestar import Controller, get
from litestar.exceptions import NotFoundException

from api_app.models import NetworkApps, TopNetworks
from config import get_logger
from dbcon.queries import get_apps_for_network, get_top_networks

logger = get_logger(__name__)


def networks_overview() -> TopNetworks:
"""Process networks and return TopNetworks class."""
df = get_top_networks()
df = df[~df["network_name"].isna()]
df = df.sort_values("app_count", ascending=False)
networks = TopNetworks(networks=df.to_dict(orient="records"))
return networks


class NetworksController(Controller):

"""API EndPoint return for app networks."""

path = "/api/networks/"

@get(path="/", cache=True)
async def top_networks(self: Self) -> TopNetworks:
"""Handle GET request for a list of top networks.
Returns
-------
A dictionary representation of the list of networks
each with an id, name, type and total of apps.
"""
logger.info(f"{self.path} start")
overview = networks_overview()

return overview

@get(path="/{network_name:str}", cache=3600)
async def get_network_apps(self: Self, network_name: str) -> NetworkApps:
"""Handle GET request for a specific network.
Args:
----
network_name (str): The name of the network to retrieve apps for.
Returns:
-------
json
"""
logger.info(f"{self.path} start")
apps_df = get_apps_for_network(network_name)

if apps_df.empty:
msg = f"Network Name not found: {network_name!r}"
raise NotFoundException(
msg,
status_code=404,
)
apps_dict = apps_df.to_dict(orient="records")

apps = NetworkApps(
title=network_name,
apps=apps_dict,
)
return apps
30 changes: 30 additions & 0 deletions backend/api_app/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,15 @@ class TrackerApps:
apps: list[AppDetail]


@dataclass
class NetworkApps:

"""A network's list of apps."""

title: str
apps: list[AppDetail]


@dataclass
class Collection:

Expand Down Expand Up @@ -124,6 +133,19 @@ class TrackerDetail:
count: int


@dataclass
class NetworkDetail:

"""Describes details of a network.
Includes its db identifier, name, and the count of its occurrences.
"""

network: int
network_name: str
count: int


@dataclass
class TopTrackers:

Expand All @@ -132,6 +154,14 @@ class TopTrackers:
trackers: list[TrackerDetail]


@dataclass
class TopNetworks:

"""Contains a list of NetworkDetail objects representing the top networks identified."""

networks: list[NetworkDetail]


@dataclass
class StoreCategoryDetail:

Expand Down
2 changes: 2 additions & 0 deletions backend/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

from api_app.controllers.apps import AppController
from api_app.controllers.categories import CategoryController
from api_app.controllers.networks import NetworksController
from api_app.controllers.rankings import RankingsController
from api_app.controllers.trackers import TrackersController

Expand Down Expand Up @@ -39,6 +40,7 @@ class MyOpenAPIController(OpenAPIController):
CategoryController,
RankingsController,
TrackersController,
NetworksController,
],
cors_config=cors_config,
openapi_config=OpenAPIConfig(
Expand Down
25 changes: 25 additions & 0 deletions backend/dbcon/queries.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ def load_sql_file(file_name: str) -> str:
)
QUERY_TOP_TRACKERS = load_sql_file("query_top_trackers.sql")
QUERY_TRACKER_APPS = load_sql_file("query_tracker_apps.sql")
QUERY_TOP_NETWORKS = load_sql_file("query_top_networks.sql")
QUERY_NETWORK_APPS = load_sql_file("query_network_apps.sql")


def get_recent_apps(collection: str, limit: int = 20) -> pd.DataFrame:
Expand Down Expand Up @@ -275,6 +277,19 @@ def get_apps_for_tracker(tracker_name: str) -> pd.DataFrame:
return df


def get_apps_for_network(network_name: str) -> pd.DataFrame:
"""Get apps for for a network."""
logger.info(f"Tracker: {network_name=}")
df = pd.read_sql(
QUERY_NETWORK_APPS,
con=DBCON.engine,
params={"network_name": network_name, "mylimit": 20},
)
if not df.empty:
df = clean_app_df(df)
return df


def search_apps(search_input: str, limit: int = 100) -> pd.DataFrame:
"""Search apps by term in database."""
logger.info(f"App search: {search_input=}")
Expand Down Expand Up @@ -307,6 +322,16 @@ def get_top_trackers() -> pd.DataFrame:
return df


def get_top_networks() -> pd.DataFrame:
"""Get top networks.
Data is pre-processed by materialized views.
"""
df = pd.read_sql(QUERY_TOP_NETWORKS, DBCON.engine)
return df


logger.info("set db engine")
DBCON = get_db_connection("madrone")
DBCON.set_engine()
17 changes: 17 additions & 0 deletions backend/dbcon/sql/query_network_apps.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
SELECT *
FROM
store_apps
WHERE
id IN
(
SELECT sat.store_app
FROM
store_apps_networks AS sat
LEFT JOIN networks AS t
ON
sat.network = t.id
WHERE
t.name = :network_name
)
ORDER BY installs DESC
LIMIT :mylimit;
31 changes: 31 additions & 0 deletions backend/dbcon/sql/query_top_networks.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
WITH
network_counts AS (
SELECT
network,
count(DISTINCT store_app) AS app_count
FROM
store_apps_networks
GROUP BY
network
),

total_app_count AS (
SELECT count(DISTINCT store_app)
FROM
store_apps_networks
)

SELECT
t.name AS network_name,
tc.app_count,
total_app_count.count AS total_app_count,
(
tc.app_count / total_app_count.count::decimal
) AS percent
FROM
network_counts AS tc
LEFT JOIN networks AS t
ON
tc.network = t.id
INNER JOIN total_app_count ON
TRUE;
3 changes: 3 additions & 0 deletions frontend/src/lib/NavTabs.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@
<TabAnchor href="/trackers" selected={$page.url.pathname === '/trackers'}
><h3 class="h4 md:h3 md:p-2">TRACKERS</h3></TabAnchor
>
<TabAnchor href="/networks" selected={$page.url.pathname === '/networks'}
><h3 class="h4 md:h3 md:p-2">NETWORKS</h3></TabAnchor
>
<TabAnchor href="/about" selected={$page.url.pathname === '/about'}
><h3 class="h4 md:h3 md:p-2">ABOUT</h3></TabAnchor
>
Expand Down
13 changes: 13 additions & 0 deletions frontend/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,19 @@ export interface TopTrackersInfo {
};
}

export interface NetworkDetail {
network_name: string;
app_count: number;
percent: number;
}

export interface TopNetworksInfo {
status?: number;
error?: string;
networks: {
streamed: Promise<{ networks: NetworkDetail[] }>;
};
}
export interface AppHistoryInfo {
crawled_date: string;
review_count: number;
Expand Down

0 comments on commit 057de18

Please sign in to comment.