Skip to content

Commit 8ebb8a4

Browse files
committed
Conform entry-list options dialog to editor-options
1 parent 1045a31 commit 8ebb8a4

8 files changed

Lines changed: 140 additions & 90 deletions

File tree

frontend/viewer/.storybook/decorators/FWLiteDecorator.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
import {ModeWatcher} from 'mode-watcher';
2222
import {Context} from 'runed';
2323
import { type Snippet } from 'svelte';
24-
import ViewPicker from '../../src/project/browse/ViewPicker.svelte';
24+
import ViewPicker from '../../src/project/browse/EditorViewOptions.svelte';
2525
import {InMemoryApiService} from '$lib/in-memory-api-service';
2626
import {setupServiceProvider} from '$lib/services/service-provider';
2727
import {setupDotnetServiceProvider} from '$lib/services/service-provider-dotnet';

frontend/viewer/src/lib/components/responsive-popup/responsive-popup.svelte

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,18 @@
88
99
type TriggerSnippet = PopoverTriggerProps['child'];
1010
11-
let { open = $bindable(false), children, title, trigger }: WithChildren<{ open?: boolean, title: string, trigger: TriggerSnippet }> = $props();
11+
let { open = $bindable(false), children, title, trigger }: WithChildren<{ open?: boolean, title?: string, trigger: TriggerSnippet }> = $props();
1212
</script>
1313

1414
{#if !IsMobile.value}
1515
<Popover.Root bind:open>
1616
<Popover.Trigger child={trigger} />
1717
<Popover.Content class="w-64 sm:mr-4">
1818
<div class="space-y-3">
19-
<h3 class="font-medium">{title}</h3>
19+
{#if title}
20+
<h3 class="font-medium">{title}</h3>
21+
{/if}
22+
2023
{#if children}
2124
{@render children()}
2225
{/if}
@@ -31,9 +34,11 @@
3134
<Icon icon="i-mdi-close" />
3235
</Drawer.Close>
3336
<div class="mx-auto w-full max-w-sm p-4">
34-
<Drawer.Header>
35-
<Drawer.Title>{title}</Drawer.Title>
36-
</Drawer.Header>
37+
{#if title}
38+
<Drawer.Header>
39+
<Drawer.Title>{title}</Drawer.Title>
40+
</Drawer.Header>
41+
{/if}
3742
{#if children}
3843
{@render children()}
3944
{/if}

frontend/viewer/src/lib/sandbox/EditorSandbox.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
import {type IMultiString} from '$lib/dotnet-types';
1212
import {type IRichString} from '$lib/dotnet-types/generated-types/MiniLcm/Models/IRichString';
1313
import { fieldData } from '$lib/entry-editor/field-data';
14-
import ViewPicker from '../../project/browse/ViewPicker.svelte';
14+
import ViewPicker from '../../project/browse/EditorViewOptions.svelte';
1515
import WsInput from '$lib/components/field-editors/ws-input.svelte';
1616
import {vt} from '$lib/views/view-text';
1717

frontend/viewer/src/project/browse/BrowseView.svelte

Lines changed: 4 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,19 @@
44
import EntryView from './EntryView.svelte';
55
import SearchFilter from './SearchFilter.svelte';
66
import EntriesList from './EntriesList.svelte';
7-
import { Icon } from '$lib/components/ui/icon';
87
import { t } from 'svelte-i18n-lingui';
98
import SidebarPrimaryAction from '../SidebarPrimaryAction.svelte';
109
import {useDialogsService} from '$lib/services/dialogs-service';
1110
import PrimaryNewEntryButton from '../PrimaryNewEntryButton.svelte';
12-
import ResponsivePopup from '$lib/components/responsive-popup/responsive-popup.svelte';
13-
import {Tabs, TabsList, TabsTrigger} from '$lib/components/ui/tabs';
14-
import {Button} from '$lib/components/ui/button';
1511
import {QueryParamState} from '$lib/utils/url.svelte';
1612
import {pt} from '$lib/views/view-text';
1713
import {useCurrentView} from '$lib/views/view-service';
1814
import IfOnce from '$lib/components/if-once/if-once.svelte';
1915
import {SortField} from '$lib/dotnet-types';
2016
import SortMenu, {type SortConfig} from './SortMenu.svelte';
2117
import {useProjectContext} from '$lib/project-context.svelte';
18+
import type {EntryListViewMode} from './EntryListViewOptions.svelte';
19+
import EntryListViewOptions from './EntryListViewOptions.svelte';
2220
2321
const projectContext = useProjectContext();
2422
const currentView = useCurrentView();
@@ -28,7 +26,7 @@
2826
let search = $state('');
2927
let gridifyFilter = $state<string>();
3028
let sort = $state<SortConfig>();
31-
let entryMode: 'preview' | 'simple' = $state('simple');
29+
let entryMode: EntryListViewMode = $state('simple');
3230
3331
async function newEntry() {
3432
const entry = await dialogsService.createNewEntry();
@@ -38,7 +36,6 @@
3836
3937
let leftPane: ResizablePane | undefined = $state();
4038
let rightPane: ResizablePane | undefined = $state();
41-
let listModeOpen = $state(false);
4239
</script>
4340
<SidebarPrimaryAction>
4441
{#snippet children(isOpen: boolean)}
@@ -62,25 +59,7 @@
6259
<div class="my-2 flex items-center justify-between">
6360
<SortMenu bind:value={sort}
6461
autoSelector={() => search ? SortField.SearchRelevance : SortField.Headword} />
65-
<ResponsivePopup bind:open={listModeOpen} title={$t`List mode`}>
66-
{#snippet trigger({props})}
67-
<Button {...props} size="xs-icon" variant="ghost" icon="i-mdi-format-list-text" />
68-
{/snippet}
69-
<div class="space-y-6">
70-
<Tabs bind:value={entryMode} class="mb-1 text-center">
71-
<TabsList onkeydown={(e) => {if (e.key === 'Enter') listModeOpen = false}}>
72-
<TabsTrigger value="simple" onclick={() => listModeOpen = false}>
73-
<Icon icon="i-mdi-format-list-bulleted-square" class="mr-1"/>
74-
{$t`Simple`}
75-
</TabsTrigger>
76-
<TabsTrigger value="preview" onclick={() => listModeOpen = false}>
77-
<Icon icon="i-mdi-format-list-text" class="mr-1"/>
78-
{$t`Preview`}
79-
</TabsTrigger>
80-
</TabsList>
81-
</Tabs>
82-
</div>
83-
</ResponsivePopup>
62+
<EntryListViewOptions bind:entryMode />
8463
</div>
8564
</div>
8665
<EntriesList {search}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<script lang="ts">
2+
import * as RadioGroup from '$lib/components/ui/radio-group';
3+
import { t } from 'svelte-i18n-lingui';
4+
import Switch from '$lib/components/ui/switch/switch.svelte';
5+
import ResponsivePopup from '$lib/components/responsive-popup/responsive-popup.svelte';
6+
import {Button} from '$lib/components/ui/button';
7+
import DevContent from '$lib/layout/DevContent.svelte';
8+
import ViewPicker from './ViewPicker.svelte';
9+
10+
let {
11+
dictionaryPreview = $bindable('show'),
12+
readonly = $bindable(false),
13+
}: {
14+
dictionaryPreview?: 'show' | 'hide' | 'sticky'
15+
readonly?: boolean
16+
} = $props();
17+
</script>
18+
<ResponsivePopup>
19+
{#snippet trigger({props})}
20+
<Button {...props} size="icon" variant="ghost" icon="i-mdi-layers" />
21+
{/snippet}
22+
<div class="space-y-2 md:space-y-4">
23+
<ViewPicker />
24+
<RadioGroup.Root bind:value={dictionaryPreview}>
25+
<h3 class="font-normal max-md:mb-1">{$t`Dictionary Preview`}</h3>
26+
<RadioGroup.Item value="show" label={$t`Show`} />
27+
<RadioGroup.Item value="hide" label={$t`Hide`}/>
28+
<RadioGroup.Item value="sticky" label={$t`Pinned`}/>
29+
</RadioGroup.Root>
30+
<DevContent>
31+
<div class="space-y-2">
32+
<h3 class="font-normal">Dev Options</h3>
33+
<div class="flex items-center space-x-2">
34+
<Switch bind:checked={readonly} label="Readonly" />
35+
</div>
36+
</div>
37+
</DevContent>
38+
</div>
39+
</ResponsivePopup>
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
<script lang="ts" context="module">
2+
export type EntryListViewMode = 'preview' | 'simple';
3+
</script>
4+
5+
<script lang="ts">
6+
import { t } from 'svelte-i18n-lingui';
7+
import Switch from '$lib/components/ui/switch/switch.svelte';
8+
import ResponsivePopup from '$lib/components/responsive-popup/responsive-popup.svelte';
9+
import {Button} from '$lib/components/ui/button';
10+
import DevContent from '$lib/layout/DevContent.svelte';
11+
import ViewPicker from './ViewPicker.svelte';
12+
import * as Tabs from '$lib/components/ui/tabs';
13+
import {Icon} from '$lib/components/ui/icon';
14+
15+
let {
16+
entryMode = $bindable('simple'),
17+
readonly = $bindable(false),
18+
}: {
19+
entryMode?: EntryListViewMode
20+
readonly?: boolean
21+
} = $props();
22+
23+
let open = $state(false);
24+
</script>
25+
26+
<ResponsivePopup bind:open>
27+
{#snippet trigger({props})}
28+
<Button {...props} size="xs-icon" variant="ghost" icon="i-mdi-layers" />
29+
{/snippet}
30+
<div class="space-y-3 md:space-y-4">
31+
32+
<div class="grid gap-2">
33+
<h3>{$t`List mode`}</h3>
34+
<Tabs.Root bind:value={entryMode} class="text-center_">
35+
<Tabs.List onkeydown={(e) => {if (e.key === 'Enter') open = false}}>
36+
<Tabs.Trigger value="simple" onclick={() => open = false}>
37+
<Icon icon="i-mdi-format-list-bulleted-square" class="mr-1"/>
38+
{$t`Simple`}
39+
</Tabs.Trigger>
40+
<Tabs.Trigger value="preview" onclick={() => open = false}>
41+
<Icon icon="i-mdi-format-list-text" class="mr-1"/>
42+
{$t`Preview`}
43+
</Tabs.Trigger>
44+
</Tabs.List>
45+
</Tabs.Root>
46+
</div>
47+
48+
<ViewPicker />
49+
50+
<DevContent>
51+
<div class="space-y-2">
52+
<h3 class="font-normal">Dev Options</h3>
53+
<div class="flex items-center space-x-2">
54+
<Switch bind:checked={readonly} label="Readonly" />
55+
</div>
56+
</div>
57+
</DevContent>
58+
</div>
59+
</ResponsivePopup>

frontend/viewer/src/project/browse/EntryView.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import {resource, Debounced, watch} from 'runed';
55
import { useMiniLcmApi } from '$lib/services/service-provider';
66
import { fade } from 'svelte/transition';
7-
import ViewPicker from './ViewPicker.svelte';
7+
import ViewPicker from './EditorViewOptions.svelte';
88
import EntryMenu from './EntryMenu.svelte';
99
import {ScrollArea} from '$lib/components/ui/scroll-area';
1010
import {cn} from '$lib/utils';
Lines changed: 25 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,13 @@
11
<script lang="ts">
2-
import * as RadioGroup from '$lib/components/ui/radio-group';
3-
import { t } from 'svelte-i18n-lingui';
4-
import { views } from '$lib/views/view-data';
5-
import { useCurrentView } from '$lib/views/view-service';
6-
import Switch from '$lib/components/ui/switch/switch.svelte';
7-
import ResponsivePopup from '$lib/components/responsive-popup/responsive-popup.svelte';
8-
import {Button} from '$lib/components/ui/button';
9-
import DevContent from '$lib/layout/DevContent.svelte';
102
import * as Popover from '$lib/components/ui/popover';
11-
import Markdown from 'svelte-exmarkdown';
3+
import * as RadioGroup from '$lib/components/ui/radio-group';
124
import NewTabLinKMarkdown from '$lib/markdown/NewTabLinKMarkdown.svelte';
135
import {delay} from '$lib/utils/time';
6+
import {views} from '$lib/views/view-data';
7+
import {useCurrentView} from '$lib/views/view-service';
8+
import Markdown from 'svelte-exmarkdown';
9+
import {t} from 'svelte-i18n-lingui';
1410
15-
let {
16-
dictionaryPreview = $bindable('show'),
17-
readonly = $bindable(false),
18-
}: {
19-
dictionaryPreview?: 'show' | 'hide' | 'sticky'
20-
readonly?: boolean
21-
} = $props();
2211
const currentView = useCurrentView();
2312
function getCurrentView() {
2413
return $currentView.id;
@@ -36,45 +25,24 @@
3625
}
3726
}
3827
</script>
39-
<ResponsivePopup title={$t`View Configuration`}>
40-
{#snippet trigger({props})}
41-
<Button {...props} size="icon" variant="ghost" icon="i-mdi-layers" />
42-
{/snippet}
43-
<div class="space-y-2 md:space-y-4">
44-
<RadioGroup.Root bind:value={getCurrentView, setCurrentView}>
45-
<Popover.Root onOpenChange={onPopoverOpenChange}>
46-
<Popover.InfoTrigger class="text-start w-fit">
47-
<h3 class="inline font-normal max-md:mb-1">{$t`View`}</h3>
48-
</Popover.InfoTrigger>
49-
<Popover.Content bind:ref={popoverContent} class="max-h-[40vh] overflow-y-auto text-sm flex flex-col gap-2">
50-
<div>
51-
<Markdown md={$t`The *FieldWorks Lite* view is designed for non-linguists and differs from the *FieldWorks Classic* view in the following ways:`} />
52-
<ul class="text-sm pl-4 list-disc mt-0.5 [&_strong]:font-semibold">
53-
<li><Markdown md={$t`**Simpler terminology** (e.g. *Word* instead of *Lexeme form*, *Meaning* instead of *Sense*)`} /></li>
54-
<li><Markdown md={$t`**Fewer fields** (e.g. hides *Complex form types*, *Literal meaning*)`} /></li>
55-
<li><Markdown md={$t`**Fewer morpheme types** (only *Root*, *Bound Root*, *Stem*, *Bound Stem*, *Particle*, *Phrase*, and *Discontiguous Phrase*)`} /></li>
56-
</ul>
57-
</div>
58-
<NewTabLinKMarkdown md={$t`The *FieldWorks Classic* view, on the other hand, is designed for users who are familiar with *[FieldWorks Language Explorer](https://software.sil.org/fieldworks/)*.`} />
59-
</Popover.Content>
60-
</Popover.Root>
61-
{#each views as view (view.id)}
62-
<RadioGroup.Item value={view.id} label={view.label} />
63-
{/each}
64-
</RadioGroup.Root>
65-
<RadioGroup.Root bind:value={dictionaryPreview}>
66-
<h3 class="font-normal max-md:mb-1">{$t`Dictionary Preview`}</h3>
67-
<RadioGroup.Item value="show" label={$t`Show`} />
68-
<RadioGroup.Item value="hide" label={$t`Hide`}/>
69-
<RadioGroup.Item value="sticky" label={$t`Pinned`}/>
70-
</RadioGroup.Root>
71-
<DevContent>
72-
<div class="space-y-2">
73-
<h3 class="font-normal">Dev Options</h3>
74-
<div class="flex items-center space-x-2">
75-
<Switch bind:checked={readonly} label="Readonly" />
76-
</div>
28+
<RadioGroup.Root bind:value={getCurrentView, setCurrentView}>
29+
<Popover.Root onOpenChange={onPopoverOpenChange}>
30+
<Popover.InfoTrigger class="text-start w-fit">
31+
<h3 class="inline font-normal max-md:mb-1">{$t`View`}</h3>
32+
</Popover.InfoTrigger>
33+
<Popover.Content bind:ref={popoverContent} class="max-h-[40vh] overflow-y-auto text-sm flex flex-col gap-2">
34+
<div>
35+
<Markdown md={$t`The *FieldWorks Lite* view is designed for non-linguists and differs from the *FieldWorks Classic* view in the following ways:`} />
36+
<ul class="text-sm pl-4 list-disc mt-0.5 [&_strong]:font-semibold">
37+
<li><Markdown md={$t`**Simpler terminology** (e.g. *Word* instead of *Lexeme form*, *Meaning* instead of *Sense*)`} /></li>
38+
<li><Markdown md={$t`**Fewer fields** (e.g. hides *Complex form types*, *Literal meaning*)`} /></li>
39+
<li><Markdown md={$t`**Fewer morpheme types** (only *Root*, *Bound Root*, *Stem*, *Bound Stem*, *Particle*, *Phrase*, and *Discontiguous Phrase*)`} /></li>
40+
</ul>
7741
</div>
78-
</DevContent>
79-
</div>
80-
</ResponsivePopup>
42+
<NewTabLinKMarkdown md={$t`The *FieldWorks Classic* view, on the other hand, is designed for users who are familiar with *[FieldWorks Language Explorer](https://software.sil.org/fieldworks/)*.`} />
43+
</Popover.Content>
44+
</Popover.Root>
45+
{#each views as view (view.id)}
46+
<RadioGroup.Item value={view.id} label={view.label} />
47+
{/each}
48+
</RadioGroup.Root>

0 commit comments

Comments
 (0)