Redesign deck options screen, swap tooltips for help modals (#2139)
* Redesign deck config, swap tooltips for help modals, link to manual * Replace canvas-inset with canvas-code for custom scheduling * Make section header link to manual too * Include elevation Sass library * Remove two unused exports * Fix tabbed spinboxes * Update ftl/core/deck-config.ftl * Update ftl/core/deck-config.ftl * Fix format * Make border-radius and box-shadow more subtle * Fix margin for vertical aspect ratio * Make direct hover on info badge apply effect instantly * Add redirect line to manual underneath chapter
This commit is contained in:
parent
2971eb9660
commit
264561cd0d
@ -101,9 +101,13 @@ deck-config-bury-title = Burying
|
||||
deck-config-bury-new-siblings = Bury new siblings
|
||||
deck-config-bury-review-siblings = Bury review siblings
|
||||
deck-config-bury-interday-learning-siblings = Bury interday learning siblings
|
||||
deck-config-bury-tooltip =
|
||||
Whether other cards of the same note (eg reverse cards, adjacent
|
||||
cloze deletions) will be delayed until the next day.
|
||||
deck-config-bury-new-tooltip =
|
||||
Whether other `new` cards of the same note (eg reverse cards, adjacent cloze deletions)
|
||||
will be delayed until the next day.
|
||||
deck-config-bury-review-tooltip = Whether other `review` cards of the same note will be delayed until the next day.
|
||||
deck-config-bury-interday-learning-tooltip =
|
||||
Whether other `learning` cards of the same note with intervals > 1 day
|
||||
will be delayed until the next day.
|
||||
|
||||
## Ordering section
|
||||
|
||||
@ -202,6 +206,9 @@ deck-config-show-answer-timer-tooltip =
|
||||
|
||||
deck-config-audio-title = Audio
|
||||
deck-config-disable-autoplay = Don't play audio automatically
|
||||
deck-config-disable-autoplay-tooltip =
|
||||
When enabled, Anki will not play audio automatically.
|
||||
It can be played manually by clicking/tapping on an audio icon, or by using the replay audio action.
|
||||
deck-config-skip-question-when-replaying = Skip question when replaying answer
|
||||
deck-config-always-include-question-audio-tooltip =
|
||||
Whether the question audio should be included when the Replay action is
|
||||
|
26
ftl/core/help.ftl
Normal file
26
ftl/core/help.ftl
Normal file
@ -0,0 +1,26 @@
|
||||
### Text shown in Help pages
|
||||
|
||||
|
||||
## Basic terminology
|
||||
|
||||
help-chapter = chapter
|
||||
|
||||
## Header
|
||||
|
||||
# Tooltip for links to the manual
|
||||
help-open-manual-chapter = Open chapter { $name } in Anki manual
|
||||
# Displayed underneath chapter title
|
||||
help-view-chapter-in-manual = View the { $chapter } on this topic in the official manual.
|
||||
|
||||
## Body
|
||||
|
||||
# Newly introduced settings may not have an explanation yet
|
||||
help-no-explanation =
|
||||
Whoops! There doesn't seem to be an explanation for this setting yet.
|
||||
|
||||
You can help us complete this help page on { $link }.
|
||||
|
||||
## Footer
|
||||
|
||||
# Link to more detailed information in the manual
|
||||
help-for-more-info = For more information, see { $link } in the manual.
|
@ -5,13 +5,16 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
<script lang="ts">
|
||||
import type { Breakpoint } from "./types";
|
||||
|
||||
let className: string = "";
|
||||
export { className as class };
|
||||
|
||||
/* flex-basis: 100% if viewport < breakpoint otherwise
|
||||
* as specified by --cols and --col-size */
|
||||
export let breakpoint: Breakpoint = "xs";
|
||||
</script>
|
||||
|
||||
<div
|
||||
class="col"
|
||||
class="col {className}"
|
||||
class:col-xs={breakpoint === "xs"}
|
||||
class:col-sm={breakpoint === "sm"}
|
||||
class:col-md={breakpoint === "md"}
|
||||
|
@ -3,14 +3,20 @@ Copyright: Ankitects Pty Ltd and contributors
|
||||
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
-->
|
||||
<script lang="ts">
|
||||
import type Carousel from "bootstrap/js/dist/carousel";
|
||||
import type Modal from "bootstrap/js/dist/modal";
|
||||
|
||||
import DynamicallySlottable from "../components/DynamicallySlottable.svelte";
|
||||
import Item from "../components/Item.svelte";
|
||||
import * as tr from "../lib/ftl";
|
||||
import CardStateCustomizer from "./CardStateCustomizer.svelte";
|
||||
import HelpModal from "./HelpModal.svelte";
|
||||
import type { DeckOptionsState } from "./lib";
|
||||
import SettingTitle from "./SettingTitle.svelte";
|
||||
import SpinBoxFloatRow from "./SpinBoxFloatRow.svelte";
|
||||
import SpinBoxRow from "./SpinBoxRow.svelte";
|
||||
import TitledContainer from "./TitledContainer.svelte";
|
||||
import type { DeckOption } from "./types";
|
||||
|
||||
export let state: DeckOptionsState;
|
||||
export let api: Record<string, never>;
|
||||
@ -18,9 +24,66 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
const config = state.currentConfig;
|
||||
const defaults = state.defaults;
|
||||
const cardStateCustomizer = state.cardStateCustomizer;
|
||||
|
||||
const settings = {
|
||||
maximumInterval: {
|
||||
title: tr.schedulingMaximumInterval(),
|
||||
help: tr.deckConfigMaximumIntervalTooltip(),
|
||||
url: "https://docs.ankiweb.net/deck-options.html#maximum-interval",
|
||||
},
|
||||
startingEase: {
|
||||
title: tr.schedulingStartingEase(),
|
||||
help: tr.deckConfigStartingEaseTooltip(),
|
||||
url: "https://docs.ankiweb.net/deck-options.html#starting-ease",
|
||||
},
|
||||
easyBonus: {
|
||||
title: tr.schedulingEasyBonus(),
|
||||
help: tr.deckConfigEasyBonusTooltip(),
|
||||
url: "https://docs.ankiweb.net/deck-options.html#easy-bonus",
|
||||
},
|
||||
intervalModifier: {
|
||||
title: tr.schedulingIntervalModifier(),
|
||||
help: tr.deckConfigIntervalModifierTooltip(),
|
||||
url: "https://docs.ankiweb.net/deck-options.html#interval-modifier",
|
||||
},
|
||||
hardInterval: {
|
||||
title: tr.schedulingHardInterval(),
|
||||
help: tr.deckConfigHardIntervalTooltip(),
|
||||
url: "https://docs.ankiweb.net/deck-options.html#hard-interval",
|
||||
},
|
||||
newInterval: {
|
||||
title: tr.schedulingNewInterval(),
|
||||
help: tr.deckConfigNewIntervalTooltip(),
|
||||
url: "https://docs.ankiweb.net/deck-options.html#new-interval",
|
||||
},
|
||||
customScheduling: {
|
||||
title: tr.deckConfigCustomScheduling(),
|
||||
help: tr.deckConfigCustomSchedulingTooltip(),
|
||||
url: "https://faqs.ankiweb.net/the-2021-scheduler.html#add-ons-and-custom-scheduling",
|
||||
},
|
||||
};
|
||||
const helpSections = Object.values(settings) as DeckOption[];
|
||||
|
||||
let modal: Modal;
|
||||
let carousel: Carousel;
|
||||
|
||||
function openHelpModal(index: number): void {
|
||||
modal.show();
|
||||
carousel.to(index);
|
||||
}
|
||||
</script>
|
||||
|
||||
<TitledContainer title={tr.deckConfigAdvancedTitle()}>
|
||||
<HelpModal
|
||||
title={tr.deckConfigAdvancedTitle()}
|
||||
url="https://docs.ankiweb.net/deck-options.html#advanced"
|
||||
slot="tooltip"
|
||||
{helpSections}
|
||||
on:mount={(e) => {
|
||||
modal = e.detail.modal;
|
||||
carousel = e.detail.carousel;
|
||||
}}
|
||||
/>
|
||||
<DynamicallySlottable slotHost={Item} {api}>
|
||||
<Item>
|
||||
<SpinBoxRow
|
||||
@ -28,9 +91,12 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
defaultValue={defaults.maximumReviewInterval}
|
||||
min={1}
|
||||
max={365 * 100}
|
||||
markdownTooltip={tr.deckConfigMaximumIntervalTooltip()}
|
||||
>
|
||||
{tr.schedulingMaximumInterval()}
|
||||
<SettingTitle
|
||||
on:click={() =>
|
||||
openHelpModal(Object.keys(settings).indexOf("maximumInterval"))}
|
||||
>{settings.maximumInterval.title}</SettingTitle
|
||||
>
|
||||
</SpinBoxRow>
|
||||
</Item>
|
||||
|
||||
@ -40,9 +106,12 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
defaultValue={defaults.initialEase}
|
||||
min={1.31}
|
||||
max={5}
|
||||
markdownTooltip={tr.deckConfigStartingEaseTooltip()}
|
||||
>
|
||||
{tr.schedulingStartingEase()}
|
||||
<SettingTitle
|
||||
on:click={() =>
|
||||
openHelpModal(Object.keys(settings).indexOf("startingEase"))}
|
||||
>{settings.startingEase.title}</SettingTitle
|
||||
>
|
||||
</SpinBoxFloatRow>
|
||||
</Item>
|
||||
|
||||
@ -52,9 +121,12 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
defaultValue={defaults.easyMultiplier}
|
||||
min={1}
|
||||
max={5}
|
||||
markdownTooltip={tr.deckConfigEasyBonusTooltip()}
|
||||
>
|
||||
{tr.schedulingEasyBonus()}
|
||||
<SettingTitle
|
||||
on:click={() =>
|
||||
openHelpModal(Object.keys(settings).indexOf("easyBonus"))}
|
||||
>{settings.easyBonus.title}</SettingTitle
|
||||
>
|
||||
</SpinBoxFloatRow>
|
||||
</Item>
|
||||
|
||||
@ -64,9 +136,13 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
defaultValue={defaults.intervalMultiplier}
|
||||
min={0.5}
|
||||
max={2}
|
||||
markdownTooltip={tr.deckConfigIntervalModifierTooltip()}
|
||||
>
|
||||
{tr.schedulingIntervalModifier()}
|
||||
<SettingTitle
|
||||
on:click={() =>
|
||||
openHelpModal(
|
||||
Object.keys(settings).indexOf("intervalModifier"),
|
||||
)}>{settings.intervalModifier.title}</SettingTitle
|
||||
>
|
||||
</SpinBoxFloatRow>
|
||||
</Item>
|
||||
|
||||
@ -76,9 +152,12 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
defaultValue={defaults.hardMultiplier}
|
||||
min={0.5}
|
||||
max={1.3}
|
||||
markdownTooltip={tr.deckConfigHardIntervalTooltip()}
|
||||
>
|
||||
{tr.schedulingHardInterval()}
|
||||
<SettingTitle
|
||||
on:click={() =>
|
||||
openHelpModal(Object.keys(settings).indexOf("hardInterval"))}
|
||||
>{settings.hardInterval.title}</SettingTitle
|
||||
>
|
||||
</SpinBoxFloatRow>
|
||||
</Item>
|
||||
|
||||
@ -87,15 +166,25 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
bind:value={$config.lapseMultiplier}
|
||||
defaultValue={defaults.lapseMultiplier}
|
||||
max={1}
|
||||
markdownTooltip={tr.deckConfigNewIntervalTooltip()}
|
||||
>
|
||||
{tr.schedulingNewInterval()}
|
||||
<SettingTitle
|
||||
on:click={() =>
|
||||
openHelpModal(Object.keys(settings).indexOf("newInterval"))}
|
||||
>{settings.newInterval.title}</SettingTitle
|
||||
>
|
||||
</SpinBoxFloatRow>
|
||||
</Item>
|
||||
|
||||
{#if state.v3Scheduler}
|
||||
<Item>
|
||||
<CardStateCustomizer bind:value={$cardStateCustomizer} />
|
||||
<CardStateCustomizer
|
||||
title={settings.customScheduling.title}
|
||||
on:click={() =>
|
||||
openHelpModal(
|
||||
Object.keys(settings).indexOf("customScheduling"),
|
||||
)}
|
||||
bind:value={$cardStateCustomizer}
|
||||
/>
|
||||
</Item>
|
||||
{/if}
|
||||
</DynamicallySlottable>
|
||||
|
@ -3,28 +3,68 @@ Copyright: Ankitects Pty Ltd and contributors
|
||||
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
-->
|
||||
<script lang="ts">
|
||||
import type Carousel from "bootstrap/js/dist/carousel";
|
||||
import type Modal from "bootstrap/js/dist/modal";
|
||||
|
||||
import DynamicallySlottable from "../components/DynamicallySlottable.svelte";
|
||||
import Item from "../components/Item.svelte";
|
||||
import * as tr from "../lib/ftl";
|
||||
import HelpModal from "./HelpModal.svelte";
|
||||
import type { DeckOptionsState } from "./lib";
|
||||
import SettingTitle from "./SettingTitle.svelte";
|
||||
import SwitchRow from "./SwitchRow.svelte";
|
||||
import TitledContainer from "./TitledContainer.svelte";
|
||||
import type { DeckOption } from "./types";
|
||||
|
||||
export let state: DeckOptionsState;
|
||||
export let api: Record<string, never>;
|
||||
|
||||
const config = state.currentConfig;
|
||||
const defaults = state.defaults;
|
||||
|
||||
const settings = {
|
||||
disableAutoplay: {
|
||||
title: tr.deckConfigDisableAutoplay(),
|
||||
help: tr.deckConfigDisableAutoplayTooltip(),
|
||||
},
|
||||
skipQuestionWhenReplaying: {
|
||||
title: tr.deckConfigSkipQuestionWhenReplaying(),
|
||||
help: tr.deckConfigAlwaysIncludeQuestionAudioTooltip(),
|
||||
},
|
||||
};
|
||||
const helpSections = Object.values(settings) as DeckOption[];
|
||||
|
||||
let modal: Modal;
|
||||
let carousel: Carousel;
|
||||
|
||||
function openHelpModal(index: number): void {
|
||||
modal.show();
|
||||
carousel.to(index);
|
||||
}
|
||||
</script>
|
||||
|
||||
<TitledContainer title={tr.deckConfigAudioTitle()}>
|
||||
<HelpModal
|
||||
title={tr.deckConfigAudioTitle()}
|
||||
url="https://docs.ankiweb.net/deck-options.html#audio"
|
||||
slot="tooltip"
|
||||
{helpSections}
|
||||
on:mount={(e) => {
|
||||
modal = e.detail.modal;
|
||||
carousel = e.detail.carousel;
|
||||
}}
|
||||
/>
|
||||
<DynamicallySlottable slotHost={Item} {api}>
|
||||
<Item>
|
||||
<SwitchRow
|
||||
bind:value={$config.disableAutoplay}
|
||||
defaultValue={defaults.disableAutoplay}
|
||||
>
|
||||
{tr.deckConfigDisableAutoplay()}
|
||||
<SettingTitle
|
||||
on:click={() =>
|
||||
openHelpModal(Object.keys(settings).indexOf("disableAutoplay"))}
|
||||
>{settings.disableAutoplay.title}</SettingTitle
|
||||
>
|
||||
</SwitchRow>
|
||||
</Item>
|
||||
|
||||
@ -32,9 +72,13 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
<SwitchRow
|
||||
bind:value={$config.skipQuestionWhenReplayingAnswer}
|
||||
defaultValue={defaults.skipQuestionWhenReplayingAnswer}
|
||||
markdownTooltip={tr.deckConfigAlwaysIncludeQuestionAudioTooltip()}
|
||||
>
|
||||
{tr.deckConfigSkipQuestionWhenReplaying()}
|
||||
<SettingTitle
|
||||
on:click={() =>
|
||||
openHelpModal(
|
||||
Object.keys(settings).indexOf("skipQuestionWhenReplaying"),
|
||||
)}>{settings.skipQuestionWhenReplaying.title}</SettingTitle
|
||||
>
|
||||
</SwitchRow>
|
||||
</Item>
|
||||
</DynamicallySlottable>
|
||||
|
@ -18,6 +18,7 @@ compile_sass(
|
||||
"//sass:breakpoints_lib",
|
||||
"//sass:scrollbar_lib",
|
||||
"//sass:night_mode_lib",
|
||||
"//sass:elevation_lib",
|
||||
"//sass/bootstrap",
|
||||
],
|
||||
)
|
||||
@ -43,6 +44,7 @@ compile_svelte(
|
||||
"//sass:breakpoints_lib",
|
||||
"//sass:scrollbar_lib",
|
||||
"//sass:night_mode_lib",
|
||||
"//sass:elevation_lib",
|
||||
"//sass/bootstrap",
|
||||
],
|
||||
)
|
||||
@ -88,6 +90,7 @@ svelte_check(
|
||||
"//sass:scrollbar_lib",
|
||||
"//sass:breakpoints_lib",
|
||||
"//sass:night_mode_lib",
|
||||
"//sass:elevation_lib",
|
||||
"//sass/bootstrap",
|
||||
"//ts/components",
|
||||
"//ts/sveltelib:sveltelib_pkg",
|
||||
|
@ -3,29 +3,69 @@ Copyright: Ankitects Pty Ltd and contributors
|
||||
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
-->
|
||||
<script lang="ts">
|
||||
import type Carousel from "bootstrap/js/dist/carousel";
|
||||
import type Modal from "bootstrap/js/dist/modal";
|
||||
|
||||
import DynamicallySlottable from "../components/DynamicallySlottable.svelte";
|
||||
import Item from "../components/Item.svelte";
|
||||
import * as tr from "../lib/ftl";
|
||||
import HelpModal from "./HelpModal.svelte";
|
||||
import type { DeckOptionsState } from "./lib";
|
||||
import SettingTitle from "./SettingTitle.svelte";
|
||||
import SwitchRow from "./SwitchRow.svelte";
|
||||
import TitledContainer from "./TitledContainer.svelte";
|
||||
import type { DeckOption } from "./types";
|
||||
|
||||
export let state: DeckOptionsState;
|
||||
export let api: Record<string, never>;
|
||||
|
||||
const config = state.currentConfig;
|
||||
const defaults = state.defaults;
|
||||
|
||||
const settings = {
|
||||
buryNewSiblings: {
|
||||
title: tr.deckConfigBuryNewSiblings(),
|
||||
help: tr.deckConfigBuryNewTooltip(),
|
||||
},
|
||||
buryReviewSiblings: {
|
||||
title: tr.deckConfigBuryReviewSiblings(),
|
||||
help: tr.deckConfigBuryReviewTooltip(),
|
||||
},
|
||||
buryInterdayLearningSiblings: {
|
||||
title: tr.deckConfigBuryInterdayLearningSiblings(),
|
||||
help: tr.deckConfigBuryInterdayLearningTooltip(),
|
||||
},
|
||||
};
|
||||
const helpSections = Object.values(settings) as DeckOption[];
|
||||
|
||||
let modal: Modal;
|
||||
let carousel: Carousel;
|
||||
|
||||
function openHelpModal(index: number): void {
|
||||
modal.show();
|
||||
carousel.to(index);
|
||||
}
|
||||
</script>
|
||||
|
||||
<TitledContainer title={tr.deckConfigBuryTitle()}>
|
||||
<HelpModal
|
||||
title={tr.deckConfigBuryTitle()}
|
||||
url="https://docs.ankiweb.net/studying.html#siblings-and-burying"
|
||||
slot="tooltip"
|
||||
{helpSections}
|
||||
on:mount={(e) => {
|
||||
modal = e.detail.modal;
|
||||
carousel = e.detail.carousel;
|
||||
}}
|
||||
/>
|
||||
<DynamicallySlottable slotHost={Item} {api}>
|
||||
<Item>
|
||||
<SwitchRow
|
||||
bind:value={$config.buryNew}
|
||||
defaultValue={defaults.buryNew}
|
||||
markdownTooltip={tr.deckConfigBuryTooltip()}
|
||||
>
|
||||
{tr.deckConfigBuryNewSiblings()}
|
||||
<SwitchRow bind:value={$config.buryNew} defaultValue={defaults.buryNew}>
|
||||
<SettingTitle
|
||||
on:click={() =>
|
||||
openHelpModal(Object.keys(settings).indexOf("buryNewSiblings"))}
|
||||
>{settings.buryNewSiblings.title}</SettingTitle
|
||||
>
|
||||
</SwitchRow>
|
||||
</Item>
|
||||
|
||||
@ -33,9 +73,13 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
<SwitchRow
|
||||
bind:value={$config.buryReviews}
|
||||
defaultValue={defaults.buryReviews}
|
||||
markdownTooltip={tr.deckConfigBuryTooltip()}
|
||||
>
|
||||
{tr.deckConfigBuryReviewSiblings()}
|
||||
<SettingTitle
|
||||
on:click={() =>
|
||||
openHelpModal(
|
||||
Object.keys(settings).indexOf("buryReviewSiblings"),
|
||||
)}>{settings.buryReviewSiblings.title}</SettingTitle
|
||||
>
|
||||
</SwitchRow>
|
||||
</Item>
|
||||
|
||||
@ -44,9 +88,16 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
<SwitchRow
|
||||
bind:value={$config.buryInterdayLearning}
|
||||
defaultValue={defaults.buryInterdayLearning}
|
||||
markdownTooltip={tr.deckConfigBuryTooltip()}
|
||||
>
|
||||
{tr.deckConfigBuryInterdayLearningSiblings()}
|
||||
<SettingTitle
|
||||
on:click={() =>
|
||||
openHelpModal(
|
||||
Object.keys(settings).indexOf(
|
||||
"buryInterdayLearningSiblings",
|
||||
),
|
||||
)}
|
||||
>{settings.buryInterdayLearningSiblings.title}</SettingTitle
|
||||
>
|
||||
</SwitchRow>
|
||||
</Item>
|
||||
{/if}
|
||||
|
@ -5,20 +5,21 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
<script lang="ts">
|
||||
import Col from "../components/Col.svelte";
|
||||
import Row from "../components/Row.svelte";
|
||||
import * as tr from "../lib/ftl";
|
||||
import ConfigInput from "./ConfigInput.svelte";
|
||||
import RevertButton from "./RevertButton.svelte";
|
||||
import TooltipLabel from "./TooltipLabel.svelte";
|
||||
import SettingTitle from "./SettingTitle.svelte";
|
||||
|
||||
export let value: string;
|
||||
export let title: string;
|
||||
</script>
|
||||
|
||||
<Row>
|
||||
<Col>
|
||||
<div class="text">
|
||||
<TooltipLabel markdownTooltip={tr.deckConfigCustomSchedulingTooltip()}>
|
||||
{tr.deckConfigCustomScheduling()}:</TooltipLabel
|
||||
>
|
||||
<RevertButton bind:value defaultValue="" />
|
||||
<ConfigInput>
|
||||
<SettingTitle on:click>{title}</SettingTitle>
|
||||
<RevertButton slot="revert" bind:value defaultValue="" />
|
||||
</ConfigInput>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
@ -32,13 +33,13 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
<style lang="scss">
|
||||
.text {
|
||||
width: 100%;
|
||||
min-height: 2em;
|
||||
}
|
||||
|
||||
.card-state-customizer {
|
||||
color: var(--fg);
|
||||
background-color: var(--canvas-elevated);
|
||||
|
||||
background-color: var(--canvas-code);
|
||||
border: 1px solid var(--border-subtle);
|
||||
width: 100%;
|
||||
height: 10em;
|
||||
font-family: monospace;
|
||||
|
38
ts/deck-options/ConfigInput.svelte
Normal file
38
ts/deck-options/ConfigInput.svelte
Normal file
@ -0,0 +1,38 @@
|
||||
<!--
|
||||
Copyright: Ankitects Pty Ltd and contributors
|
||||
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
-->
|
||||
<script lang="ts">
|
||||
export let grow = true;
|
||||
let width = 0;
|
||||
</script>
|
||||
|
||||
<div
|
||||
class="config-input position-relative justify-content-end"
|
||||
class:flex-grow-1={grow}
|
||||
style:--offset="-{width}px"
|
||||
>
|
||||
<div class="revert" bind:clientWidth={width}>
|
||||
<slot name="revert" />
|
||||
</div>
|
||||
<slot />
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.revert {
|
||||
position: absolute;
|
||||
right: var(--offset);
|
||||
color: var(--fg-faint);
|
||||
}
|
||||
.config-input {
|
||||
&:hover,
|
||||
&:focus-within {
|
||||
.revert {
|
||||
color: var(--fg-subtle);
|
||||
}
|
||||
}
|
||||
.revert:hover {
|
||||
color: var(--fg);
|
||||
}
|
||||
}
|
||||
</style>
|
@ -3,14 +3,20 @@
|
||||
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
-->
|
||||
<script lang="ts">
|
||||
import type Carousel from "bootstrap/js/dist/carousel";
|
||||
import type Modal from "bootstrap/js/dist/modal";
|
||||
|
||||
import DynamicallySlottable from "../components/DynamicallySlottable.svelte";
|
||||
import Item from "../components/Item.svelte";
|
||||
import * as tr from "../lib/ftl";
|
||||
import HelpModal from "./HelpModal.svelte";
|
||||
import type { DeckOptionsState } from "./lib";
|
||||
import { ValueTab } from "./lib";
|
||||
import SettingTitle from "./SettingTitle.svelte";
|
||||
import SpinBoxRow from "./SpinBoxRow.svelte";
|
||||
import TabbedValue from "./TabbedValue.svelte";
|
||||
import TitledContainer from "./TitledContainer.svelte";
|
||||
import type { DeckOption } from "./types";
|
||||
import Warning from "./Warning.svelte";
|
||||
|
||||
export let state: DeckOptionsState;
|
||||
@ -120,35 +126,66 @@
|
||||
: [],
|
||||
);
|
||||
|
||||
let reviewsValue: number;
|
||||
let newValue: number;
|
||||
let reviewsValue: number;
|
||||
|
||||
const settings = {
|
||||
newLimit: {
|
||||
title: tr.schedulingNewCardsday(),
|
||||
help: tr.deckConfigNewLimitTooltip() + v3Extra,
|
||||
url: "https://docs.ankiweb.net/deck-options.html#new-cardsday",
|
||||
},
|
||||
reviewLimit: {
|
||||
title: tr.schedulingMaximumReviewsday(),
|
||||
help: tr.deckConfigReviewLimitTooltip() + v3Extra,
|
||||
url: "https://docs.ankiweb.net/deck-options.html#maximum-reviewsday",
|
||||
},
|
||||
};
|
||||
const helpSections = Object.values(settings) as DeckOption[];
|
||||
|
||||
let modal: Modal;
|
||||
let carousel: Carousel;
|
||||
|
||||
function openHelpModal(index: number): void {
|
||||
modal.show();
|
||||
carousel.to(index);
|
||||
}
|
||||
</script>
|
||||
|
||||
<TitledContainer title={tr.deckConfigDailyLimits()}>
|
||||
<HelpModal
|
||||
title={tr.deckConfigDailyLimits()}
|
||||
url="https://docs.ankiweb.net/deck-options.html#daily-limits"
|
||||
slot="tooltip"
|
||||
{helpSections}
|
||||
on:mount={(e) => {
|
||||
modal = e.detail.modal;
|
||||
carousel = e.detail.carousel;
|
||||
}}
|
||||
/>
|
||||
<DynamicallySlottable slotHost={Item} {api}>
|
||||
<TabbedValue tabs={newTabs} bind:value={newValue} />
|
||||
<Item>
|
||||
<SpinBoxRow
|
||||
bind:value={newValue}
|
||||
defaultValue={defaults.newPerDay}
|
||||
markdownTooltip={tr.deckConfigNewLimitTooltip() + v3Extra}
|
||||
>
|
||||
{tr.schedulingNewCardsday()}
|
||||
<SpinBoxRow bind:value={newValue} defaultValue={defaults.newPerDay}>
|
||||
<TabbedValue slot="tabs" tabs={newTabs} bind:value={newValue} />
|
||||
<SettingTitle
|
||||
on:click={() =>
|
||||
openHelpModal(Object.keys(settings).indexOf("newLimit"))}
|
||||
>{settings.newLimit.title}</SettingTitle
|
||||
>
|
||||
</SpinBoxRow>
|
||||
</Item>
|
||||
|
||||
<Item>
|
||||
<Warning warning={newCardsGreaterThanParent} />
|
||||
</Item>
|
||||
|
||||
<TabbedValue tabs={reviewTabs} bind:value={reviewsValue} />
|
||||
<Item>
|
||||
<SpinBoxRow
|
||||
bind:value={reviewsValue}
|
||||
defaultValue={defaults.reviewsPerDay}
|
||||
markdownTooltip={tr.deckConfigReviewLimitTooltip() + v3Extra}
|
||||
>
|
||||
{tr.schedulingMaximumReviewsday()}
|
||||
<SpinBoxRow bind:value={reviewsValue} defaultValue={defaults.reviewsPerDay}>
|
||||
<TabbedValue slot="tabs" tabs={reviewTabs} bind:value={reviewsValue} />
|
||||
<SettingTitle
|
||||
on:click={() =>
|
||||
openHelpModal(Object.keys(settings).indexOf("reviewLimit"))}
|
||||
>{settings.reviewLimit.title}</SettingTitle
|
||||
>
|
||||
</SpinBoxRow>
|
||||
</Item>
|
||||
|
||||
|
@ -64,7 +64,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
<Container
|
||||
breakpoint="sm"
|
||||
--gutter-inline="0.25rem"
|
||||
--gutter-block="0.5rem"
|
||||
--gutter-block="0.75rem"
|
||||
class="container-columns"
|
||||
>
|
||||
<DynamicallySlottable slotHost={Item} api={options}>
|
||||
|
@ -3,14 +3,20 @@ Copyright: Ankitects Pty Ltd and contributors
|
||||
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
-->
|
||||
<script lang="ts">
|
||||
import type Carousel from "bootstrap/js/dist/carousel";
|
||||
import type Modal from "bootstrap/js/dist/modal";
|
||||
|
||||
import DynamicallySlottable from "../components/DynamicallySlottable.svelte";
|
||||
import Item from "../components/Item.svelte";
|
||||
import * as tr from "../lib/ftl";
|
||||
import { DeckConfig } from "../lib/proto";
|
||||
import EnumSelectorRow from "./EnumSelectorRow.svelte";
|
||||
import HelpModal from "./HelpModal.svelte";
|
||||
import type { DeckOptionsState } from "./lib";
|
||||
import SettingTitle from "./SettingTitle.svelte";
|
||||
import { reviewMixChoices } from "./strings";
|
||||
import TitledContainer from "./TitledContainer.svelte";
|
||||
import type { DeckOption } from "./types";
|
||||
|
||||
export let state: DeckOptionsState;
|
||||
export let api: Record<string, never>;
|
||||
@ -84,19 +90,64 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
$config.newCardSortOrder = 0;
|
||||
}
|
||||
}
|
||||
|
||||
const settings = {
|
||||
newGatherPriority: {
|
||||
title: tr.deckConfigNewGatherPriority(),
|
||||
help: tr.deckConfigNewGatherPriorityTooltip_2() + currentDeck,
|
||||
},
|
||||
newCardSortOrder: {
|
||||
title: tr.deckConfigNewCardSortOrder(),
|
||||
help: tr.deckConfigNewCardSortOrderTooltip_2() + currentDeck,
|
||||
},
|
||||
newReviewPriority: {
|
||||
title: tr.deckConfigNewReviewPriority(),
|
||||
help: tr.deckConfigNewReviewPriorityTooltip() + currentDeck,
|
||||
},
|
||||
interdayStepPriority: {
|
||||
title: tr.deckConfigInterdayStepPriority(),
|
||||
help: tr.deckConfigInterdayStepPriorityTooltip() + currentDeck,
|
||||
},
|
||||
reviewSortOrder: {
|
||||
title: tr.deckConfigReviewSortOrder(),
|
||||
help: tr.deckConfigReviewSortOrderTooltip() + currentDeck,
|
||||
},
|
||||
};
|
||||
const helpSections = Object.values(settings) as DeckOption[];
|
||||
|
||||
let modal: Modal;
|
||||
let carousel: Carousel;
|
||||
|
||||
function openHelpModal(index: number): void {
|
||||
modal.show();
|
||||
carousel.to(index);
|
||||
}
|
||||
</script>
|
||||
|
||||
<TitledContainer title={tr.deckConfigOrderingTitle()}>
|
||||
<HelpModal
|
||||
title={tr.deckConfigOrderingTitle()}
|
||||
url="https://docs.ankiweb.net/deck-options.html#display-order"
|
||||
slot="tooltip"
|
||||
{helpSections}
|
||||
on:mount={(e) => {
|
||||
modal = e.detail.modal;
|
||||
carousel = e.detail.carousel;
|
||||
}}
|
||||
/>
|
||||
<DynamicallySlottable slotHost={Item} {api}>
|
||||
<Item>
|
||||
<EnumSelectorRow
|
||||
bind:value={$config.newCardGatherPriority}
|
||||
defaultValue={defaults.newCardGatherPriority}
|
||||
choices={newGatherPriorityChoices}
|
||||
markdownTooltip={tr.deckConfigNewGatherPriorityTooltip_2() +
|
||||
currentDeck}
|
||||
>
|
||||
{tr.deckConfigNewGatherPriority()}
|
||||
<SettingTitle
|
||||
on:click={() =>
|
||||
openHelpModal(
|
||||
Object.keys(settings).indexOf("newGatherPriority"),
|
||||
)}>{settings.newGatherPriority.title}</SettingTitle
|
||||
>
|
||||
</EnumSelectorRow>
|
||||
</Item>
|
||||
|
||||
@ -106,9 +157,13 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
defaultValue={defaults.newCardSortOrder}
|
||||
choices={newSortOrderChoices}
|
||||
disabled={disabledNewSortOrders}
|
||||
markdownTooltip={tr.deckConfigNewCardSortOrderTooltip_2() + currentDeck}
|
||||
>
|
||||
{tr.deckConfigNewCardSortOrder()}
|
||||
<SettingTitle
|
||||
on:click={() =>
|
||||
openHelpModal(
|
||||
Object.keys(settings).indexOf("newCardSortOrder"),
|
||||
)}>{settings.newCardSortOrder.title}</SettingTitle
|
||||
>
|
||||
</EnumSelectorRow>
|
||||
</Item>
|
||||
|
||||
@ -117,9 +172,13 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
bind:value={$config.newMix}
|
||||
defaultValue={defaults.newMix}
|
||||
choices={reviewMixChoices()}
|
||||
markdownTooltip={tr.deckConfigNewReviewPriorityTooltip() + currentDeck}
|
||||
>
|
||||
{tr.deckConfigNewReviewPriority()}
|
||||
<SettingTitle
|
||||
on:click={() =>
|
||||
openHelpModal(
|
||||
Object.keys(settings).indexOf("newReviewPriority"),
|
||||
)}>{settings.newReviewPriority.title}</SettingTitle
|
||||
>
|
||||
</EnumSelectorRow>
|
||||
</Item>
|
||||
|
||||
@ -128,10 +187,13 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
bind:value={$config.interdayLearningMix}
|
||||
defaultValue={defaults.interdayLearningMix}
|
||||
choices={reviewMixChoices()}
|
||||
markdownTooltip={tr.deckConfigInterdayStepPriorityTooltip() +
|
||||
currentDeck}
|
||||
>
|
||||
{tr.deckConfigInterdayStepPriority()}
|
||||
<SettingTitle
|
||||
on:click={() =>
|
||||
openHelpModal(
|
||||
Object.keys(settings).indexOf("interdayStepPriority"),
|
||||
)}>{settings.interdayStepPriority.title}</SettingTitle
|
||||
>
|
||||
</EnumSelectorRow>
|
||||
</Item>
|
||||
|
||||
@ -140,9 +202,12 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
bind:value={$config.reviewOrder}
|
||||
defaultValue={defaults.reviewOrder}
|
||||
choices={reviewOrderChoices}
|
||||
markdownTooltip={tr.deckConfigReviewSortOrderTooltip() + currentDeck}
|
||||
>
|
||||
{tr.deckConfigReviewSortOrder()}
|
||||
<SettingTitle
|
||||
on:click={() =>
|
||||
openHelpModal(Object.keys(settings).indexOf("reviewSortOrder"))}
|
||||
>{settings.reviewSortOrder.title}</SettingTitle
|
||||
>
|
||||
</EnumSelectorRow>
|
||||
</Item>
|
||||
</DynamicallySlottable>
|
||||
|
@ -6,24 +6,25 @@
|
||||
import Col from "../components/Col.svelte";
|
||||
import Row from "../components/Row.svelte";
|
||||
import type { Breakpoint } from "../components/types";
|
||||
import ConfigInput from "./ConfigInput.svelte";
|
||||
import EnumSelector from "./EnumSelector.svelte";
|
||||
import RevertButton from "./RevertButton.svelte";
|
||||
import TooltipLabel from "./TooltipLabel.svelte";
|
||||
|
||||
export let value: number;
|
||||
export let defaultValue: number;
|
||||
export let breakpoint: Breakpoint = "md";
|
||||
export let choices: string[];
|
||||
export let disabled: number[] = [];
|
||||
export let markdownTooltip: string;
|
||||
</script>
|
||||
|
||||
<Row --cols={12}>
|
||||
<Row --cols={13}>
|
||||
<Col --col-size={7} {breakpoint}>
|
||||
<TooltipLabel {markdownTooltip}><slot /></TooltipLabel>
|
||||
<slot />
|
||||
</Col>
|
||||
<Col --col-size={5} {breakpoint}>
|
||||
<EnumSelector bind:value options={choices} {disabled} />
|
||||
<RevertButton bind:value {defaultValue} />
|
||||
<Col --col-size={6} {breakpoint}>
|
||||
<ConfigInput>
|
||||
<EnumSelector bind:value options={choices} {disabled} />
|
||||
<RevertButton slot="revert" bind:value {defaultValue} />
|
||||
</ConfigInput>
|
||||
</Col>
|
||||
</Row>
|
||||
|
183
ts/deck-options/HelpModal.svelte
Normal file
183
ts/deck-options/HelpModal.svelte
Normal file
@ -0,0 +1,183 @@
|
||||
<!--
|
||||
Copyright: Ankitects Pty Ltd and contributors
|
||||
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
-->
|
||||
<script lang="ts">
|
||||
import Carousel from "bootstrap/js/dist/carousel";
|
||||
import Modal from "bootstrap/js/dist/modal";
|
||||
import { createEventDispatcher, getContext, onMount } from "svelte";
|
||||
|
||||
import Badge from "../components/Badge.svelte";
|
||||
import Col from "../components/Col.svelte";
|
||||
import { modalsKey } from "../components/context-keys";
|
||||
import Row from "../components/Row.svelte";
|
||||
import * as tr from "../lib/ftl";
|
||||
import { pageTheme } from "../sveltelib/theme";
|
||||
import HelpSection from "./HelpSection.svelte";
|
||||
import { infoCircle } from "./icons";
|
||||
import type { DeckOption } from "./types";
|
||||
|
||||
export let title: string;
|
||||
export let url: string;
|
||||
export let startIndex = 0;
|
||||
export let helpSections: DeckOption[];
|
||||
|
||||
export const modalKey: string = Math.random().toString(36).substring(2);
|
||||
|
||||
const modals = getContext<Map<string, Modal>>(modalsKey);
|
||||
|
||||
let modal: Modal;
|
||||
let carousel: Carousel;
|
||||
|
||||
let modalRef: HTMLDivElement;
|
||||
let carouselRef: HTMLDivElement;
|
||||
|
||||
function onOkClicked(): void {
|
||||
modal.hide();
|
||||
}
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
onMount(() => {
|
||||
modal = new Modal(modalRef);
|
||||
carousel = new Carousel(carouselRef, { interval: false, ride: false });
|
||||
/* Bootstrap's Carousel.Event interface doesn't seem to work as a type here */
|
||||
carouselRef.addEventListener("slide.bs.carousel", (e: any) => {
|
||||
activeIndex = e.to;
|
||||
});
|
||||
dispatch("mount", { modal: modal, carousel: carousel });
|
||||
modals.set(modalKey, modal);
|
||||
});
|
||||
|
||||
let activeIndex = startIndex;
|
||||
</script>
|
||||
|
||||
<Badge on:click={() => modal.show()}>
|
||||
{@html infoCircle}
|
||||
</Badge>
|
||||
|
||||
<div
|
||||
bind:this={modalRef}
|
||||
class="modal fade"
|
||||
tabindex="-1"
|
||||
aria-labelledby="modalLabel"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h1 class="modal-title" id="modalLabel">
|
||||
{title}
|
||||
</h1>
|
||||
<button
|
||||
type="button"
|
||||
class="btn-close"
|
||||
class:invert={$pageTheme.isDark}
|
||||
data-bs-dismiss="modal"
|
||||
aria-label="Close"
|
||||
/>
|
||||
{#if url}
|
||||
<div class="chapter-redirect">
|
||||
{@html tr.helpViewChapterInManual({
|
||||
chapter: `<a href="${url}" title="${tr.helpOpenManualChapter(
|
||||
{ name: title },
|
||||
)}">${tr.helpChapter()}</a>`,
|
||||
})}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<Row --cols={4}>
|
||||
<Col --col-size={1}>
|
||||
<nav>
|
||||
<div id="nav">
|
||||
<ul>
|
||||
{#each helpSections as section, i}
|
||||
<li
|
||||
on:click={() => {
|
||||
activeIndex = i;
|
||||
carousel.to(activeIndex);
|
||||
}}
|
||||
>
|
||||
<span class:active={i == activeIndex}>
|
||||
{section.title}
|
||||
</span>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
</Col>
|
||||
<Col --col-size={3}>
|
||||
<div
|
||||
id="helpSectionIndicators"
|
||||
class="carousel slide"
|
||||
bind:this={carouselRef}
|
||||
>
|
||||
<div class="carousel-inner">
|
||||
{#each helpSections as section, i}
|
||||
<div
|
||||
class="carousel-item"
|
||||
class:active={i == startIndex}
|
||||
>
|
||||
<HelpSection {section} />
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-primary" on:click={onOkClicked}
|
||||
>OK</button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.modal-header {
|
||||
align-items: unset;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.chapter-redirect {
|
||||
width: 100%;
|
||||
color: var(--fg-subtle);
|
||||
font-size: small;
|
||||
}
|
||||
#nav {
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
padding-top: 0.5rem;
|
||||
background-color: var(--canvas);
|
||||
color: var(--fg);
|
||||
border-radius: var(--border-radius-large, 10px);
|
||||
}
|
||||
|
||||
.invert {
|
||||
filter: invert(1) grayscale(100%) brightness(200%);
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
li span {
|
||||
display: block;
|
||||
padding: 0.5rem 0.75rem;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
background-color: var(--canvas-inset);
|
||||
}
|
||||
&.active {
|
||||
border-left: 4px solid var(--border-focus);
|
||||
}
|
||||
}
|
||||
</style>
|
70
ts/deck-options/HelpSection.svelte
Normal file
70
ts/deck-options/HelpSection.svelte
Normal file
@ -0,0 +1,70 @@
|
||||
<!--
|
||||
Copyright: Ankitects Pty Ltd and contributors
|
||||
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { marked } from "marked";
|
||||
|
||||
import Row from "../components/Row.svelte";
|
||||
import * as tr from "../lib/ftl";
|
||||
import type { DeckOption } from "./types";
|
||||
|
||||
export let section: DeckOption;
|
||||
</script>
|
||||
|
||||
<Row>
|
||||
<h2>
|
||||
{#if section.url}
|
||||
<a
|
||||
href={section.url}
|
||||
title={tr.helpOpenManualChapter({ name: section.title })}
|
||||
>
|
||||
{@html section.title}
|
||||
</a>
|
||||
{:else}
|
||||
{@html section.title}
|
||||
{/if}
|
||||
</h2>
|
||||
{#if section.help}
|
||||
{@html marked(section.help)}
|
||||
{:else}
|
||||
{@html marked(
|
||||
tr.helpNoExplanation({
|
||||
link: "[GitHub](https://github.com/ankitects/anki)",
|
||||
}),
|
||||
)}
|
||||
{/if}
|
||||
</Row>
|
||||
{#if section.url}
|
||||
<hr />
|
||||
<div class="chapter-redirect">
|
||||
{@html marked(
|
||||
tr.helpForMoreInfo({
|
||||
link: `<a href="${section.url}" title="${tr.helpOpenManualChapter({
|
||||
name: section.title,
|
||||
})}">${section.title}</a>`,
|
||||
}),
|
||||
)}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<style lang="scss">
|
||||
h2 {
|
||||
margin-bottom: 1em;
|
||||
a {
|
||||
cursor: pointer;
|
||||
border-bottom: 1px solid var(--border);
|
||||
text-decoration: none;
|
||||
color: var(--fg);
|
||||
&:hover {
|
||||
border-color: var(--fg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.chapter-redirect {
|
||||
width: 100%;
|
||||
color: var(--fg-subtle);
|
||||
font-size: small;
|
||||
}
|
||||
</style>
|
@ -3,14 +3,20 @@ Copyright: Ankitects Pty Ltd and contributors
|
||||
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
-->
|
||||
<script lang="ts">
|
||||
import type Carousel from "bootstrap/js/dist/carousel";
|
||||
import type Modal from "bootstrap/js/dist/modal";
|
||||
|
||||
import DynamicallySlottable from "../components/DynamicallySlottable.svelte";
|
||||
import Item from "../components/Item.svelte";
|
||||
import * as tr from "../lib/ftl";
|
||||
import EnumSelectorRow from "./EnumSelectorRow.svelte";
|
||||
import HelpModal from "./HelpModal.svelte";
|
||||
import type { DeckOptionsState } from "./lib";
|
||||
import SettingTitle from "./SettingTitle.svelte";
|
||||
import SpinBoxRow from "./SpinBoxRow.svelte";
|
||||
import StepsInputRow from "./StepsInputRow.svelte";
|
||||
import TitledContainer from "./TitledContainer.svelte";
|
||||
import type { DeckOption } from "./types";
|
||||
import Warning from "./Warning.svelte";
|
||||
|
||||
export let state: DeckOptionsState;
|
||||
@ -31,17 +37,62 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
}
|
||||
|
||||
const leechChoices = [tr.actionsSuspendCard(), tr.schedulingTagOnly()];
|
||||
|
||||
const settings = {
|
||||
relearningSteps: {
|
||||
title: tr.deckConfigRelearningSteps(),
|
||||
help: tr.deckConfigRelearningStepsTooltip(),
|
||||
url: "https://docs.ankiweb.net/deck-options.html#relearning-steps",
|
||||
},
|
||||
minimumInterval: {
|
||||
title: tr.schedulingMinimumInterval(),
|
||||
help: tr.deckConfigMinimumIntervalTooltip(),
|
||||
url: "https://docs.ankiweb.net/deck-options.html#minimum-interval",
|
||||
},
|
||||
leechThreshold: {
|
||||
title: tr.schedulingLeechThreshold(),
|
||||
help: tr.deckConfigLeechThresholdTooltip(),
|
||||
url: "https://docs.ankiweb.net/leeches.html#leeches",
|
||||
},
|
||||
leechAction: {
|
||||
title: tr.schedulingLeechAction(),
|
||||
help: tr.deckConfigLeechActionTooltip(),
|
||||
url: "https://docs.ankiweb.net/leeches.html#waiting",
|
||||
},
|
||||
};
|
||||
const helpSections = Object.values(settings) as DeckOption[];
|
||||
|
||||
let modal: Modal;
|
||||
let carousel: Carousel;
|
||||
|
||||
function openHelpModal(index: number): void {
|
||||
modal.show();
|
||||
carousel.to(index);
|
||||
}
|
||||
</script>
|
||||
|
||||
<TitledContainer title={tr.schedulingLapses()}>
|
||||
<HelpModal
|
||||
title={tr.schedulingLapses()}
|
||||
url="https://docs.ankiweb.net/deck-options.html#lapses"
|
||||
slot="tooltip"
|
||||
{helpSections}
|
||||
on:mount={(e) => {
|
||||
modal = e.detail.modal;
|
||||
carousel = e.detail.carousel;
|
||||
}}
|
||||
/>
|
||||
<DynamicallySlottable slotHost={Item} {api}>
|
||||
<Item>
|
||||
<StepsInputRow
|
||||
bind:value={$config.relearnSteps}
|
||||
defaultValue={defaults.relearnSteps}
|
||||
markdownTooltip={tr.deckConfigRelearningStepsTooltip()}
|
||||
>
|
||||
{tr.deckConfigRelearningSteps()}
|
||||
<SettingTitle
|
||||
on:click={() =>
|
||||
openHelpModal(Object.keys(settings).indexOf("relearningSteps"))}
|
||||
>{settings.relearningSteps.title}</SettingTitle
|
||||
>
|
||||
</StepsInputRow>
|
||||
</Item>
|
||||
|
||||
@ -50,9 +101,12 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
bind:value={$config.minimumLapseInterval}
|
||||
defaultValue={defaults.minimumLapseInterval}
|
||||
min={1}
|
||||
markdownTooltip={tr.deckConfigMinimumIntervalTooltip()}
|
||||
>
|
||||
{tr.schedulingMinimumInterval()}
|
||||
<SettingTitle
|
||||
on:click={() =>
|
||||
openHelpModal(Object.keys(settings).indexOf("minimumInterval"))}
|
||||
>{settings.minimumInterval.title}</SettingTitle
|
||||
>
|
||||
</SpinBoxRow>
|
||||
</Item>
|
||||
|
||||
@ -65,9 +119,12 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
bind:value={$config.leechThreshold}
|
||||
defaultValue={defaults.leechThreshold}
|
||||
min={1}
|
||||
markdownTooltip={tr.deckConfigLeechThresholdTooltip()}
|
||||
>
|
||||
{tr.schedulingLeechThreshold()}
|
||||
<SettingTitle
|
||||
on:click={() =>
|
||||
openHelpModal(Object.keys(settings).indexOf("leechThreshold"))}
|
||||
>{settings.leechThreshold.title}</SettingTitle
|
||||
>
|
||||
</SpinBoxRow>
|
||||
</Item>
|
||||
|
||||
@ -76,10 +133,13 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
bind:value={$config.leechAction}
|
||||
defaultValue={defaults.leechAction}
|
||||
choices={leechChoices}
|
||||
breakpoint="sm"
|
||||
markdownTooltip={tr.deckConfigLeechActionTooltip()}
|
||||
breakpoint="md"
|
||||
>
|
||||
{tr.schedulingLeechAction()}
|
||||
<SettingTitle
|
||||
on:click={() =>
|
||||
openHelpModal(Object.keys(settings).indexOf("leechAction"))}
|
||||
>{settings.leechAction.title}</SettingTitle
|
||||
>
|
||||
</EnumSelectorRow>
|
||||
</Item>
|
||||
</DynamicallySlottable>
|
||||
|
@ -3,15 +3,21 @@ Copyright: Ankitects Pty Ltd and contributors
|
||||
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
-->
|
||||
<script lang="ts">
|
||||
import type Carousel from "bootstrap/js/dist/carousel";
|
||||
import type Modal from "bootstrap/js/dist/modal";
|
||||
|
||||
import DynamicallySlottable from "../components/DynamicallySlottable.svelte";
|
||||
import Item from "../components/Item.svelte";
|
||||
import * as tr from "../lib/ftl";
|
||||
import { DeckConfig } from "../lib/proto";
|
||||
import EnumSelectorRow from "./EnumSelectorRow.svelte";
|
||||
import HelpModal from "./HelpModal.svelte";
|
||||
import type { DeckOptionsState } from "./lib";
|
||||
import SettingTitle from "./SettingTitle.svelte";
|
||||
import SpinBoxRow from "./SpinBoxRow.svelte";
|
||||
import StepsInputRow from "./StepsInputRow.svelte";
|
||||
import TitledContainer from "./TitledContainer.svelte";
|
||||
import type { DeckOption } from "./types";
|
||||
import Warning from "./Warning.svelte";
|
||||
|
||||
export let state: DeckOptionsState;
|
||||
@ -47,17 +53,62 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
DeckConfig.DeckConfig.Config.NewCardInsertOrder.NEW_CARD_INSERT_ORDER_RANDOM
|
||||
? tr.deckConfigNewInsertionOrderRandomWithV3()
|
||||
: "";
|
||||
|
||||
const settings = {
|
||||
learningSteps: {
|
||||
title: tr.deckConfigLearningSteps(),
|
||||
help: tr.deckConfigLearningStepsTooltip(),
|
||||
url: "https://docs.ankiweb.net/deck-options.html#learning-steps",
|
||||
},
|
||||
graduatingInterval: {
|
||||
title: tr.schedulingGraduatingInterval(),
|
||||
help: tr.deckConfigGraduatingIntervalTooltip(),
|
||||
url: "https://docs.ankiweb.net/deck-options.html#graduating-interval",
|
||||
},
|
||||
easyInterval: {
|
||||
title: tr.schedulingEasyInterval(),
|
||||
help: tr.deckConfigEasyIntervalTooltip(),
|
||||
url: "https://docs.ankiweb.net/deck-options.html#easy-interval",
|
||||
},
|
||||
insertionOrder: {
|
||||
title: tr.deckConfigNewInsertionOrder(),
|
||||
help: tr.deckConfigNewInsertionOrderTooltip(),
|
||||
url: "https://docs.ankiweb.net/deck-options.html#insertion-order",
|
||||
},
|
||||
};
|
||||
const helpSections = Object.values(settings) as DeckOption[];
|
||||
|
||||
let modal: Modal;
|
||||
let carousel: Carousel;
|
||||
|
||||
function openHelpModal(index: number): void {
|
||||
modal.show();
|
||||
carousel.to(index);
|
||||
}
|
||||
</script>
|
||||
|
||||
<TitledContainer title={tr.schedulingNewCards()}>
|
||||
<HelpModal
|
||||
title={tr.schedulingNewCards()}
|
||||
url="https://docs.ankiweb.net/deck-options.html#new-cards"
|
||||
slot="tooltip"
|
||||
{helpSections}
|
||||
on:mount={(e) => {
|
||||
modal = e.detail.modal;
|
||||
carousel = e.detail.carousel;
|
||||
}}
|
||||
/>
|
||||
<DynamicallySlottable slotHost={Item} {api}>
|
||||
<Item>
|
||||
<StepsInputRow
|
||||
bind:value={$config.learnSteps}
|
||||
defaultValue={defaults.learnSteps}
|
||||
markdownTooltip={tr.deckConfigLearningStepsTooltip()}
|
||||
>
|
||||
{tr.deckConfigLearningSteps()}
|
||||
<SettingTitle
|
||||
on:click={() =>
|
||||
openHelpModal(Object.keys(settings).indexOf("learningSteps"))}
|
||||
>{settings.learningSteps.title}</SettingTitle
|
||||
>
|
||||
</StepsInputRow>
|
||||
</Item>
|
||||
|
||||
@ -65,9 +116,13 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
<SpinBoxRow
|
||||
bind:value={$config.graduatingIntervalGood}
|
||||
defaultValue={defaults.graduatingIntervalGood}
|
||||
markdownTooltip={tr.deckConfigGraduatingIntervalTooltip()}
|
||||
>
|
||||
{tr.schedulingGraduatingInterval()}
|
||||
<SettingTitle
|
||||
on:click={() =>
|
||||
openHelpModal(
|
||||
Object.keys(settings).indexOf("graduatingInterval"),
|
||||
)}>{settings.graduatingInterval.title}</SettingTitle
|
||||
>
|
||||
</SpinBoxRow>
|
||||
</Item>
|
||||
|
||||
@ -79,9 +134,12 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
<SpinBoxRow
|
||||
bind:value={$config.graduatingIntervalEasy}
|
||||
defaultValue={defaults.graduatingIntervalEasy}
|
||||
markdownTooltip={tr.deckConfigEasyIntervalTooltip()}
|
||||
>
|
||||
{tr.schedulingEasyInterval()}
|
||||
<SettingTitle
|
||||
on:click={() =>
|
||||
openHelpModal(Object.keys(settings).indexOf("easyInterval"))}
|
||||
>{settings.easyInterval.title}</SettingTitle
|
||||
>
|
||||
</SpinBoxRow>
|
||||
</Item>
|
||||
|
||||
@ -95,9 +153,12 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
defaultValue={defaults.newCardInsertOrder}
|
||||
choices={newInsertOrderChoices}
|
||||
breakpoint={"md"}
|
||||
markdownTooltip={tr.deckConfigNewInsertionOrderTooltip()}
|
||||
>
|
||||
{tr.deckConfigNewInsertionOrder()}
|
||||
<SettingTitle
|
||||
on:click={() =>
|
||||
openHelpModal(Object.keys(settings).indexOf("insertionOrder"))}
|
||||
>{settings.insertionOrder.title}</SettingTitle
|
||||
>
|
||||
</EnumSelectorRow>
|
||||
</Item>
|
||||
|
||||
|
@ -53,6 +53,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
>
|
||||
<div class:hide={!modified} use:asReference>
|
||||
<Badge
|
||||
iconSize={85}
|
||||
class="p-1"
|
||||
on:click={() => {
|
||||
if (modified) {
|
||||
|
17
ts/deck-options/SettingTitle.svelte
Normal file
17
ts/deck-options/SettingTitle.svelte
Normal file
@ -0,0 +1,17 @@
|
||||
<!--
|
||||
Copyright: Ankitects Pty Ltd and contributors
|
||||
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
-->
|
||||
<div class="setting-title" on:click>
|
||||
<slot />
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.setting-title {
|
||||
cursor: help;
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
text-decoration-style: dashed;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -6,22 +6,23 @@
|
||||
import Col from "../components/Col.svelte";
|
||||
import Row from "../components/Row.svelte";
|
||||
import SpinBox from "../components/SpinBox.svelte";
|
||||
import ConfigInput from "./ConfigInput.svelte";
|
||||
import RevertButton from "./RevertButton.svelte";
|
||||
import TooltipLabel from "./TooltipLabel.svelte";
|
||||
|
||||
export let value: any;
|
||||
export let defaultValue: any;
|
||||
export let min = 0;
|
||||
export let max: number | undefined = undefined;
|
||||
export let markdownTooltip: string;
|
||||
</script>
|
||||
|
||||
<Row --cols={12}>
|
||||
<Col --col-size={7} breakpoint="sm">
|
||||
<TooltipLabel {markdownTooltip}><slot /></TooltipLabel>
|
||||
<Row --cols={13}>
|
||||
<Col --col-size={7} breakpoint="xs">
|
||||
<slot />
|
||||
</Col>
|
||||
<Col --col-size={5} breakpoint="sm">
|
||||
<SpinBox bind:value {min} {max} step={0.01} />
|
||||
<RevertButton bind:value {defaultValue} />
|
||||
<Col --col-size={6} breakpoint="xs">
|
||||
<ConfigInput>
|
||||
<SpinBox bind:value {min} {max} step={0.01} />
|
||||
<RevertButton slot="revert" bind:value {defaultValue} />
|
||||
</ConfigInput>
|
||||
</Col>
|
||||
</Row>
|
||||
|
@ -6,22 +6,26 @@
|
||||
import Col from "../components/Col.svelte";
|
||||
import Row from "../components/Row.svelte";
|
||||
import SpinBox from "../components/SpinBox.svelte";
|
||||
import ConfigInput from "./ConfigInput.svelte";
|
||||
import RevertButton from "./RevertButton.svelte";
|
||||
import TooltipLabel from "./TooltipLabel.svelte";
|
||||
|
||||
export let value: any;
|
||||
export let defaultValue: any;
|
||||
export let min = 0;
|
||||
export let max: number | undefined = undefined;
|
||||
export let markdownTooltip: string;
|
||||
</script>
|
||||
|
||||
<Row --cols={12}>
|
||||
<Col --col-size={7} breakpoint="sm">
|
||||
<TooltipLabel {markdownTooltip}><slot /></TooltipLabel>
|
||||
<Row --cols={13}>
|
||||
<Col --col-size={7} breakpoint="xs">
|
||||
<slot />
|
||||
</Col>
|
||||
<Col --col-size={5} breakpoint="sm">
|
||||
<SpinBox bind:value {min} {max} />
|
||||
<RevertButton bind:value {defaultValue} />
|
||||
<Col --col-size={6} breakpoint="xs">
|
||||
<Row class="flex-grow-1">
|
||||
<slot name="tabs" />
|
||||
<ConfigInput>
|
||||
<SpinBox bind:value {min} {max} />
|
||||
<RevertButton slot="revert" bind:value {defaultValue} />
|
||||
</ConfigInput>
|
||||
</Row>
|
||||
</Col>
|
||||
</Row>
|
||||
|
@ -5,21 +5,22 @@
|
||||
<script lang="ts">
|
||||
import Col from "../components/Col.svelte";
|
||||
import Row from "../components/Row.svelte";
|
||||
import ConfigInput from "./ConfigInput.svelte";
|
||||
import RevertButton from "./RevertButton.svelte";
|
||||
import StepsInput from "./StepsInput.svelte";
|
||||
import TooltipLabel from "./TooltipLabel.svelte";
|
||||
|
||||
export let value: any;
|
||||
export let defaultValue: any;
|
||||
export let markdownTooltip: string;
|
||||
</script>
|
||||
|
||||
<Row --cols={12}>
|
||||
<Col --col-size={7} breakpoint="sm">
|
||||
<TooltipLabel {markdownTooltip}><slot /></TooltipLabel>
|
||||
<Row --cols={13}>
|
||||
<Col --col-size={7} breakpoint="xs">
|
||||
<slot />
|
||||
</Col>
|
||||
<Col --col-size={5} breakpoint="sm">
|
||||
<StepsInput bind:value />
|
||||
<RevertButton bind:value {defaultValue} />
|
||||
<Col --col-size={6} breakpoint="xs">
|
||||
<ConfigInput>
|
||||
<StepsInput bind:value />
|
||||
<RevertButton slot="revert" bind:value {defaultValue} />
|
||||
</ConfigInput>
|
||||
</Col>
|
||||
</Row>
|
||||
|
@ -6,25 +6,22 @@
|
||||
import Col from "../components/Col.svelte";
|
||||
import Row from "../components/Row.svelte";
|
||||
import Switch from "../components/Switch.svelte";
|
||||
import ConfigInput from "./ConfigInput.svelte";
|
||||
import Label from "./Label.svelte";
|
||||
import RevertButton from "./RevertButton.svelte";
|
||||
import TooltipLabel from "./TooltipLabel.svelte";
|
||||
|
||||
export let value: boolean;
|
||||
export let defaultValue: boolean;
|
||||
export let markdownTooltip: string | undefined = undefined;
|
||||
|
||||
const id = Math.random().toString(36).substring(2);
|
||||
</script>
|
||||
|
||||
<Row --cols={6}>
|
||||
<Col --col-size={4}
|
||||
>{#if markdownTooltip}<TooltipLabel for={id} {markdownTooltip}
|
||||
><slot /></TooltipLabel
|
||||
>{:else}<Label for={id}><slot /></Label>{/if}</Col
|
||||
>
|
||||
<Col --col-size={4}><Label for={id}><slot /></Label></Col>
|
||||
<Col --col-justify="flex-end">
|
||||
<Switch {id} bind:value />
|
||||
<RevertButton bind:value {defaultValue} />
|
||||
<ConfigInput grow={false}>
|
||||
<Switch {id} bind:value />
|
||||
<RevertButton slot="revert" bind:value {defaultValue} />
|
||||
</ConfigInput>
|
||||
</Col>
|
||||
</Row>
|
||||
|
@ -44,7 +44,7 @@
|
||||
|
||||
<ul>
|
||||
{#each tabs as tab, idx}
|
||||
<li class={activeTab === idx ? "active" : ""}>
|
||||
<li class:active={activeTab === idx}>
|
||||
<span on:click={handleClick(idx)}>{tab.title}</span>
|
||||
</li>
|
||||
{/each}
|
||||
@ -52,31 +52,27 @@
|
||||
|
||||
<style lang="scss">
|
||||
ul {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: space-between;
|
||||
padding-left: 0;
|
||||
margin-top: 1rem;
|
||||
margin-bottom: 0.5rem;
|
||||
margin-bottom: 0.25rem;
|
||||
list-style: none;
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
|
||||
span {
|
||||
border: 1px solid transparent;
|
||||
border-top-left-radius: 0.25rem;
|
||||
border-top-right-radius: 0.25rem;
|
||||
display: block;
|
||||
padding: 0.25rem 1rem;
|
||||
white-space: nowrap;
|
||||
cursor: pointer;
|
||||
margin: 0 8px -1px 0;
|
||||
color: var(--fg-subtle);
|
||||
}
|
||||
|
||||
li.active > span {
|
||||
border-color: var(--border) var(--border) var(--canvas);
|
||||
color: var(--fg);
|
||||
border-bottom: 4px solid var(--border-focus);
|
||||
margin-bottom: -2px;
|
||||
}
|
||||
|
||||
span:hover {
|
||||
color: var(--fg);
|
||||
}
|
||||
|
@ -3,13 +3,19 @@ Copyright: Ankitects Pty Ltd and contributors
|
||||
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
-->
|
||||
<script lang="ts">
|
||||
import type Carousel from "bootstrap/js/dist/carousel";
|
||||
import type Modal from "bootstrap/js/dist/modal";
|
||||
|
||||
import DynamicallySlottable from "../components/DynamicallySlottable.svelte";
|
||||
import Item from "../components/Item.svelte";
|
||||
import * as tr from "../lib/ftl";
|
||||
import HelpModal from "./HelpModal.svelte";
|
||||
import type { DeckOptionsState } from "./lib";
|
||||
import SettingTitle from "./SettingTitle.svelte";
|
||||
import SpinBoxRow from "./SpinBoxRow.svelte";
|
||||
import SwitchRow from "./SwitchRow.svelte";
|
||||
import TitledContainer from "./TitledContainer.svelte";
|
||||
import type { DeckOption } from "./types";
|
||||
import Warning from "./Warning.svelte";
|
||||
|
||||
export let state: DeckOptionsState;
|
||||
@ -22,9 +28,39 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
$config.capAnswerTimeToSecs > 600
|
||||
? tr.deckConfigMaximumAnswerSecsAboveRecommended()
|
||||
: "";
|
||||
|
||||
const settings = {
|
||||
maximumAnswerSecs: {
|
||||
title: tr.deckConfigMaximumAnswerSecs(),
|
||||
help: tr.deckConfigMaximumAnswerSecsTooltip(),
|
||||
},
|
||||
showAnswerTimer: {
|
||||
title: tr.schedulingShowAnswerTimer(),
|
||||
help: tr.deckConfigShowAnswerTimerTooltip(),
|
||||
},
|
||||
};
|
||||
const helpSections = Object.values(settings) as DeckOption[];
|
||||
|
||||
let modal: Modal;
|
||||
let carousel: Carousel;
|
||||
|
||||
function openHelpModal(index: number): void {
|
||||
modal.show();
|
||||
carousel.to(index);
|
||||
}
|
||||
</script>
|
||||
|
||||
<TitledContainer title={tr.deckConfigTimerTitle()}>
|
||||
<HelpModal
|
||||
title={tr.deckConfigTimerTitle()}
|
||||
url="https://docs.ankiweb.net/deck-options.html#timer"
|
||||
slot="tooltip"
|
||||
{helpSections}
|
||||
on:mount={(e) => {
|
||||
modal = e.detail.modal;
|
||||
carousel = e.detail.carousel;
|
||||
}}
|
||||
/>
|
||||
<DynamicallySlottable slotHost={Item} {api}>
|
||||
<Item>
|
||||
<SpinBoxRow
|
||||
@ -32,9 +68,13 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
defaultValue={defaults.capAnswerTimeToSecs}
|
||||
min={1}
|
||||
max={7200}
|
||||
markdownTooltip={tr.deckConfigMaximumAnswerSecsTooltip()}
|
||||
>
|
||||
{tr.deckConfigMaximumAnswerSecs()}
|
||||
<SettingTitle
|
||||
on:click={() =>
|
||||
openHelpModal(
|
||||
Object.keys(settings).indexOf("maximumAnswerSecs"),
|
||||
)}>{settings.maximumAnswerSecs.title}</SettingTitle
|
||||
>
|
||||
</SpinBoxRow>
|
||||
</Item>
|
||||
|
||||
@ -48,9 +88,13 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
<SwitchRow
|
||||
bind:value={$config.showTimer}
|
||||
defaultValue={defaults.showTimer}
|
||||
markdownTooltip={tr.deckConfigShowAnswerTimerTooltip()}
|
||||
>
|
||||
{tr.schedulingShowAnswerTimer()}
|
||||
<SettingTitle
|
||||
on:click={() =>
|
||||
openHelpModal(
|
||||
Object.keys(settings).indexOf("showAnswerTimer"),
|
||||
)}>{settings.showAnswerTimer.title}</SettingTitle
|
||||
>
|
||||
</SwitchRow>
|
||||
</div>
|
||||
</Item>
|
||||
|
@ -3,19 +3,56 @@ Copyright: Ankitects Pty Ltd and contributors
|
||||
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
-->
|
||||
<script lang="ts">
|
||||
import Container from "../components/Container.svelte";
|
||||
import { pageTheme } from "../sveltelib/theme";
|
||||
|
||||
export let title: string;
|
||||
</script>
|
||||
|
||||
<Container --gutter-block="2px" --container-margin="0">
|
||||
<h1>{title}</h1>
|
||||
|
||||
<div
|
||||
class="container"
|
||||
class:light={!$pageTheme.isDark}
|
||||
class:dark={$pageTheme.isDark}
|
||||
style:--gutter-block="2px"
|
||||
style:--container-margin="0"
|
||||
>
|
||||
<div class="position-relative">
|
||||
<h1>{title}</h1>
|
||||
<div class="help-badge position-absolute"><slot name="tooltip" /></div>
|
||||
</div>
|
||||
<slot />
|
||||
</Container>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
@use "sass/elevation" as *;
|
||||
.container {
|
||||
width: 100%;
|
||||
border-radius: var(--border-radius-large, 10px);
|
||||
padding: 1rem 1.75rem 0.75rem 1.25rem;
|
||||
border: var(--border-subtle);
|
||||
&:hover,
|
||||
&:focus-within {
|
||||
.help-badge {
|
||||
color: var(--fg-subtle);
|
||||
}
|
||||
}
|
||||
&.light {
|
||||
@include elevation(2);
|
||||
}
|
||||
&.dark {
|
||||
@include elevation(3);
|
||||
}
|
||||
}
|
||||
h1 {
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
.help-badge {
|
||||
right: 0;
|
||||
bottom: 4px;
|
||||
color: var(--fg-faint);
|
||||
transition: color 0.2s linear;
|
||||
&:hover {
|
||||
transition: none;
|
||||
color: var(--fg);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -1,39 +0,0 @@
|
||||
<!--
|
||||
Copyright: Ankitects Pty Ltd and contributors
|
||||
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { marked } from "marked";
|
||||
|
||||
import Badge from "../components/Badge.svelte";
|
||||
import WithTooltip from "../components/WithTooltip.svelte";
|
||||
import { infoCircle } from "./icons";
|
||||
import Label from "./Label.svelte";
|
||||
|
||||
export let markdownTooltip: string;
|
||||
let forId: string | undefined = undefined;
|
||||
export { forId as for };
|
||||
</script>
|
||||
|
||||
<span>
|
||||
{#if forId}
|
||||
<Label for={forId}><slot /></Label>
|
||||
{:else}
|
||||
<slot />
|
||||
{/if}
|
||||
<WithTooltip
|
||||
tooltip={marked(markdownTooltip)}
|
||||
showDelay={250}
|
||||
offset={[0, 20]}
|
||||
placement="bottom"
|
||||
let:createTooltip
|
||||
>
|
||||
<Badge
|
||||
class="opacity-50"
|
||||
iconSize={85}
|
||||
on:mount={(event) => createTooltip(event.detail.span)}
|
||||
>
|
||||
{@html infoCircle}
|
||||
</Badge>
|
||||
</WithTooltip>
|
||||
</span>
|
@ -1,10 +1,14 @@
|
||||
@import "sass/base";
|
||||
|
||||
// override Bootstrap transition duration
|
||||
$carousel-transition: 0.2s;
|
||||
|
||||
@import "sass/bootstrap/scss/dropdown";
|
||||
@import "sass/bootstrap/scss/buttons";
|
||||
@import "sass/bootstrap/scss/button-group";
|
||||
@import "sass/bootstrap/scss/transitions";
|
||||
@import "sass/bootstrap/scss/modal";
|
||||
@import "sass/bootstrap/scss/carousel";
|
||||
@import "sass/bootstrap/scss/close";
|
||||
@import "sass/bootstrap/scss/alert";
|
||||
@import "sass/bootstrap/scss/badge";
|
||||
|
@ -17,6 +17,7 @@ import { DeckOptionsState } from "./lib";
|
||||
|
||||
const i18n = setupI18n({
|
||||
modules: [
|
||||
ModuleName.HELP,
|
||||
ModuleName.SCHEDULING,
|
||||
ModuleName.ACTIONS,
|
||||
ModuleName.DECK_CONFIG,
|
||||
|
8
ts/deck-options/types.ts
Normal file
8
ts/deck-options/types.ts
Normal file
@ -0,0 +1,8 @@
|
||||
// Copyright: Ankitects Pty Ltd and contributors
|
||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
export type DeckOption = {
|
||||
title: string;
|
||||
help?: string;
|
||||
url?: string;
|
||||
};
|
Loading…
Reference in New Issue
Block a user