2020-06-22 11:11:50 +02:00
|
|
|
<script context="module">
|
2020-11-01 05:26:58 +01:00
|
|
|
// import _ from "./graph-helpers.scss";
|
2020-06-22 11:11:50 +02:00
|
|
|
</script>
|
|
|
|
|
|
|
|
<script lang="typescript">
|
2020-11-05 02:01:30 +01:00
|
|
|
import type { I18n } from "anki/i18n";
|
|
|
|
import type pb from "anki/backend_proto";
|
2020-11-01 05:26:58 +01:00
|
|
|
import { getGraphData, RevlogRange } from "./graph-helpers";
|
2020-06-22 11:11:50 +02:00
|
|
|
|
2020-06-27 11:24:49 +02:00
|
|
|
export let i18n: I18n;
|
2020-06-30 08:23:46 +02:00
|
|
|
export let nightMode: boolean;
|
2020-12-22 22:06:12 +01:00
|
|
|
export let graphs: any[];
|
2020-06-27 11:24:49 +02:00
|
|
|
|
2020-12-22 22:25:47 +01:00
|
|
|
export let search: string;
|
|
|
|
export let days: number;
|
|
|
|
|
2020-06-26 02:42:10 +02:00
|
|
|
let sourceData: pb.BackendProto.GraphsOut | null = null;
|
2020-06-22 11:11:50 +02:00
|
|
|
|
2020-06-22 12:28:36 +02:00
|
|
|
enum SearchRange {
|
|
|
|
Deck = 1,
|
|
|
|
Collection = 2,
|
|
|
|
Custom = 3,
|
|
|
|
}
|
|
|
|
|
|
|
|
let searchRange: SearchRange = SearchRange.Deck;
|
2020-07-06 10:29:35 +02:00
|
|
|
let revlogRange: RevlogRange = RevlogRange.Year;
|
2020-06-26 07:34:21 +02:00
|
|
|
let refreshing = false;
|
2020-06-22 11:11:50 +02:00
|
|
|
|
2020-06-22 13:39:16 +02:00
|
|
|
let displayedSearch = search;
|
2020-06-22 12:28:36 +02:00
|
|
|
|
2020-06-22 11:11:50 +02:00
|
|
|
const refresh = async () => {
|
2020-06-26 07:34:21 +02:00
|
|
|
refreshing = true;
|
2020-07-24 01:56:28 +02:00
|
|
|
try {
|
|
|
|
sourceData = await getGraphData(search, days);
|
|
|
|
} catch (e) {
|
|
|
|
sourceData = null;
|
|
|
|
alert(i18n.tr(i18n.TR.STATISTICS_ERROR_FETCHING));
|
|
|
|
}
|
2020-06-26 07:34:21 +02:00
|
|
|
refreshing = false;
|
2020-06-22 11:11:50 +02:00
|
|
|
};
|
|
|
|
|
2020-06-22 13:39:16 +02:00
|
|
|
$: {
|
|
|
|
// refresh if either of these change
|
|
|
|
search;
|
|
|
|
days;
|
|
|
|
refresh();
|
|
|
|
}
|
|
|
|
|
2020-06-22 12:28:36 +02:00
|
|
|
$: {
|
|
|
|
switch (searchRange as SearchRange) {
|
|
|
|
case SearchRange.Deck:
|
2020-06-22 13:39:16 +02:00
|
|
|
search = displayedSearch = "deck:current";
|
2020-06-22 12:28:36 +02:00
|
|
|
break;
|
|
|
|
case SearchRange.Collection:
|
2020-06-22 13:39:16 +02:00
|
|
|
search = displayedSearch = "";
|
2020-06-22 12:28:36 +02:00
|
|
|
break;
|
|
|
|
case SearchRange.Custom:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-22 11:11:50 +02:00
|
|
|
$: {
|
2020-06-27 07:35:34 +02:00
|
|
|
switch (revlogRange as RevlogRange) {
|
|
|
|
case RevlogRange.Year:
|
2020-06-22 11:11:50 +02:00
|
|
|
days = 365;
|
|
|
|
break;
|
2020-06-27 07:35:34 +02:00
|
|
|
case RevlogRange.All:
|
2020-06-22 11:11:50 +02:00
|
|
|
days = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-22 13:39:16 +02:00
|
|
|
const searchKeyUp = (e: KeyboardEvent) => {
|
|
|
|
// fetch data on enter
|
2020-11-01 05:26:58 +01:00
|
|
|
if (e.key == "Enter") {
|
2020-06-29 07:11:46 +02:00
|
|
|
const wasSame = search == displayedSearch;
|
2020-06-22 13:39:16 +02:00
|
|
|
search = displayedSearch;
|
2020-06-29 07:11:46 +02:00
|
|
|
if (wasSame) {
|
|
|
|
// force a refresh (user may have changed current deck, etc)
|
|
|
|
refresh();
|
|
|
|
}
|
2020-06-22 13:39:16 +02:00
|
|
|
}
|
|
|
|
};
|
2020-06-27 14:10:56 +02:00
|
|
|
|
2020-07-06 10:29:35 +02:00
|
|
|
const year = i18n.tr(i18n.TR.STATISTICS_RANGE_1_YEAR_HISTORY);
|
2020-06-28 05:46:17 +02:00
|
|
|
const deck = i18n.tr(i18n.TR.STATISTICS_RANGE_DECK);
|
|
|
|
const collection = i18n.tr(i18n.TR.STATISTICS_RANGE_COLLECTION);
|
|
|
|
const searchLabel = i18n.tr(i18n.TR.STATISTICS_RANGE_SEARCH);
|
2020-07-06 10:29:35 +02:00
|
|
|
const all = i18n.tr(i18n.TR.STATISTICS_RANGE_ALL_HISTORY);
|
2020-06-22 11:11:50 +02:00
|
|
|
</script>
|
|
|
|
|
2020-08-21 07:15:19 +02:00
|
|
|
<style>
|
|
|
|
.no-focus-outline:focus {
|
|
|
|
outline: 0;
|
|
|
|
}
|
|
|
|
</style>
|
|
|
|
|
2020-06-22 11:11:50 +02:00
|
|
|
<div class="range-box">
|
2020-06-26 07:34:21 +02:00
|
|
|
<div class="spin {refreshing ? 'active' : ''}">◐</div>
|
|
|
|
|
|
|
|
<div class="range-box-inner">
|
|
|
|
<label>
|
|
|
|
<input type="radio" bind:group={searchRange} value={SearchRange.Deck} />
|
2020-06-28 05:46:17 +02:00
|
|
|
{deck}
|
2020-06-26 07:34:21 +02:00
|
|
|
</label>
|
|
|
|
<label>
|
|
|
|
<input
|
|
|
|
type="radio"
|
|
|
|
bind:group={searchRange}
|
|
|
|
value={SearchRange.Collection} />
|
2020-06-28 05:46:17 +02:00
|
|
|
{collection}
|
2020-06-26 07:34:21 +02:00
|
|
|
</label>
|
|
|
|
|
2020-06-27 13:45:16 +02:00
|
|
|
<input
|
|
|
|
type="text"
|
|
|
|
bind:value={displayedSearch}
|
|
|
|
on:keyup={searchKeyUp}
|
|
|
|
on:focus={() => {
|
|
|
|
searchRange = SearchRange.Custom;
|
|
|
|
}}
|
2020-06-28 05:46:17 +02:00
|
|
|
placeholder={searchLabel} />
|
2020-06-26 07:34:21 +02:00
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="range-box-inner">
|
|
|
|
<label>
|
2020-06-27 07:35:34 +02:00
|
|
|
<input type="radio" bind:group={revlogRange} value={RevlogRange.Year} />
|
2020-06-27 14:10:56 +02:00
|
|
|
{year}
|
2020-06-26 07:34:21 +02:00
|
|
|
</label>
|
|
|
|
<label>
|
2020-06-27 07:35:34 +02:00
|
|
|
<input type="radio" bind:group={revlogRange} value={RevlogRange.All} />
|
2020-06-28 05:46:17 +02:00
|
|
|
{all}
|
2020-06-26 07:34:21 +02:00
|
|
|
</label>
|
|
|
|
</div>
|
2020-06-22 11:11:50 +02:00
|
|
|
</div>
|
2020-06-26 07:34:21 +02:00
|
|
|
<div class="range-box-pad" />
|
2020-06-22 11:11:50 +02:00
|
|
|
|
2020-08-21 07:15:19 +02:00
|
|
|
<div tabindex="-1" class="no-focus-outline">
|
|
|
|
{#if sourceData}
|
2020-12-22 22:06:12 +01:00
|
|
|
{#each graphs as Graph}
|
|
|
|
<Graph {sourceData} {revlogRange} {i18n} {nightMode} />
|
|
|
|
{/each}
|
2020-08-21 07:15:19 +02:00
|
|
|
{/if}
|
|
|
|
</div>
|