Skip to content

Commit

Permalink
Refactor OptionEditors to explicitly use string values
Browse files Browse the repository at this point in the history
so we don't create fake objects
  • Loading branch information
myieye committed Oct 17, 2024
1 parent 70034ec commit 6fd56de
Show file tree
Hide file tree
Showing 8 changed files with 39 additions and 75 deletions.
2 changes: 0 additions & 2 deletions frontend/viewer/src/lib/config-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@ export type OptionFieldConfig = {
ws: `first-${WritingSystemType}`;
}

export type OptionFieldValue = {id: string};

export type BaseEntityFieldConfig<T> = (({
type: 'multi';
id: ConditionalKeys<T, IMultiString>;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<script lang="ts">
import type { MultiString } from '../../mini-lcm';
import type {FieldConfig, OptionFieldConfig, OptionFieldValue} from '../../config-types';
import type {FieldConfig, OptionFieldConfig} from '../../config-types';
import MultiOptionEditor from './MultiOptionEditor.svelte';
import SingleOptionEditor from './SingleOptionEditor.svelte';
import SingleFieldEditor from './SingleFieldEditor.svelte';
Expand Down Expand Up @@ -33,7 +33,7 @@
function isSingleOption(state: {value: unknown, field: FieldConfig}): state is {value: string, field: FieldConfig & OptionFieldConfig} {
return field.type === 'option';
}
function isMultiOption(state: {value: unknown, field: FieldConfig}): state is {value: OptionFieldValue[], field: FieldConfig & OptionFieldConfig} {
function isMultiOption(state: {value: unknown, field: FieldConfig}): state is {value: string[], field: FieldConfig & OptionFieldConfig} {
return field.type === 'multi-option';
}
</script>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,19 @@
import type { MenuOption } from 'svelte-ux';
import CrdtMultiOptionField from '../inputs/CrdtMultiOptionField.svelte';
import FieldTitle from '../FieldTitle.svelte';
import type { WritingSystems } from '../../mini-lcm';
import { type Readable } from 'svelte/store';
import { getContext } from 'svelte';
import { pickWritingSystems } from '../../utils';
import type {
OptionFieldValue,
WritingSystemSelection
} from '../../config-types';
import type { WritingSystemSelection } from '../../config-types';
import {useCurrentView} from '../../services/view-service';
import {useWritingSystems} from '../../writing-systems';
type T = $$Generic<{}>;
export let id: string;
export let wsType: WritingSystemSelection;
export let name: string | undefined = undefined;
export let readonly: boolean = false;
export let value: OptionFieldValue[];
export let value: string[];
export let options: MenuOption<string>[];
export let options: MenuOption[] = [];
let currentView = useCurrentView();
const allWritingSystems = useWritingSystems();
$: [ws] = pickWritingSystems(wsType, $allWritingSystems);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,20 @@
<script lang="ts">
import CrdtOptionField from '../inputs/CrdtOptionField.svelte';
import FieldTitle from '../FieldTitle.svelte';
import type { WritingSystems } from '../../mini-lcm';
import { type Readable } from 'svelte/store';
import { getContext } from 'svelte';
import { pickWritingSystems } from '../../utils';
import type {WritingSystemSelection} from '../../config-types';
import type { MenuOption } from 'svelte-ux';
import {useCurrentView} from '../../services/view-service';
import {useWritingSystems} from '../../writing-systems';
type T = $$Generic<{}>;
export let id: string;
export let wsType: WritingSystemSelection;
export let name: string | undefined = undefined;
export let value: string | undefined;
export let readonly: boolean = false;
export let value: string | undefined;
export let options: MenuOption<string>[];
export let options: MenuOption[] = [];
let currentView = useCurrentView();
const allWritingSystems = useWritingSystems();
$: [ws] = pickWritingSystems(wsType, $allWritingSystems);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
<script lang="ts">
import type { ComponentProps } from 'svelte';
import { createEventDispatcher, type ComponentProps } from 'svelte';
import CrdtField from './CrdtField.svelte';
import { TextField, type MenuOption, MultiSelectField } from 'svelte-ux';
import type {OptionFieldValue} from '../../config-types';
import { type TextField, type MenuOption, MultiSelectField } from 'svelte-ux';
import {mdiMagnify} from '@mdi/js';
export let value: OptionFieldValue[];
const dispatch = createEventDispatcher<{
change: { value: string[] }; // Generics aren't working properly in CrdtField, so we make the type excplicit here
}>();
export let value: string[];
export let unsavedChanges = false;
export let options: MenuOption[] = [];
export let label: string | undefined = undefined;
Expand All @@ -16,28 +18,18 @@
let append: HTMLElement;
$: sortedOptions = options.sort((a, b) => a.label.localeCompare(b.label));
function asMultiSelectValues(values: any[]): string[] {
return values?.map(v => v.id) ?? [];
}
function asObjectValues(values: string[]) {
return values.map(v => ({id: v}));
}
</script>

<CrdtField on:change bind:value bind:unsavedChanges let:editorValue let:onEditorValueChange viewMergeButtonPortal={append}>
<CrdtField on:change={(e) => dispatch('change', { value: e.detail.value})} bind:value bind:unsavedChanges let:editorValue let:onEditorValueChange viewMergeButtonPortal={append}>
<MultiSelectField
on:change={(e) => {
onEditorValueChange(asObjectValues(e.detail.value), true);
}}
value={asMultiSelectValues(editorValue)}
on:change={(e) =>
onEditorValueChange(e.detail.value ?? [], true)}
value={editorValue}
disabled={readonly}
options={sortedOptions}
icon={readonly ? undefined : mdiMagnify}
valueProp="value"
labelProp="label"
formatSelected={({ options }) =>
options.map((o) => o.label).join(", ") || "None"}
options.map((o) => o.label).join(', ') || 'None'}
infiniteScroll
clearSearchOnOpen={false}
clearable={false}
Expand All @@ -49,9 +41,3 @@
<span bind:this={append} slot="append" />
</MultiSelectField>
</CrdtField>

<style lang="postcss">
:global(.unresolved-merge .field-container) {
@apply !border-warning;
}
</style>
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script lang="ts">
import type { ComponentProps } from 'svelte';
import CrdtField from './CrdtField.svelte';
import { SelectField, TextField, type MenuOption } from 'svelte-ux';
import { SelectField, type TextField, type MenuOption } from 'svelte-ux';
export let value: string | undefined;
export let unsavedChanges = false;
Expand Down Expand Up @@ -32,9 +32,3 @@
</SelectField>
{/key}
</CrdtField>

<style>
:global(.unresolved-merge .field-container) {
@apply !border-warning;
}
</style>
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,15 @@
import {useWritingSystems} from '../../writing-systems';
import {pickBestAlternative} from '../../utils';
import {usePartsOfSpeech} from '../../parts-of-speech';
import type {OptionFieldValue} from '../../config-types';
import {useCurrentView, objectTemplateAreas} from '../../services/view-service';
export let sense: ISense;
export let readonly: boolean = false;
const partsOfSpeech = usePartsOfSpeech();
const semanticDomains = useSemanticDomains();
const writingSystems = useWritingSystems();
function setSemanticDomains(selectedValues: OptionFieldValue[]) {
sense.semanticDomains = selectedValues.map(v => $semanticDomains.find(sd => sd.id === v.id)).filter((sd): sd is SemanticDomain => !!sd);
function setSemanticDomains(ids: string[]): void {
sense.semanticDomains = ids.map(id => $semanticDomains.find(sd => sd.id === id)).filter((sd): sd is SemanticDomain => !!sd);
}
const currentView = useCurrentView();
</script>
Expand All @@ -35,18 +34,18 @@
wsType="analysis" />
<SingleOptionEditor on:change
bind:value={sense.partOfSpeechId}
options={$partsOfSpeech.map(pos => ({value: pos.id, label: pickBestAlternative(pos.name, 'analysis', $writingSystems)}))}
{readonly}
id="partOfSpeechId"
wsType="first-analysis"
options={$partsOfSpeech.map(pos => ({label: pickBestAlternative(pos.name, 'analysis', $writingSystems), value: pos.id}))}/>
wsType="first-analysis" />
<MultiOptionEditor
value={sense.semanticDomains}
on:change={e =>{ setSemanticDomains(e.detail.value)} }
on:change
{readonly}
id="semanticDomains"
wsType="first-analysis"
options={$semanticDomains.map(sd => ({label: sd.code + ' ' + pickBestAlternative(sd.name, 'analysis', $writingSystems), value: sd.id}))}/>
on:change={(e) => setSemanticDomains(e.detail.value)}
on:change
value={sense.semanticDomains.map(sd => sd.id)}
options={$semanticDomains.map(sd => ({value: sd.id, label: `${sd.code} ${pickBestAlternative(sd.name, 'analysis', $writingSystems)}`}))}
{readonly}
id="semanticDomains"
wsType="first-analysis" />
<EntityEditor
entity={sense}
{readonly}
Expand Down
18 changes: 9 additions & 9 deletions frontend/viewer/src/lib/sandbox/Sandbox.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,30 @@
import CrdtMultiOptionField from '../entry-editor/inputs/CrdtMultiOptionField.svelte';
const options = [
{ name: 'One', value: 1 },
{ name: 'Two', value: 2 },
{ name: 'Three', value: 3 },
{ name: 'Four', value: 4 },
{ label: 'One', value: 1 },
{ label: 'Two', value: 2 },
{ label: 'Three', value: 3 },
{ label: 'Four', value: 4 },
];
let value = [3];
const crdtOptions:MenuOption[] = [
const crdtOptions: MenuOption[] = [
{value: 'a', label: 'Alpha'},
{value: 'b', label: 'Beta'},
{value: 'c', label: 'Charlie'},
];
let crdtValue = [{id: 'a'}];
let crdtValue = ['a'];
</script>

<div class="grid gap-3 justify-items-start">
<MultiSelectField {options} {value} on:change={(e) => (value = e.detail.value)}/>
<MultiSelectField {options} {value} on:change={(e) => (value = e.detail.value ?? [])}/>
<p>selected: {value.join('|')}</p>
<Button on:click={() => value = [4]}>Select Four only</Button>
</div>
<div class="grid gap-3 justify-items-start">
<CrdtMultiOptionField bind:value={crdtValue} options={crdtOptions}/>
<p>selected: {crdtValue.map(c => c.id).join('|')}</p>
<Button on:click={() => crdtValue = [{id: 'c'}]}>Select Charlie only</Button>
<p>selected: {crdtValue.join('|')}</p>
<Button on:click={() => crdtValue = ['c']}>Select Charlie only</Button>
</div>

0 comments on commit 6fd56de

Please sign in to comment.