abstracted proper entry picker component - ugly inside, nice on outside

This commit is contained in:
lingdocs 2022-04-04 16:23:01 +05:00
parent 03c7a8ba02
commit f1dd160b53
6 changed files with 102 additions and 54 deletions

View File

@ -0,0 +1,67 @@
import {
Types as T,
} from "@lingdocs/pashto-inflector";
import Select from "react-select";
import {
makeSelectOption,
makeVerbSelectOption,
zIndexProps,
} from "./np-picker/picker-tools";
function EntrySelect<E extends T.DictionaryEntry | VerbEntry>(props: {
entries: E[],
value: E | undefined,
onChange: (value: E | undefined) => void,
name: string | undefined,
isVerbSelect?: boolean,
}) {
const options = props.entries
.sort((a, b) => {
if ("entry" in a) {
return a.entry.p.localeCompare("p" in b ? b.p : b.entry.p, "af-PS")
}
return a.p.localeCompare("p" in b ? b.p : b.entry.p, "af-PS");
})
.map((e) => {
if ("entry" in e) {
return (props.isVerbSelect ? makeVerbSelectOption : makeSelectOption)(e);
}
return makeSelectOption(e);
});
function onSelect(v: { label: string, value: string } | null) {
if (!v) {
props.onChange(undefined);
return;
}
const s = props.entries.find(e => (
("entry" in e)
? e.entry.ts.toString() === v.value
: e.ts.toString() === v.value
));
if (!s) return;
props.onChange(s);
}
const selectedEntry: T.DictionaryEntry | undefined = !props.value
? undefined
: "entry" in props.value
? props.value.entry
: "p" in props.value
? props.value
: undefined;
const selected = !selectedEntry
? undefined
: options.find(o => (selectedEntry && (o.value === selectedEntry.ts.toString())));
return <div>
<Select
isSearchable={true}
value={selected}
onChange={onSelect}
className="mb-2"
options={options}
placeholder={props.name ? `Select ${props.name}...` : undefined}
{...zIndexProps}
/>
</div>
}
export default EntrySelect;

View File

@ -1,7 +1,6 @@
import Select from "react-select";
import {
makeNounSelection,
makeVerbSelectOption,
zIndexProps,
} from "./np-picker/picker-tools";
import {
@ -10,6 +9,7 @@ import {
getVerbInfo,
} from "@lingdocs/pashto-inflector";
import { isPerfectTense } from "../lib/phrase-building/vp-tools";
import EntrySelect from "./EntrySelect";
// import { useState } from "react";
const tenseOptions: { label: string | JSX.Element, value: VerbTense }[] = [{
@ -73,7 +73,7 @@ function VerbPicker({ onChange, subject, changeSubject, verb, verbs }: {
verbs: VerbEntry[],
verb: VerbSelection | undefined,
subject: NPSelection | undefined,
onChange: (p: VerbSelection) => void,
onChange: (p: VerbSelection | undefined) => void,
changeSubject: (p: NPSelection | undefined) => void,
}) {
// const [filters, useFilters] = useState<Filters>({
@ -83,12 +83,10 @@ function VerbPicker({ onChange, subject, changeSubject, verb, verbs }: {
// intransitive: true,
// grammaticallyTransitive: true,
// });
const options = verbs.sort((a, b) => (a.entry.p.localeCompare(b.entry.p, "af-PS"))).map(makeVerbSelectOption);
function onEntrySelect({ value }: { label: string, value: string }) {
const v = verbs.find(v => v.entry.ts.toString() === value);
function onVerbSelect(v: VerbEntry | undefined) {
// TODO: what to do when clearing
if (!v) {
console.error("entry not found");
return;
return onChange(v);
}
onChange(makeVerbSelection(v, changeSubject, verb));
}
@ -178,7 +176,13 @@ function VerbPicker({ onChange, subject, changeSubject, verb, verbs }: {
const tOptions = (verb?.tenseCategory === "perfect") ? perfectTenseOptions : tenseOptions;
return <div style={{ maxWidth: "225px", minWidth: "175px" }}>
<div>Verb:</div>
<Select
<EntrySelect
entries={verbs}
value={verb?.verb}
onChange={onVerbSelect}
name="Verb"
/>
{/* <Select
value={verb && verb.verb.entry.ts.toString()}
// @ts-ignore
onChange={onEntrySelect}
@ -189,7 +193,7 @@ function VerbPicker({ onChange, subject, changeSubject, verb, verbs }: {
// // @ts-ignore
placeholder={verb ? options.find(o => o.value === (verb.verb.entry).ts.toString())?.label : "Select Verb..."}
{...zIndexProps}
/>
/> */}
{verb && verb.changeTransitivity && <div className="text-center mt-3">
<ButtonSelect
small

View File

@ -1,7 +1,4 @@
import Select from "react-select";
import {
makeSelectOption,
zIndexProps,
makeNounSelection,
} from "./picker-tools";
import {
@ -11,6 +8,7 @@ import {
} from "@lingdocs/pashto-inflector";
import { useState } from "react";
import { isFemNounEntry, isPattern1Entry, isPattern2Entry, isPattern3Entry, isPattern4Entry, isPattern5Entry, isPattern6FemEntry } from "../../lib/type-predicates";
import EntrySelect from "../EntrySelect";
const filterOptions = [
{
@ -59,18 +57,15 @@ function nounFilter(p: FilterPattern | undefined) {
: () => true;
}
function NPNounPicker({ onChange, noun, nouns, clearButton }: { nouns: NounEntry[], noun: NounSelection | undefined, onChange: (p: NounSelection) => void, clearButton?: JSX.Element }) {
function NPNounPicker({ onChange, noun, nouns, clearButton }: { nouns: NounEntry[], noun: NounSelection | undefined, onChange: (p: NounSelection | undefined) => void, clearButton?: JSX.Element }) {
const [patternFilter, setPatternFilter] = useState<FilterPattern | undefined>(undefined);
const [showFilter, setShowFilter] = useState<boolean>(false)
const options = nouns
const nounsFiltered = nouns
.filter(nounFilter(patternFilter))
.sort((a, b) => (a.p.localeCompare(b.p, "af-PS")))
.map(makeSelectOption);
function onEntrySelect({ value }: { label: string, value: string }) {
const entry = nouns.find(n => n.ts.toString() === value);
.sort((a, b) => (a.p.localeCompare(b.p, "af-PS")));
function onEntrySelect(entry: NounEntry | undefined) {
if (!entry) {
console.error("entry not found");
return;
return onChange(undefined);
}
onChange(makeNounSelection(entry));
}
@ -101,17 +96,11 @@ function NPNounPicker({ onChange, noun, nouns, clearButton }: { nouns: NounEntry
/>
</div>}
{!(noun && noun.dynamicComplement) ? <div>
<Select
value={noun && noun.entry.ts.toString()}
// @ts-ignore
<EntrySelect
value={noun?.entry}
entries={nounsFiltered}
onChange={onEntrySelect}
className="mb-2"
// @ts-ignore
options={options}
isSearchable
// @ts-ignore
placeholder={noun ? options.find(o => o.value === (noun.entry).ts.toString())?.label : "Select Noun..."}
{...zIndexProps}
name="Noun"
/>
</div> : <div>
{noun && <div>

View File

@ -1,8 +1,4 @@
import Select from "react-select";
import {
makeSelectOption,
zIndexProps,
} from "./picker-tools";
import EntrySelect from "../EntrySelect";
function makeParticipleSelection(verb: VerbEntry): ParticipleSelection {
return {
@ -14,31 +10,23 @@ function makeParticipleSelection(verb: VerbEntry): ParticipleSelection {
function NPParticiplePicker({ onChange, participle, verbs, clearButton }: {
verbs: VerbEntry[],
participle: ParticipleSelection | undefined,
onChange: (p: ParticipleSelection) => void,
onChange: (p: ParticipleSelection | undefined) => void,
clearButton: JSX.Element,
}) {
const options = verbs.map(makeSelectOption)
function onEntrySelect({ value }: { label: string, value: string }) {
const verb = verbs.find(v => v.entry.ts.toString() === value);
if (!verb) {
console.error("entry not found");
function onEntrySelect(entry: VerbEntry | undefined) {
if (!entry) {
onChange(undefined);
return;
}
onChange(makeParticipleSelection(verb));
onChange(makeParticipleSelection(entry));
}
return <div style={{ maxWidth: "225px" }}>
{clearButton}
<Select
value={participle && participle.verb.entry.ts.toString()}
// @ts-ignore
<EntrySelect
value={participle?.verb}
entries={verbs}
onChange={onEntrySelect}
className="mb-2"
// @ts-ignore
options={options}
isSearchable
// // @ts-ignore
placeholder={participle ? options.find(o => o.value === (participle.verb.entry).ts.toString())?.label : "Select Participle..."}
{...zIndexProps}
name="Pariticple"
/>
{participle && <div className="my-2 d-flex flex-row justify-content-around align-items-center">
<div>Masc.</div>

View File

@ -27,7 +27,7 @@ export function makeVerbSelectOption(e: VerbEntry): { value: string, label: stri
};
}
export function makeSelectOption(e: VerbEntry | NounEntry | AdjectiveEntry | LocativeAdverbEntry): { value: string, label: string } {
export function makeSelectOption(e: T.DictionaryEntry | VerbEntry | NounEntry | AdjectiveEntry | LocativeAdverbEntry): { value: string, label: string } {
const entry = "entry" in e ? e.entry : e;
const eng = (isVerbEntry(e))
? (getEnglishParticiple(e.entry))

View File

@ -28,7 +28,7 @@ export function isNounOrAdjEntry(e: Entry): e is (NounEntry | AdjectiveEntry) {
return isNounEntry(e) || isAdjectiveEntry(e);
}
export function isVerbEntry(e: Entry): e is VerbEntry {
export function isVerbEntry(e: Entry | T.DictionaryEntry): e is VerbEntry {
return "entry" in e && !!e.entry.c?.startsWith("v.");
}