Skip to content

Commit

Permalink
feat: front add admin stats map station selector, minor improvements …
Browse files Browse the repository at this point in the history
…to studio dashboard page (#101)
  • Loading branch information
ramiroaisen authored Jul 3, 2023
2 parents d1bf6a8 + 6bb8f81 commit b418a45
Show file tree
Hide file tree
Showing 7 changed files with 286 additions and 404 deletions.
24 changes: 15 additions & 9 deletions front/admin/src/routes/(online)/(app)/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import Page from "$lib/components/Page.svelte";
import { locale } from "$lib/locale";
import Icon from "$share/Icon.svelte";
import StationSelector from "$share/Map/StationSelector.svelte";
import StatsMap from "$share/Map/StatsMap.svelte";
import { ripple } from "$share/ripple";
import { mdiAccountMultipleOutline, mdiAccountOutline, mdiCurrencyUsd, mdiPoll, mdiRadioTower, mdiShieldAccountOutline } from "@mdi/js";
Expand All @@ -15,14 +16,14 @@
let map_view: "now" | "last_24h" | "last_7d" | "last_30d" = "now";
export const snapshot = {
capture: () => {
return { map_view }
},
restore: (ctx: { map_view: typeof map_view }) => {
map_view = ctx.map_view;
}
let map_selector_data: import("$share/Map/StationSelector.svelte").Data = {
all_kind: "all",
kind: "all",
record_id: "",
station: null,
stations: data.stations.items,
stats: data.stats,
storage_public_url: data.config.storage_public_url,
}
</script>

Expand Down Expand Up @@ -173,8 +174,13 @@
</div>

<div class="map">

<div class="selector">
<StationSelector bind:data={map_selector_data} />
</div>

<StatsMap
bind:data={data.stats}
bind:data={map_selector_data.stats}
country_names={$locale.countries}
kind="all"
record_id=""
Expand Down
222 changes: 28 additions & 194 deletions front/admin/src/routes/(online)/(app)/accounts/[account]/stats.svelte
Original file line number Diff line number Diff line change
@@ -1,70 +1,26 @@
<script lang="ts">
export let data: import("./$types").PageData;
import StatsMap from "$share/Map/StatsMap.svelte";
import type { Stats } from "$share/Map/StatsMap.svelte";
import { click_out } from "$share/actions";
import { _get, _patch, action } from "$share/net.client";
import { ripple } from "$share/ripple";
import { _get, _patch } from "$share/net.client";
let selector_state: { kind: "account" | "station", record_id: string, data: Stats, station: typeof data.stations.items[number] | null } = {
kind: "account",
record_id: data.account._id,
data: data.stats,
station: null,
};
import type { View } from "$share/Map/StatsMap.svelte";
import { locale } from "$lib/locale";
import { logical_fly } from "$share/transition";
let view: View = "now";
let _token = 0;
const select = action(async (station: typeof data.stations.items[number] | null) => {
selector_open = false;
if(station?._id === selector_state.station?._id) return;
const token = ++_token;
if(station) {
const { stats }: import("$api/stations/[station]/stream-stats/GET/Output").Output =
await _get(`/api/stations/${station._id}/stream-stats`);
if(token === _token) {
selector_state = {
kind: "station",
record_id: station._id,
data: stats,
station,
}
}
} else {
const { stats }: import("$api/accounts/[account]/stream-stats/GET/Output").Output =
await _get(`/api/accounts/${data.account._id}/stream-stats`);
if(token === _token) {
selector_state = {
kind: "account",
record_id: data.account._id,
data: stats,
station: null,
}
}
}
})
let selector_open = false;
const close_selector = () => {
selector_open = false
}
import type { Data } from "$share/Map/StationSelector.svelte";
import StationSelector from "$share/Map/StationSelector.svelte";
const toggle_selector = () => {
selector_open = !selector_open
}
const selector_menu_click_out = () => {
setTimeout(close_selector, 2);
let selection_data: Data = {
all_kind: "account",
account_id: data.account._id,
station: null,
kind: "account",
record_id: data.account._id,
stations: data.stations.items,
stats: data.stats,
storage_public_url: data.config.storage_public_url,
}
const units = [ "B", "KB", "MB", "GB", "TB" ];
let view: View = "now";
</script>

<style>
Expand All @@ -73,143 +29,21 @@
border-radius: 0.5rem;
box-shadow: 0 20px 25px -5px rgba(0,0,0,.1),0 10px 10px -5px rgba(0,0,0,.04);
}
.stats-selector-out {
padding: 0.5rem;
margin-bottom: -1rem;
}
.stats-selector {
position: relative;
display: flex;
flex-direction: column;
align-items: flex-start;
}
.stats-selector-btn, .stats-selector-item {
display: flex;
flex-direction: row;
align-items: center;
padding: 0 1rem;
height: 3rem;
border-radius: 0.25rem;
transition: background-color 200ms ease;
}
.stats-selector-btn:hover, .stats-selector-btn.open, .stats-selector-item:hover {
background: rgba(0,0,0,0.025);
}
.stats-selector-btn-text {
margin-inline-end: 0.35rem;
}
.stats-selector-btn-chevron {
display: flex;
align-items: center;
justify-content: center;
}
.stats-selector-item.current {
background: rgba(var(--blue-rgb), 0.1);
}
.stats-selector-menu {
min-width: min(80vw, 20rem);
}
.stats-selector-btn-icon, .stats-selector-icon {
width: 1.75rem;
height: 1.75rem;
border-radius: 0.25rem;
background-position: center;
background-size: contain;
background-repeat: no-repeat;
flex: none;
margin-inline-start: -0.5rem;
margin-inline-end: 0.75rem;
}
.stats-selector-anchor {
position: absolute;
inset-block-end: 0;
inset-inline-start: 0;
width: 0;
height: 0;
z-index: 1;
}
.stats-selector-menu {
display: flex;
flex-direction: column;
box-shadow: 0 5px 25px 0 rgb(0 0 0 / 10%);
background: #fff;
padding: 0.5rem;
border-radius: 0.5rem;
}
.stats-selector-item {
display: flex;
flex-direction: row;
align-items: center;
}
</style>

<div class="stats">
<div class="stats-selector-out">
<div class="stats-selector">
<button class="stats-selector-btn ripple-container" class:open={selector_open} use:ripple aria-label={"Select one station or all"} on:click={toggle_selector}>
{#if selector_state.station != null}
<div
class="stats-selector-btn-icon"
style:background-image="url({data.config.storage_public_url}/station-pictures/webp/64/{selector_state.station.picture_id}.webp)"
/>
{/if}
<span class="stats-selector-btn-text">
{#if selector_state.station}
{selector_state.station.name}
{:else}
All stations
{/if}
</span>
<span class="stats-selector-btn-chevron">
<!-- <Icon d={mdiPlay} /> -->
</span>
</button>
<div class="stats-selector-anchor">
{#if selector_open}
<div
class="stats-selector-menu"
use:click_out={selector_menu_click_out}
transition:logical_fly|local={{ duration: 125, y: -10 }}
>
<button class="stats-selector-item" class:current={selector_state.station == null} on:click={() => select(null)}>
<div class="stats-selector-name">
All stations
</div>
</button>
{#each data.account_stations as station (station._id)}
<button class="stats-selector-item" class:current={selector_state.station?._id === station._id} on:click={() => select(station)}>
<div class="stats-selector-icon" style:background-image="url({data.config.storage_public_url}/station-pictures/webp/64/{station.picture_id}.webp)" />
<div class="stats-selector-name">
{station.name}
</div>
</button>
{/each}
</div>
{/if}
</div>
</div>
</div>

<StatsMap
bind:view
kind={selector_state.kind}
record_id={selector_state.record_id}
locale={$locale.stats_map}
country_names={$locale.countries}
bind:data={selector_state.data}
/>
<div class="stats">

<div class="selector">
<StationSelector bind:data={selection_data} />
</div>

<StatsMap
bind:view
kind={selection_data.kind}
record_id={selection_data.record_id}
locale={$locale.stats_map}
country_names={$locale.countries}
bind:data={selection_data.stats}
/>
</div>

Loading

0 comments on commit b418a45

Please sign in to comment.