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>
|
||||
import { goto } from '$app/navigation';
|
||||
import { importState } from '$lib/stores.svelte';
|
||||
import * as Accordion from '$lib/components/ui/accordion';
|
||||
import AccordionItem from '$lib/components/ui/accordion/accordion-item.svelte';
|
||||
import { Button } from '$lib/components/ui/button';
|
||||
@ -7,12 +9,25 @@
|
||||
import { Label } from '$lib/components/ui/label';
|
||||
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';
|
||||
export let open;
|
||||
export let open = true;
|
||||
|
||||
export let data = {
|
||||
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>
|
||||
|
||||
<Dialog.Root bind:open closeOnOutsideClick={false}>
|
||||
@ -29,7 +44,28 @@
|
||||
<Accordion.Root class="w-full">
|
||||
<Accordion.Item value="import">
|
||||
<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 value="settings">
|
||||
<Accordion.Trigger>Ändra inställningar</Accordion.Trigger>
|
||||
@ -39,8 +75,12 @@
|
||||
<Accordion.Trigger>Ge feedback eller rapportera fel</Accordion.Trigger>
|
||||
<Accordion.Content>Här ger man feedback eller rapporterar fel</Accordion.Content>
|
||||
</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.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.Item>
|
||||
</Accordion.Root>
|
||||
|
@ -1,4 +1,8 @@
|
||||
<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 * as Select from '$lib/components/ui/select';
|
||||
import { Label } from '$lib/components/ui/label';
|
||||
@ -17,7 +21,6 @@
|
||||
name: '',
|
||||
type: false
|
||||
};
|
||||
let errors = '...';
|
||||
let importing = false;
|
||||
let progress = 0;
|
||||
const handleImport = () => {
|
||||
@ -31,51 +34,56 @@
|
||||
}
|
||||
});
|
||||
};
|
||||
const cancelImport = () => {
|
||||
importState.data = '';
|
||||
importState.errors = [];
|
||||
goto('/');
|
||||
};
|
||||
const importDefaultList = () => {
|
||||
importState.data = '';
|
||||
importState.errors = [];
|
||||
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>
|
||||
|
||||
<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>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="#" 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">
|
||||
<div class="grid grid-cols-4 items-center gap-4">
|
||||
<Label>Förkortningar</Label>
|
||||
<textarea
|
||||
class="block w-[290px] rounded-lg border border-gray-200 bg-gray-50 p-2.5 text-sm text-gray-900 focus:border-blue-500 focus:ring-blue-500 dark:border-gray-600 dark:bg-gray-700 dark:text-white dark:placeholder-gray-400 dark:focus:border-blue-500 dark:focus:ring-blue-500"
|
||||
bind:value={form.textarea}
|
||||
placeholder="Skriv/klistra in dina förkortingar i formatet
|
||||
<Card.Root class="w-[490px]">
|
||||
<Card.Header>
|
||||
<Card.Title>Importera förkortningar</Card.Title>
|
||||
<Card.Description>Nån annan hjälptext.</Card.Description>
|
||||
</Card.Header>
|
||||
<Card.Content>
|
||||
<form class="grid gap-4 py-4" method="post" enctype="multipart/form-data">
|
||||
<div class="grid grid-cols-4 items-center gap-4">
|
||||
<Label>Förkortningar</Label>
|
||||
<textarea
|
||||
class="block w-[290px] rounded-lg border border-gray-200 bg-gray-50 p-2.5 text-sm text-gray-900 focus:border-blue-500 focus:ring-blue-500 dark:border-gray-600 dark:bg-gray-700 dark:text-white dark:placeholder-gray-400 dark:focus:border-blue-500 dark:focus:ring-blue-500"
|
||||
bind:value={form.textarea}
|
||||
placeholder="Skriv/klistra in dina förkortingar i formatet
|
||||
förk=förkortning
|
||||
förkr=förkortningar
|
||||
förkn=förkortningen
|
||||
..."
|
||||
rows="5"
|
||||
></textarea>
|
||||
</div>
|
||||
<div class="grid grid-cols-4 items-center gap-4">
|
||||
<Label>Namn</Label>
|
||||
<Input bind:value={form.name} placeholder="Döp förkortningslistan" class="w-[290px]" />
|
||||
</div>
|
||||
<div class="grid grid-cols-4 items-center gap-4">
|
||||
<Label>Prioritera lista</Label>
|
||||
<Switch bind:checked={form.type} />
|
||||
</div>
|
||||
<p class="leading-7 [&:not(:first-child)]:mt-2">{errors}</p>
|
||||
<Button on:click={handleImport}>Importera</Button>
|
||||
</form>
|
||||
|
||||
{#if importing}<Progress value={progress} />{/if}
|
||||
rows="5"
|
||||
></textarea>
|
||||
</div>
|
||||
<div class="grid grid-cols-4 items-center gap-4">
|
||||
<Label>Namn</Label>
|
||||
<Input bind:value={form.name} placeholder="Döp förkortningslistan" class="w-[290px]" />
|
||||
</div>
|
||||
<div class="grid grid-cols-4 items-center gap-4">
|
||||
<Label>Prioritera lista</Label>
|
||||
<Switch bind:checked={form.type} />
|
||||
</div>
|
||||
<p class="leading-7 [&:not(:first-child)]:mt-2">{importState.errors}</p>
|
||||
</form>
|
||||
</Card.Content>
|
||||
<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">
|
||||
import { shortforms } from '$lib/stores.svelte';
|
||||
import { onMount } from 'svelte';
|
||||
import { browser } from '$app/environment';
|
||||
|
||||
@ -8,8 +9,6 @@
|
||||
import type { Shortform } from '../db/main';
|
||||
import AccordionTrigger from '$lib/components/ui/accordion/accordion-trigger.svelte';
|
||||
|
||||
export let activeShortforms: Array<Shortform>;
|
||||
let shortforms: Map<string, any>;
|
||||
let state = {
|
||||
capitalizeNext: true,
|
||||
currentWord: ''
|
||||
@ -19,7 +18,7 @@
|
||||
let text = '';
|
||||
|
||||
onMount(() => {
|
||||
shortforms = cacheShortforms([890324]);
|
||||
shortforms.cache = cacheShortforms([890324]);
|
||||
if (browser) {
|
||||
let t = document.getElementById('doc') as HTMLTextAreaElement;
|
||||
if (t != null) {
|
||||
@ -38,7 +37,7 @@
|
||||
if (defaultExpanders.has(expander)) {
|
||||
const expanderRules = defaultExpanders.get(expander)!;
|
||||
const currentWord = getCurrentWord(textarea).trim();
|
||||
const expandedPhrase = expandShortform(shortforms, currentWord);
|
||||
const expandedPhrase = expandShortform(shortforms.cache, currentWord);
|
||||
if (expanderRules.fullstop) {
|
||||
// console.log("should capitalize next");
|
||||
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";
|
||||
|
||||
export const defaultExpanders: Map<string, ExpanderType> = new Map();
|
||||
export const hotkeys: Map<string, any> = new Map();
|
||||
|
||||
defaultExpanders.set(" ", {
|
||||
key: { keyCode: 190, shiftKey: false },
|
||||
@ -72,3 +74,18 @@ defaultExpanders.set(";", {
|
||||
symbol: ":",
|
||||
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 { type Shortform } from "../db/main"
|
||||
export function cacheShortforms(lists: Array<string> = []) {
|
||||
export function cacheShortforms(lists: Array<number> = []) {
|
||||
let shortforms = new Map();
|
||||
// console.log("Caching shortforms with lists:", lists);
|
||||
|
||||
|
@ -5,6 +5,8 @@
|
||||
let { children } = $props();
|
||||
</script>
|
||||
|
||||
<ParaglideJS {i18n}>
|
||||
{@render children()}
|
||||
</ParaglideJS>
|
||||
<div role="presentation">
|
||||
<ParaglideJS {i18n}>
|
||||
{@render children()}
|
||||
</ParaglideJS>
|
||||
</div>
|
||||
|
@ -6,7 +6,9 @@
|
||||
|
||||
import { Button } from '$lib/components/ui/button';
|
||||
|
||||
import { hotkeys } from '../modules/keyboard';
|
||||
let cache: Array<Shortform>;
|
||||
let showDashboard: boolean = true;
|
||||
db.shortforms
|
||||
.toArray()
|
||||
.then((shortforms) => {
|
||||
@ -20,11 +22,16 @@
|
||||
deleteShortformList(890324);
|
||||
cache = [];
|
||||
};
|
||||
const handleHotkeys = (e: KeyboardEvent) => {
|
||||
hotkeys.get(e.key)?.action(e);
|
||||
};
|
||||
</script>
|
||||
|
||||
<svelte:window on:keydown={handleHotkeys} />
|
||||
|
||||
<div class="h-full w-full" role="application">
|
||||
<Textarea activeShortforms={cache} />
|
||||
<Dashboard open="true" />
|
||||
<Textarea />
|
||||
<Dashboard open={showDashboard} />
|
||||
|
||||
<!-- <Button variant="destructive" on:click={deleteDefaultShortforms}>Ta bort standardlista</Button>-->
|
||||
</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