state för importsidan, snyggare dashboard och förbered global hotkeys
This commit is contained in:
parent
c03226a610
commit
7373f30ddc
@ -1,4 +1,6 @@
|
|||||||
<script>
|
<script>
|
||||||
|
import { goto } from '$app/navigation';
|
||||||
|
import { importState } from '$lib/stores.svelte';
|
||||||
import * as Accordion from '$lib/components/ui/accordion';
|
import * as Accordion from '$lib/components/ui/accordion';
|
||||||
import AccordionItem from '$lib/components/ui/accordion/accordion-item.svelte';
|
import AccordionItem from '$lib/components/ui/accordion/accordion-item.svelte';
|
||||||
import { Button } from '$lib/components/ui/button';
|
import { Button } from '$lib/components/ui/button';
|
||||||
@ -7,12 +9,25 @@
|
|||||||
import { Label } from '$lib/components/ui/label';
|
import { Label } from '$lib/components/ui/label';
|
||||||
import * as m from '$lib/paraglide/messages.js';
|
import * as m from '$lib/paraglide/messages.js';
|
||||||
|
|
||||||
|
import { Badge } from '$lib/components/ui/badge';
|
||||||
|
import { Separator } from '$lib/components/ui/separator';
|
||||||
import Import from './import/import.svelte';
|
import Import from './import/import.svelte';
|
||||||
export let open;
|
export let open = true;
|
||||||
|
|
||||||
export let data = {
|
export let data = {
|
||||||
form: {}
|
form: {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
import default_shortforms from '../db/shortforms.se.json';
|
||||||
|
const importDefaultList = () => {
|
||||||
|
importState.data = '';
|
||||||
|
importState.errors = [];
|
||||||
|
default_shortforms.shortforms.forEach((sf) => {
|
||||||
|
importState.data += sf.sf + '=' + sf.p + '\n';
|
||||||
|
});
|
||||||
|
console.log('goto import');
|
||||||
|
goto('/import');
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Dialog.Root bind:open closeOnOutsideClick={false}>
|
<Dialog.Root bind:open closeOnOutsideClick={false}>
|
||||||
@ -29,7 +44,28 @@
|
|||||||
<Accordion.Root class="w-full">
|
<Accordion.Root class="w-full">
|
||||||
<Accordion.Item value="import">
|
<Accordion.Item value="import">
|
||||||
<Accordion.Trigger>Importera förkortningar</Accordion.Trigger>
|
<Accordion.Trigger>Importera förkortningar</Accordion.Trigger>
|
||||||
<Accordion.Content><Import data={data.form} /></Accordion.Content>
|
<Accordion.Content>
|
||||||
|
<p class="leading-7 [&:not(:first-child)]:mt-6">
|
||||||
|
Skrivert kan bara importera och exportera förkortningslistor i läsbart textformat.<br />
|
||||||
|
Det finns ett verktyg för att konvertera listor och export-filer mellan olika format här:
|
||||||
|
<br />
|
||||||
|
<a href="https://qwertyist.se/tools/shortforms/" target="_blank"
|
||||||
|
><Badge variant="secondary">qwertyist.se/förkortingar/</Badge></a
|
||||||
|
>
|
||||||
|
</p>
|
||||||
|
<Separator class="my-4" />
|
||||||
|
<p class="leading-7 [&:not(:first-child)]:mt-6">
|
||||||
|
Vill du inte importera en egen lista så kan du använda programmets baslista som i den
|
||||||
|
här versionen av programmet har {default_shortforms.shortforms.length} förkortningar.<br
|
||||||
|
/>
|
||||||
|
<a href="/import" on:click={importDefaultList}
|
||||||
|
><Badge variant="secondary">Importera baslista</Badge></a
|
||||||
|
>
|
||||||
|
</p>
|
||||||
|
<p class="leading-7 [&:not(:first-child)]:mt-6">
|
||||||
|
<a href="/import"><Badge>Importera förkortningar</Badge></a>
|
||||||
|
</p>
|
||||||
|
</Accordion.Content>
|
||||||
</Accordion.Item>
|
</Accordion.Item>
|
||||||
<Accordion.Item value="settings">
|
<Accordion.Item value="settings">
|
||||||
<Accordion.Trigger>Ändra inställningar</Accordion.Trigger>
|
<Accordion.Trigger>Ändra inställningar</Accordion.Trigger>
|
||||||
@ -39,8 +75,12 @@
|
|||||||
<Accordion.Trigger>Ge feedback eller rapportera fel</Accordion.Trigger>
|
<Accordion.Trigger>Ge feedback eller rapportera fel</Accordion.Trigger>
|
||||||
<Accordion.Content>Här ger man feedback eller rapporterar fel</Accordion.Content>
|
<Accordion.Content>Här ger man feedback eller rapporterar fel</Accordion.Content>
|
||||||
</Accordion.Item>
|
</Accordion.Item>
|
||||||
|
<Accordion.Item value="connect">
|
||||||
|
<Accordion.Trigger>Koppla upp mot tolkanvändare</Accordion.Trigger>
|
||||||
|
<Accordion.Content></Accordion.Content>
|
||||||
|
</Accordion.Item>
|
||||||
<Accordion.Item value="interpret">
|
<Accordion.Item value="interpret">
|
||||||
<Accordion.Trigger>Börja skriva</Accordion.Trigger>
|
<Accordion.Trigger>Börja skrivtolka</Accordion.Trigger>
|
||||||
<Accordion.Content>Man för börja skriva på en gång om man vill.</Accordion.Content>
|
<Accordion.Content>Man för börja skriva på en gång om man vill.</Accordion.Content>
|
||||||
</Accordion.Item>
|
</Accordion.Item>
|
||||||
</Accordion.Root>
|
</Accordion.Root>
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import { goto } from '$app/navigation';
|
||||||
|
import { onMount } from 'svelte';
|
||||||
|
import { importState } from '$lib/stores.svelte';
|
||||||
|
import * as Card from '$lib/components/ui/card/index.js';
|
||||||
import { Input } from '$lib/components/ui/input';
|
import { Input } from '$lib/components/ui/input';
|
||||||
import * as Select from '$lib/components/ui/select';
|
import * as Select from '$lib/components/ui/select';
|
||||||
import { Label } from '$lib/components/ui/label';
|
import { Label } from '$lib/components/ui/label';
|
||||||
@ -17,7 +21,6 @@
|
|||||||
name: '',
|
name: '',
|
||||||
type: false
|
type: false
|
||||||
};
|
};
|
||||||
let errors = '...';
|
|
||||||
let importing = false;
|
let importing = false;
|
||||||
let progress = 0;
|
let progress = 0;
|
||||||
const handleImport = () => {
|
const handleImport = () => {
|
||||||
@ -31,27 +34,29 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
const cancelImport = () => {
|
||||||
|
importState.data = '';
|
||||||
|
importState.errors = [];
|
||||||
|
goto('/');
|
||||||
|
};
|
||||||
const importDefaultList = () => {
|
const importDefaultList = () => {
|
||||||
|
importState.data = '';
|
||||||
|
importState.errors = [];
|
||||||
default_shortforms.shortforms.forEach((sf) => {
|
default_shortforms.shortforms.forEach((sf) => {
|
||||||
form.textarea += sf.sf + '=' + sf.p + '\n';
|
importState.data += sf.sf + '=' + sf.p + '\n';
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
onMount(() => {
|
||||||
|
form.textarea = importState.data;
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<p class="leading-7 [&:not(:first-child)]:mt-6">
|
<Card.Root class="w-[490px]">
|
||||||
Skrivert kan bara importera och exportera förkortningslistor i läsbart textformat.<br />
|
<Card.Header>
|
||||||
Det finns ett verktyg för att konvertera listor och export-filer mellan olika format här: <br />
|
<Card.Title>Importera förkortningar</Card.Title>
|
||||||
<a href="https://qwertyist.se/tools/shortforms/" target="_blank"
|
<Card.Description>Nån annan hjälptext.</Card.Description>
|
||||||
><Badge>qwertyist.se/förkortingar/</Badge></a
|
</Card.Header>
|
||||||
>
|
<Card.Content>
|
||||||
</p>
|
|
||||||
<Separator class="my-4" />
|
|
||||||
<p class="leading-7 [&:not(:first-child)]:mt-6">
|
|
||||||
Vill du inte importera en egen lista så kan du använda programmets baslista som i den här
|
|
||||||
versionen av programmet har {default_shortforms.shortforms.length} förkortningar.<br />
|
|
||||||
<a href="#" on:click={importDefaultList}><Badge>Importera baslista</Badge></a>
|
|
||||||
</p>
|
|
||||||
<Separator class="my-4" />
|
|
||||||
<form class="grid gap-4 py-4" method="post" enctype="multipart/form-data">
|
<form class="grid gap-4 py-4" method="post" enctype="multipart/form-data">
|
||||||
<div class="grid grid-cols-4 items-center gap-4">
|
<div class="grid grid-cols-4 items-center gap-4">
|
||||||
<Label>Förkortningar</Label>
|
<Label>Förkortningar</Label>
|
||||||
@ -74,8 +79,11 @@ förkn=förkortningen
|
|||||||
<Label>Prioritera lista</Label>
|
<Label>Prioritera lista</Label>
|
||||||
<Switch bind:checked={form.type} />
|
<Switch bind:checked={form.type} />
|
||||||
</div>
|
</div>
|
||||||
<p class="leading-7 [&:not(:first-child)]:mt-2">{errors}</p>
|
<p class="leading-7 [&:not(:first-child)]:mt-2">{importState.errors}</p>
|
||||||
<Button on:click={handleImport}>Importera</Button>
|
|
||||||
</form>
|
</form>
|
||||||
|
</Card.Content>
|
||||||
{#if importing}<Progress value={progress} />{/if}
|
<Card.Footer class="flex justify-between">
|
||||||
|
<Button on:click={cancelImport} variant="outline">Avbryt</Button>
|
||||||
|
<Button on:click={handleImport}>Importera</Button>
|
||||||
|
</Card.Footer>
|
||||||
|
</Card.Root>
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import { shortforms } from '$lib/stores.svelte';
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
import { browser } from '$app/environment';
|
import { browser } from '$app/environment';
|
||||||
|
|
||||||
@ -8,8 +9,6 @@
|
|||||||
import type { Shortform } from '../db/main';
|
import type { Shortform } from '../db/main';
|
||||||
import AccordionTrigger from '$lib/components/ui/accordion/accordion-trigger.svelte';
|
import AccordionTrigger from '$lib/components/ui/accordion/accordion-trigger.svelte';
|
||||||
|
|
||||||
export let activeShortforms: Array<Shortform>;
|
|
||||||
let shortforms: Map<string, any>;
|
|
||||||
let state = {
|
let state = {
|
||||||
capitalizeNext: true,
|
capitalizeNext: true,
|
||||||
currentWord: ''
|
currentWord: ''
|
||||||
@ -19,7 +18,7 @@
|
|||||||
let text = '';
|
let text = '';
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
shortforms = cacheShortforms([890324]);
|
shortforms.cache = cacheShortforms([890324]);
|
||||||
if (browser) {
|
if (browser) {
|
||||||
let t = document.getElementById('doc') as HTMLTextAreaElement;
|
let t = document.getElementById('doc') as HTMLTextAreaElement;
|
||||||
if (t != null) {
|
if (t != null) {
|
||||||
@ -38,7 +37,7 @@
|
|||||||
if (defaultExpanders.has(expander)) {
|
if (defaultExpanders.has(expander)) {
|
||||||
const expanderRules = defaultExpanders.get(expander)!;
|
const expanderRules = defaultExpanders.get(expander)!;
|
||||||
const currentWord = getCurrentWord(textarea).trim();
|
const currentWord = getCurrentWord(textarea).trim();
|
||||||
const expandedPhrase = expandShortform(shortforms, currentWord);
|
const expandedPhrase = expandShortform(shortforms.cache, currentWord);
|
||||||
if (expanderRules.fullstop) {
|
if (expanderRules.fullstop) {
|
||||||
// console.log("should capitalize next");
|
// console.log("should capitalize next");
|
||||||
state.capitalizeNext = true;
|
state.capitalizeNext = true;
|
||||||
|
13
src/lib/components/ui/card/card-content.svelte
Normal file
13
src/lib/components/ui/card/card-content.svelte
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import type { HTMLAttributes } from "svelte/elements";
|
||||||
|
import { cn } from "$lib/utils.js";
|
||||||
|
|
||||||
|
type $$Props = HTMLAttributes<HTMLDivElement>;
|
||||||
|
|
||||||
|
let className: $$Props["class"] = undefined;
|
||||||
|
export { className as class };
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class={cn("p-6", className)} {...$$restProps}>
|
||||||
|
<slot />
|
||||||
|
</div>
|
13
src/lib/components/ui/card/card-description.svelte
Normal file
13
src/lib/components/ui/card/card-description.svelte
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import type { HTMLAttributes } from "svelte/elements";
|
||||||
|
import { cn } from "$lib/utils.js";
|
||||||
|
|
||||||
|
type $$Props = HTMLAttributes<HTMLParagraphElement>;
|
||||||
|
|
||||||
|
let className: $$Props["class"] = undefined;
|
||||||
|
export { className as class };
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<p class={cn("text-muted-foreground text-sm", className)} {...$$restProps}>
|
||||||
|
<slot />
|
||||||
|
</p>
|
13
src/lib/components/ui/card/card-footer.svelte
Normal file
13
src/lib/components/ui/card/card-footer.svelte
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import type { HTMLAttributes } from "svelte/elements";
|
||||||
|
import { cn } from "$lib/utils.js";
|
||||||
|
|
||||||
|
type $$Props = HTMLAttributes<HTMLDivElement>;
|
||||||
|
|
||||||
|
let className: $$Props["class"] = undefined;
|
||||||
|
export { className as class };
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class={cn("flex items-center p-6 pt-0", className)} {...$$restProps}>
|
||||||
|
<slot />
|
||||||
|
</div>
|
13
src/lib/components/ui/card/card-header.svelte
Normal file
13
src/lib/components/ui/card/card-header.svelte
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import type { HTMLAttributes } from "svelte/elements";
|
||||||
|
import { cn } from "$lib/utils.js";
|
||||||
|
|
||||||
|
type $$Props = HTMLAttributes<HTMLDivElement>;
|
||||||
|
|
||||||
|
let className: $$Props["class"] = undefined;
|
||||||
|
export { className as class };
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class={cn("flex flex-col space-y-1.5 p-6 pb-0", className)} {...$$restProps}>
|
||||||
|
<slot />
|
||||||
|
</div>
|
21
src/lib/components/ui/card/card-title.svelte
Normal file
21
src/lib/components/ui/card/card-title.svelte
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import type { HTMLAttributes } from "svelte/elements";
|
||||||
|
import type { HeadingLevel } from "./index.js";
|
||||||
|
import { cn } from "$lib/utils.js";
|
||||||
|
|
||||||
|
type $$Props = HTMLAttributes<HTMLHeadingElement> & {
|
||||||
|
tag?: HeadingLevel;
|
||||||
|
};
|
||||||
|
|
||||||
|
let className: $$Props["class"] = undefined;
|
||||||
|
export let tag: $$Props["tag"] = "h3";
|
||||||
|
export { className as class };
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<svelte:element
|
||||||
|
this={tag}
|
||||||
|
class={cn("font-semibold leading-none tracking-tight", className)}
|
||||||
|
{...$$restProps}
|
||||||
|
>
|
||||||
|
<slot />
|
||||||
|
</svelte:element>
|
22
src/lib/components/ui/card/card.svelte
Normal file
22
src/lib/components/ui/card/card.svelte
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import type { HTMLAttributes } from "svelte/elements";
|
||||||
|
import { cn } from "$lib/utils.js";
|
||||||
|
|
||||||
|
type $$Props = HTMLAttributes<HTMLDivElement>;
|
||||||
|
|
||||||
|
let className: $$Props["class"] = undefined;
|
||||||
|
export { className as class };
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||||
|
<div
|
||||||
|
class={cn("bg-card text-card-foreground rounded-xl border shadow", className)}
|
||||||
|
{...$$restProps}
|
||||||
|
on:click
|
||||||
|
on:focusin
|
||||||
|
on:focusout
|
||||||
|
on:mouseenter
|
||||||
|
on:mouseleave
|
||||||
|
>
|
||||||
|
<slot />
|
||||||
|
</div>
|
24
src/lib/components/ui/card/index.ts
Normal file
24
src/lib/components/ui/card/index.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import Root from "./card.svelte";
|
||||||
|
import Content from "./card-content.svelte";
|
||||||
|
import Description from "./card-description.svelte";
|
||||||
|
import Footer from "./card-footer.svelte";
|
||||||
|
import Header from "./card-header.svelte";
|
||||||
|
import Title from "./card-title.svelte";
|
||||||
|
|
||||||
|
export {
|
||||||
|
Root,
|
||||||
|
Content,
|
||||||
|
Description,
|
||||||
|
Footer,
|
||||||
|
Header,
|
||||||
|
Title,
|
||||||
|
//
|
||||||
|
Root as Card,
|
||||||
|
Content as CardContent,
|
||||||
|
Description as CardDescription,
|
||||||
|
Footer as CardFooter,
|
||||||
|
Header as CardHeader,
|
||||||
|
Title as CardTitle,
|
||||||
|
};
|
||||||
|
|
||||||
|
export type HeadingLevel = "h1" | "h2" | "h3" | "h4" | "h5" | "h6";
|
2
src/lib/stores.svelte.ts
Normal file
2
src/lib/stores.svelte.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export const shortforms = $state({ standardList: "", subjectLists: [], cache: new Map() })
|
||||||
|
export const importState = $state({ data: "", errors: [] })
|
@ -1,6 +1,8 @@
|
|||||||
|
import { goto } from '$app/navigation';
|
||||||
import type { ExpanderType } from "./index.d.ts";
|
import type { ExpanderType } from "./index.d.ts";
|
||||||
|
|
||||||
export const defaultExpanders: Map<string, ExpanderType> = new Map();
|
export const defaultExpanders: Map<string, ExpanderType> = new Map();
|
||||||
|
export const hotkeys: Map<string, any> = new Map();
|
||||||
|
|
||||||
defaultExpanders.set(" ", {
|
defaultExpanders.set(" ", {
|
||||||
key: { keyCode: 190, shiftKey: false },
|
key: { keyCode: 190, shiftKey: false },
|
||||||
@ -72,3 +74,18 @@ defaultExpanders.set(";", {
|
|||||||
symbol: ":",
|
symbol: ":",
|
||||||
fullstop: false,
|
fullstop: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
hotkeys.set("F1", {
|
||||||
|
action: (e) => {
|
||||||
|
e.preventDefault()
|
||||||
|
console.log("Open help page")
|
||||||
|
|
||||||
|
}
|
||||||
|
})
|
||||||
|
hotkeys.set("F12", {
|
||||||
|
action: (e) => {
|
||||||
|
e.preventDefault()
|
||||||
|
console.log("Open import page")
|
||||||
|
goto("/import")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { db } from "../db/main"
|
import { db } from "../db/main"
|
||||||
import { type Shortform } from "../db/main"
|
import { type Shortform } from "../db/main"
|
||||||
export function cacheShortforms(lists: Array<string> = []) {
|
export function cacheShortforms(lists: Array<number> = []) {
|
||||||
let shortforms = new Map();
|
let shortforms = new Map();
|
||||||
// console.log("Caching shortforms with lists:", lists);
|
// console.log("Caching shortforms with lists:", lists);
|
||||||
|
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
let { children } = $props();
|
let { children } = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<div role="presentation">
|
||||||
<ParaglideJS {i18n}>
|
<ParaglideJS {i18n}>
|
||||||
{@render children()}
|
{@render children()}
|
||||||
</ParaglideJS>
|
</ParaglideJS>
|
||||||
|
</div>
|
||||||
|
@ -6,7 +6,9 @@
|
|||||||
|
|
||||||
import { Button } from '$lib/components/ui/button';
|
import { Button } from '$lib/components/ui/button';
|
||||||
|
|
||||||
|
import { hotkeys } from '../modules/keyboard';
|
||||||
let cache: Array<Shortform>;
|
let cache: Array<Shortform>;
|
||||||
|
let showDashboard: boolean = true;
|
||||||
db.shortforms
|
db.shortforms
|
||||||
.toArray()
|
.toArray()
|
||||||
.then((shortforms) => {
|
.then((shortforms) => {
|
||||||
@ -20,11 +22,16 @@
|
|||||||
deleteShortformList(890324);
|
deleteShortformList(890324);
|
||||||
cache = [];
|
cache = [];
|
||||||
};
|
};
|
||||||
|
const handleHotkeys = (e: KeyboardEvent) => {
|
||||||
|
hotkeys.get(e.key)?.action(e);
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<svelte:window on:keydown={handleHotkeys} />
|
||||||
|
|
||||||
<div class="h-full w-full" role="application">
|
<div class="h-full w-full" role="application">
|
||||||
<Textarea activeShortforms={cache} />
|
<Textarea />
|
||||||
<Dashboard open="true" />
|
<Dashboard open={showDashboard} />
|
||||||
|
|
||||||
<!-- <Button variant="destructive" on:click={deleteDefaultShortforms}>Ta bort standardlista</Button>-->
|
<!-- <Button variant="destructive" on:click={deleteDefaultShortforms}>Ta bort standardlista</Button>-->
|
||||||
</div>
|
</div>
|
||||||
|
7
src/routes/import/+page.svelte
Normal file
7
src/routes/import/+page.svelte
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<script>
|
||||||
|
import Import from '../../components/import/import.svelte';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="flex items-center justify-center p-24">
|
||||||
|
<Import />
|
||||||
|
</div>
|
Loading…
x
Reference in New Issue
Block a user