mirror of
https://github.com/ankitects/anki.git
synced 2025-09-18 22:12:21 -04:00
Make CardStats a separate component
This commit is contained in:
parent
1d63253b4f
commit
4b5ea6c110
2 changed files with 116 additions and 102 deletions
|
@ -3,108 +3,16 @@ Copyright: Ankitects Pty Ltd and contributors
|
||||||
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import * as tr2 from "../lib/ftl";
|
import type { Stats } from "../lib/proto";
|
||||||
import { Stats, unwrapOptionalNumber } from "../lib/proto";
|
import CardStats from "./CardStats.svelte";
|
||||||
import { Timestamp, timeSpan, DAY } from "../lib/time";
|
|
||||||
import Revlog from "./Revlog.svelte";
|
import Revlog from "./Revlog.svelte";
|
||||||
|
|
||||||
export let stats: Stats.CardStatsResponse;
|
export let stats: Stats.CardStatsResponse;
|
||||||
|
|
||||||
function dateString(timestamp: number): string {
|
|
||||||
return new Timestamp(timestamp).dateString();
|
|
||||||
}
|
|
||||||
|
|
||||||
interface StatsRow {
|
|
||||||
label: string;
|
|
||||||
value: string | number;
|
|
||||||
}
|
|
||||||
|
|
||||||
function rowsFromStats(stats: Stats.CardStatsResponse): StatsRow[] {
|
|
||||||
const statsRows: StatsRow[] = [];
|
|
||||||
|
|
||||||
statsRows.push({ label: tr2.cardStatsAdded(), value: dateString(stats.added) });
|
|
||||||
|
|
||||||
const firstReview = unwrapOptionalNumber(stats.firstReview);
|
|
||||||
if (firstReview !== undefined) {
|
|
||||||
statsRows.push({
|
|
||||||
label: tr2.cardStatsFirstReview(),
|
|
||||||
value: dateString(firstReview),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
const latestReview = unwrapOptionalNumber(stats.latestReview);
|
|
||||||
if (latestReview !== undefined) {
|
|
||||||
statsRows.push({
|
|
||||||
label: tr2.cardStatsLatestReview(),
|
|
||||||
value: dateString(latestReview),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const dueDate = unwrapOptionalNumber(stats.dueDate);
|
|
||||||
if (dueDate !== undefined) {
|
|
||||||
statsRows.push({
|
|
||||||
label: tr2.statisticsDueDate(),
|
|
||||||
value: dateString(dueDate),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
const duePosition = unwrapOptionalNumber(stats.duePosition);
|
|
||||||
if (duePosition !== undefined) {
|
|
||||||
statsRows.push({
|
|
||||||
label: tr2.cardStatsNewCardPosition(),
|
|
||||||
value: dateString(duePosition),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stats.interval) {
|
|
||||||
statsRows.push({
|
|
||||||
label: tr2.cardStatsInterval(),
|
|
||||||
value: timeSpan(stats.interval * DAY),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (stats.ease) {
|
|
||||||
statsRows.push({
|
|
||||||
label: tr2.cardStatsEase(),
|
|
||||||
value: `${stats.ease / 10}%`,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
statsRows.push({ label: tr2.cardStatsReviewCount(), value: stats.reviews });
|
|
||||||
statsRows.push({ label: tr2.cardStatsLapseCount(), value: stats.lapses });
|
|
||||||
|
|
||||||
if (stats.totalSecs) {
|
|
||||||
statsRows.push({
|
|
||||||
label: tr2.cardStatsAverageTime(),
|
|
||||||
value: timeSpan(stats.averageSecs),
|
|
||||||
});
|
|
||||||
statsRows.push({
|
|
||||||
label: tr2.cardStatsTotalTime(),
|
|
||||||
value: timeSpan(stats.totalSecs),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
statsRows.push({ label: tr2.cardStatsCardTemplate(), value: stats.cardType });
|
|
||||||
statsRows.push({ label: tr2.cardStatsNoteType(), value: stats.notetype });
|
|
||||||
statsRows.push({ label: tr2.cardStatsDeckName(), value: stats.deck });
|
|
||||||
|
|
||||||
statsRows.push({ label: tr2.cardStatsCardId(), value: stats.cardId });
|
|
||||||
statsRows.push({ label: tr2.cardStatsNoteId(), value: stats.noteId });
|
|
||||||
|
|
||||||
return statsRows;
|
|
||||||
}
|
|
||||||
|
|
||||||
let statsRows: StatsRow[];
|
|
||||||
$: statsRows = rowsFromStats(stats);
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div>
|
<div>
|
||||||
<table class="stats-table">
|
<CardStats {stats} />
|
||||||
{#each statsRows as row, _index}
|
|
||||||
<tr>
|
|
||||||
<th style="text-align:start">{row.label}</th>
|
|
||||||
<td>{row.value}</td>
|
|
||||||
</tr>
|
|
||||||
{/each}
|
|
||||||
</table>
|
|
||||||
<Revlog {stats} />
|
<Revlog {stats} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -113,11 +21,4 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
.container {
|
.container {
|
||||||
max-width: 40em;
|
max-width: 40em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.stats-table {
|
|
||||||
width: 100%;
|
|
||||||
border-spacing: 1em 0;
|
|
||||||
border-collapse: collapse;
|
|
||||||
text-align: start;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
113
ts/card-info/CardStats.svelte
Normal file
113
ts/card-info/CardStats.svelte
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
<!--
|
||||||
|
Copyright: Ankitects Pty Ltd and contributors
|
||||||
|
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
|
-->
|
||||||
|
<script lang="ts">
|
||||||
|
import * as tr2 from "../lib/ftl";
|
||||||
|
import { Stats, unwrapOptionalNumber } from "../lib/proto";
|
||||||
|
import { Timestamp, timeSpan, DAY } from "../lib/time";
|
||||||
|
|
||||||
|
export let stats: Stats.CardStatsResponse;
|
||||||
|
|
||||||
|
function dateString(timestamp: number): string {
|
||||||
|
return new Timestamp(timestamp).dateString();
|
||||||
|
}
|
||||||
|
|
||||||
|
interface StatsRow {
|
||||||
|
label: string;
|
||||||
|
value: string | number;
|
||||||
|
}
|
||||||
|
|
||||||
|
function rowsFromStats(stats: Stats.CardStatsResponse): StatsRow[] {
|
||||||
|
const statsRows: StatsRow[] = [];
|
||||||
|
|
||||||
|
statsRows.push({ label: tr2.cardStatsAdded(), value: dateString(stats.added) });
|
||||||
|
|
||||||
|
const firstReview = unwrapOptionalNumber(stats.firstReview);
|
||||||
|
if (firstReview !== undefined) {
|
||||||
|
statsRows.push({
|
||||||
|
label: tr2.cardStatsFirstReview(),
|
||||||
|
value: dateString(firstReview),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const latestReview = unwrapOptionalNumber(stats.latestReview);
|
||||||
|
if (latestReview !== undefined) {
|
||||||
|
statsRows.push({
|
||||||
|
label: tr2.cardStatsLatestReview(),
|
||||||
|
value: dateString(latestReview),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const dueDate = unwrapOptionalNumber(stats.dueDate);
|
||||||
|
if (dueDate !== undefined) {
|
||||||
|
statsRows.push({
|
||||||
|
label: tr2.statisticsDueDate(),
|
||||||
|
value: dateString(dueDate),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const duePosition = unwrapOptionalNumber(stats.duePosition);
|
||||||
|
if (duePosition !== undefined) {
|
||||||
|
statsRows.push({
|
||||||
|
label: tr2.cardStatsNewCardPosition(),
|
||||||
|
value: dateString(duePosition),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stats.interval) {
|
||||||
|
statsRows.push({
|
||||||
|
label: tr2.cardStatsInterval(),
|
||||||
|
value: timeSpan(stats.interval * DAY),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (stats.ease) {
|
||||||
|
statsRows.push({
|
||||||
|
label: tr2.cardStatsEase(),
|
||||||
|
value: `${stats.ease / 10}%`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
statsRows.push({ label: tr2.cardStatsReviewCount(), value: stats.reviews });
|
||||||
|
statsRows.push({ label: tr2.cardStatsLapseCount(), value: stats.lapses });
|
||||||
|
|
||||||
|
if (stats.totalSecs) {
|
||||||
|
statsRows.push({
|
||||||
|
label: tr2.cardStatsAverageTime(),
|
||||||
|
value: timeSpan(stats.averageSecs),
|
||||||
|
});
|
||||||
|
statsRows.push({
|
||||||
|
label: tr2.cardStatsTotalTime(),
|
||||||
|
value: timeSpan(stats.totalSecs),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
statsRows.push({ label: tr2.cardStatsCardTemplate(), value: stats.cardType });
|
||||||
|
statsRows.push({ label: tr2.cardStatsNoteType(), value: stats.notetype });
|
||||||
|
statsRows.push({ label: tr2.cardStatsDeckName(), value: stats.deck });
|
||||||
|
|
||||||
|
statsRows.push({ label: tr2.cardStatsCardId(), value: stats.cardId });
|
||||||
|
statsRows.push({ label: tr2.cardStatsNoteId(), value: stats.noteId });
|
||||||
|
|
||||||
|
return statsRows;
|
||||||
|
}
|
||||||
|
|
||||||
|
let statsRows: StatsRow[];
|
||||||
|
$: statsRows = rowsFromStats(stats);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<table class="stats-table">
|
||||||
|
{#each statsRows as row, _index}
|
||||||
|
<tr>
|
||||||
|
<th style="text-align:start">{row.label}</th>
|
||||||
|
<td>{row.value}</td>
|
||||||
|
</tr>
|
||||||
|
{/each}
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.stats-table {
|
||||||
|
width: 100%;
|
||||||
|
border-spacing: 1em 0;
|
||||||
|
border-collapse: collapse;
|
||||||
|
text-align: start;
|
||||||
|
}
|
||||||
|
</style>
|
Loading…
Reference in a new issue