Skip to content

Commit

Permalink
feat: front and back ws analytics query and ui (#234)
Browse files Browse the repository at this point in the history
  • Loading branch information
ramiroaisen authored Dec 24, 2023
2 parents 38f36ba + 2cc5f1d commit a7dd77d
Show file tree
Hide file tree
Showing 25 changed files with 1,676 additions and 69 deletions.
5 changes: 5 additions & 0 deletions defs/api/app-analytics/GET/CountryCodeOrZZ.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { CountryCode } from "../../../CountryCode";
import type { ZZ } from "./ZZ";

export type CountryCodeOrZZ = ZZ | CountryCode;
4 changes: 4 additions & 0 deletions defs/api/app-analytics/GET/Output.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { Analytics } from "../../../app-analytics/Analytics";

export type Output = { analytics: Analytics };
12 changes: 12 additions & 0 deletions defs/api/app-analytics/GET/Query.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { AnalyticsQueryKind } from "../../../app-analytics/AnalyticsQueryKind";
import type { CountryCodeOrZZ } from "./CountryCodeOrZZ";

export type Query = {
kind: AnalyticsQueryKind;
stations: string[] | undefined;
app_kind: string | null;
app_version: string | null;
country_code: CountryCodeOrZZ | null;
min_duration_ms?: number;
};
3 changes: 3 additions & 0 deletions defs/api/app-analytics/GET/ZZ.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.

export type ZZ = "ZZ";
29 changes: 29 additions & 0 deletions defs/app-analytics/Analytics.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { AnalyticsItem } from "./AnalyticsItem";
import type { AnalyticsQueryKind } from "./AnalyticsQueryKind";
import type { AnalyticsStation } from "./AnalyticsStation";
import type { AppKindVersion } from "./AppKindVersion";
import type { CountryCode } from "../CountryCode";
import type { DateTime } from "../DateTime";
import type { YearMonthDay } from "./YearMonthDay";
import type { YearMonthDayHour } from "./YearMonthDayHour";

export type Analytics = {
is_now: boolean;
kind: AnalyticsQueryKind;
stations: Array<AnalyticsStation>;
since: /** time::DateTime */ string;
until: /** time::DateTime */ string;
utc_offset_minutes: number;
sessions: number;
ips: number;
total_duration_ms: number;
max_concurrent_listeners?: number;
max_concurrent_listeners_date?: DateTime;
by_day: Array<AnalyticsItem<YearMonthDay>>;
by_hour: Array<AnalyticsItem<YearMonthDayHour>> | null;
by_country: Array<AnalyticsItem<CountryCode | null>>;
by_station: Array<AnalyticsItem<string>>;
by_app_kind: Array<AnalyticsItem<string | null>>;
by_app_version: Array<AnalyticsItem<AppKindVersion>>;
};
12 changes: 12 additions & 0 deletions defs/app-analytics/AnalyticsItem.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { DateTime } from "../DateTime";

export type AnalyticsItem<K> = {
key: K;
sessions: number;
ips: number;
total_duration_ms: number;
total_transfer_bytes: number;
max_concurrent_listeners?: number;
max_concurrent_listeners_date?: DateTime;
};
10 changes: 10 additions & 0 deletions defs/app-analytics/AnalyticsQueryKind.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.

export type AnalyticsQueryKind = {
now: { offset_date: /** time::DateTime */ string };
} | {
time_range: {
since: /** time::DateTime */ string;
until: /** time::DateTime */ string;
};
};
8 changes: 8 additions & 0 deletions defs/app-analytics/AnalyticsStation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { DateTime } from "../DateTime";

export type AnalyticsStation = {
_id: string;
name: string;
created_at: DateTime;
};
3 changes: 3 additions & 0 deletions defs/app-analytics/AppKindVersion.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.

export type AppKindVersion = { kind: string | null; version: number | null };
3 changes: 3 additions & 0 deletions defs/app-analytics/YearMonthDay.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.

export type YearMonthDay = { year: number; month: number; day: number };
8 changes: 8 additions & 0 deletions defs/app-analytics/YearMonthDayHour.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.

export type YearMonthDayHour = {
year: number;
month: number;
day: number;
hour: number;
};
25 changes: 19 additions & 6 deletions front/admin/src/routes/(online)/(app)/analytics/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,34 +1,43 @@
<script lang="ts">
export let data: import("./$types").PageData;
let type: "stream" | "app" = "stream";
let country_code: CountryCode | null | undefined = undefined;
let os: string | null | undefined = undefined;
let browser: string | null | undefined = undefined;
let domain: string | null | undefined = undefined;
let kind: QueryKind = "last-30d";
let selected_stations: StationItem[] | "all" = "all";
let loading: boolean = false;
let analytics_data: import("$server/defs/analytics/Analytics").Analytics | null = null;
let app_kind: string | null | undefined = undefined;
let app_version: number | null | undefined = undefined;
let analytics_data: Data | null = null;
type Snapshot = {
type: "stream" | "app",
kind: QueryKind,
country_code: CountryCode | null | undefined,
os: string | null | undefined,
browser: string | null | undefined,
domain: string | null | undefined,
kind: QueryKind,
app_kind: string | null | undefined,
app_version: number | null | undefined,
selected_stations: StationItem[] | "all",
analytics_data: import("$server/defs/analytics/Analytics").Analytics | null,
analytics_data: Data | null,
};
export const snapshot = {
capture: (): Snapshot => {
return {
type,
analytics_data,
country_code,
os,
browser,
kind,
domain,
app_kind,
app_version,
selected_stations
}
},
Expand All @@ -41,6 +50,8 @@
country_code,
os,
domain,
app_kind,
app_version,
selected_stations,
} = snapshot);
}
Expand All @@ -53,6 +64,8 @@
import { locale, lang } from "$lib/locale";
import type { CountryCode } from "$server/defs/CountryCode";
import type { QueryKind, StationItem } from "$share/analytics/AnalyticsFilters.svelte";
import type { Data } from "$share/analytics/AnalyticsData.svelte";
import { ripple } from "$share/ripple";
</script>

<svelte:head>
Expand All @@ -61,9 +74,7 @@

<Page>
<PageTop>
<svelte:fragment slot="title">
Analytics
</svelte:fragment>
<svelte:fragment slot="title">Analytics</svelte:fragment>
</PageTop>

<Analytics
Expand All @@ -76,6 +87,8 @@
bind:os
bind:browser
bind:domain
bind:app_kind
bind:app_version
lang={$lang}
locale={$locale.analytics}
stats_map_locale={$locale.stats_map}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,41 +2,52 @@
export let data: import("./$types").PageData;
import Page from "$lib/components/Page.svelte";
import Analytics from "$share/analytics/Analytics.svelte";
import AnalyticsTypeSelector from "$share/analytics/AnalyticsTypeSelector.svelte";
import { locale, lang } from "$lib/locale";
import type { CountryCode } from "$server/defs/CountryCode";
import type { QueryKind, StationItem } from "$share/analytics/AnalyticsFilters.svelte";
import type { Data } from "$share/analytics/AnalyticsData.svelte";
$: account_stations = data.stations.items.filter(item => item.account_id === data.account._id);
let type: "stream" | "app" = "stream";
let country_code: CountryCode | null | undefined = undefined;
let os: string | null | undefined = undefined;
let browser: string | null | undefined = undefined;
let domain: string | null | undefined = undefined;
let kind: QueryKind = "last-30d";
let selected_stations: StationItem[] | "all" = "all";
let loading: boolean = false;
let analytics_data: import("$server/defs/analytics/Analytics").Analytics | null = null;
let app_kind: string | null | undefined = undefined;
let app_version: number | null | undefined = undefined;
let analytics_data: Data | null = null;
type Snapshot = {
type: "stream" | "app",
kind: QueryKind,
country_code: CountryCode | null | undefined,
os: string | null | undefined,
browser: string | null | undefined,
domain: string | null | undefined,
kind: QueryKind,
app_kind: string | null | undefined,
app_version: number | null | undefined,
selected_stations: StationItem[] | "all",
analytics_data: import("$server/defs/analytics/Analytics").Analytics | null,
analytics_data: Data | null,
};
export const snapshot = {
capture: (): Snapshot => {
return {
type,
analytics_data,
country_code,
os,
browser,
kind,
domain,
app_kind,
app_version,
selected_stations
}
},
Expand All @@ -49,6 +60,8 @@
country_code,
os,
domain,
app_kind,
app_version,
selected_stations,
} = snapshot);
}
Expand All @@ -60,10 +73,13 @@
</svelte:head>

<Page>
<h1>{$locale.pages["account/analytics"].title}</h1>
<h1>
{$locale.pages["account/analytics"].title}
</h1>

<Analytics
stations={account_stations}
bind:type
bind:data={analytics_data}
bind:loading
bind:selected_stations
Expand All @@ -72,9 +88,11 @@
bind:os
bind:browser
bind:domain
bind:app_kind
bind:app_version
lang={$lang}
locale={$locale.analytics}
stats_map_locale={$locale.stats_map}
country_names={$locale.countries}
/>
/>
</Page>
4 changes: 4 additions & 0 deletions front/server/src/api/shared-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,10 @@ export const shared_api = ({
return await client.analytics.get(ip(req), ua(req), get_token(req), req.query as any);
}))

api.route("/app-analytics").get(json(async req => {
return await client.app_analytics.get(ip(req), ua(req), get_token(req), req.query as any);
}))

api.route("/invitations")
.get(json(async req => {
return await client.invitations.list(ip(req), ua(req), get_token(req), req.query as any)
Expand Down
14 changes: 14 additions & 0 deletions front/server/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export class Client {
accounts: Accounts;
stations: Stations;
analytics: Analytics;
app_analytics: AppAnalytics;
invitations: AccountInvitations;
payment_methods: PaymentMethods;
stream_connections: StreamConnections;
Expand All @@ -48,6 +49,7 @@ export class Client {
this.accounts = new Accounts(this);
this.stations = new Stations(this);
this.analytics = new Analytics(this);
this.app_analytics = new AppAnalytics(this);
this.invitations = new AccountInvitations(this);
this.payment_methods = new PaymentMethods(this);
this.stream_connections = new StreamConnections(this);
Expand Down Expand Up @@ -635,6 +637,18 @@ export class Analytics {
}
}

export class AppAnalytics {
client: Client;
constructor(client: Client) {
this.client = client;
}

async get(ip: string | null, ua: string | null, token: string, query: import("$api/app-analytics/GET/Query").Query): Promise<import("$api/app-analytics/GET/Output").Output> {
const url = `/app-analytics${qss(query)}`;
return await this.client.get(ip, ua, token, url);
}
}

export class PaymentMethods {
client: Client;
constructor(client: Client) {
Expand Down
Loading

0 comments on commit a7dd77d

Please sign in to comment.