refactor/better naming for inflection search types
This commit is contained in:
parent
ced17170a7
commit
0ad08abb88
|
@ -134,7 +134,7 @@ class App extends Component<RouteComponentProps, State> {
|
|||
wordlist: [],
|
||||
reviewTasks: [],
|
||||
user: readUser(),
|
||||
powerResults: undefined,
|
||||
inflectionSearchResults: undefined,
|
||||
};
|
||||
this.handleOptionsUpdate = this.handleOptionsUpdate.bind(this);
|
||||
this.handleTextOptionsUpdate = this.handleTextOptionsUpdate.bind(this);
|
||||
|
@ -146,7 +146,7 @@ class App extends Component<RouteComponentProps, State> {
|
|||
this.handleRefreshWordlist = this.handleRefreshWordlist.bind(this);
|
||||
this.handleRefreshReviewTasks = this.handleRefreshReviewTasks.bind(this);
|
||||
this.handleDictionaryUpdate = this.handleDictionaryUpdate.bind(this);
|
||||
this.handlePowerSearch = this.handlePowerSearch.bind(this);
|
||||
this.handleInflectionSearch = this.handleInflectionSearch.bind(this);
|
||||
}
|
||||
|
||||
public componentDidMount() {
|
||||
|
@ -245,7 +245,7 @@ class App extends Component<RouteComponentProps, State> {
|
|||
e.preventDefault();
|
||||
if (e.repeat) return;
|
||||
if (!this.state.searchValue) return;
|
||||
this.handlePowerSearch();
|
||||
this.handleInflectionSearch();
|
||||
});
|
||||
Mousetrap.bind(["ctrl+s", "command+s"], (e) => {
|
||||
if (this.state.user?.level === "basic") return;
|
||||
|
@ -406,7 +406,7 @@ class App extends Component<RouteComponentProps, State> {
|
|||
searchValue: "",
|
||||
results: [],
|
||||
page: 1,
|
||||
powerResults: undefined,
|
||||
inflectionSearchResults: undefined,
|
||||
});
|
||||
if (this.props.location.pathname !== "/") {
|
||||
this.props.history.replace("/");
|
||||
|
@ -417,7 +417,7 @@ class App extends Component<RouteComponentProps, State> {
|
|||
searchValue,
|
||||
results: dictionary.search({ ...prevState, searchValue }),
|
||||
page: 1,
|
||||
powerResults: undefined,
|
||||
inflectionSearchResults: undefined,
|
||||
}));
|
||||
if (this.props.history.location.pathname !== "/search") {
|
||||
this.props.history.push("/search");
|
||||
|
@ -459,19 +459,19 @@ class App extends Component<RouteComponentProps, State> {
|
|||
}
|
||||
}
|
||||
|
||||
private handlePowerSearch() {
|
||||
private handleInflectionSearch() {
|
||||
function prepValueForSearch(searchValue: string, textOptions: T.TextOptions): string {
|
||||
const s = revertSpelling(searchValue, textOptions.spelling);
|
||||
return standardizePashto(s.trim());
|
||||
}
|
||||
this.setState({ powerResults: "searching" });
|
||||
this.setState({ inflectionSearchResults: "searching" });
|
||||
// need timeout to make sure the "searching" notice gets rendered before things lock up for the big search
|
||||
setTimeout(() => {
|
||||
const powerResults = searchAllInflections(
|
||||
const inflectionSearchResults = searchAllInflections(
|
||||
allEntries(),
|
||||
prepValueForSearch(this.state.searchValue, this.state.options.textOptionsRecord.textOptions),
|
||||
);
|
||||
this.setState({ powerResults });
|
||||
this.setState({ inflectionSearchResults });
|
||||
}, 20);
|
||||
}
|
||||
|
||||
|
@ -563,7 +563,7 @@ class App extends Component<RouteComponentProps, State> {
|
|||
<Results
|
||||
state={this.state}
|
||||
isolateEntry={this.handleIsolateEntry}
|
||||
handlePowerSearch={this.handlePowerSearch}
|
||||
handleInflectionSearch={this.handleInflectionSearch}
|
||||
/>
|
||||
</Route>
|
||||
<Route path="/new-entries">
|
||||
|
@ -572,7 +572,7 @@ class App extends Component<RouteComponentProps, State> {
|
|||
<Results
|
||||
state={this.state}
|
||||
isolateEntry={this.handleIsolateEntry}
|
||||
handlePowerSearch={this.handlePowerSearch}
|
||||
handleInflectionSearch={this.handleInflectionSearch}
|
||||
/>
|
||||
:
|
||||
<div>No new words added this month 😓</div>
|
||||
|
|
|
@ -15,19 +15,19 @@ import {
|
|||
displayPositionResult,
|
||||
} from "../lib/inflection-search-helpers";
|
||||
import {
|
||||
InflectionSearchResult,
|
||||
InflectionName,
|
||||
InflectionFormMatch,
|
||||
} from "../types/dictionary-types";
|
||||
|
||||
function InflectionSearchResultDisplay(
|
||||
{ result, textOptions, entry }:
|
||||
{ result: InflectionSearchResult, textOptions: T.TextOptions, entry: T.DictionaryEntry }
|
||||
function InflectionFormMatchDisplay(
|
||||
{ form, textOptions, entry }:
|
||||
{ form: InflectionFormMatch, textOptions: T.TextOptions, entry: T.DictionaryEntry }
|
||||
) {
|
||||
function getTransitivity(): "transitive" | "intransitive" | "grammatically transitive" {
|
||||
if (result.form.includes("grammaticallyTransitive")) {
|
||||
if (form.path.includes("grammaticallyTransitive")) {
|
||||
return "grammatically transitive";
|
||||
}
|
||||
if (result.form.includes("transitive")) {
|
||||
if (form.path.includes("transitive")) {
|
||||
return "transitive";
|
||||
}
|
||||
if (entry.c?.includes("intrans.")) {
|
||||
|
@ -36,15 +36,15 @@ function InflectionSearchResultDisplay(
|
|||
return "transitive";
|
||||
}
|
||||
const transitivity = getTransitivity();
|
||||
const isPast = (result.form.includes("past") || result.form.includes("perfect"));
|
||||
const isPast = (form.path.includes("past") || form.path.includes("perfect"));
|
||||
const isErgative = (transitivity !== "intransitive") && isPast;
|
||||
const isVerbPos = (x: InflectionName[] | T.Person[] | null) => {
|
||||
if (x === null) return false;
|
||||
return (typeof x[0] !== "string");
|
||||
};
|
||||
return <div className="mb-4">
|
||||
<div className="mb-2"><strong>{displayFormResult(result.form)}</strong></div>
|
||||
{result.matches.map((match, i) => <div className="ml-2" key={i}>
|
||||
<div className="mb-2"><strong>{displayFormResult(form.path)}</strong></div>
|
||||
{form.matches.map((match, i) => <div className="ml-2" key={i}>
|
||||
<InlinePs opts={textOptions}>{match.ps}</InlinePs>
|
||||
<div className="ml-3 my-2">
|
||||
<em>
|
||||
|
@ -57,4 +57,4 @@ function InflectionSearchResultDisplay(
|
|||
</div>;
|
||||
}
|
||||
|
||||
export default InflectionSearchResultDisplay;
|
||||
export default InflectionFormMatchDisplay;
|
|
@ -11,7 +11,7 @@ import {
|
|||
} from "@lingdocs/pashto-inflector";
|
||||
import { isPashtoScript } from "./is-pashto";
|
||||
import {
|
||||
InflectionSearchResult, PowerResult,
|
||||
InflectionSearchResult, InflectionFormMatch,
|
||||
} from "../types/dictionary-types";
|
||||
import { makeAWeeBitFuzzy } from "./wee-bit-fuzzy";
|
||||
// @ts-ignore
|
||||
|
@ -26,19 +26,19 @@ const relevancySorter = new relevancy.Sorter();
|
|||
// That's so much better I'm removing the option of skipping compounds
|
||||
// ~4th iteration:~ ignore perfective or imperfective if wasn't present in verb info (not worth it - scrapped)
|
||||
|
||||
export function searchAllInflections(allDocs: T.DictionaryEntry[], searchValue: string): { entry: T.DictionaryEntry, results: InflectionSearchResult[] }[] {
|
||||
export function searchAllInflections(allDocs: T.DictionaryEntry[], searchValue: string): InflectionSearchResult[] {
|
||||
const index = isPashtoScript(searchValue) ? "p" : "f"
|
||||
function sortResultsByRelevancy(arr: PowerResult[]): PowerResult[] {
|
||||
return relevancySorter.sort(arr, searchValue, (obj: PowerResult, calc: any) => (
|
||||
calc(removeAccents(obj.results[0].matches[0].ps[index]))
|
||||
function sortResultsByRelevancy(arr: InflectionSearchResult[]): InflectionSearchResult[] {
|
||||
return relevancySorter.sort(arr, searchValue, (obj: InflectionSearchResult, calc: any) => (
|
||||
calc(removeAccents(obj.forms[0].matches[0].ps[index]))
|
||||
));
|
||||
}
|
||||
// TODO: could be better to remove the accents on the searchValue as well beforehand
|
||||
function sortMatchesByRelevancy(r: PowerResult): PowerResult {
|
||||
function sortMatchesByRelevancy(r: InflectionSearchResult): InflectionSearchResult {
|
||||
// first sort all the matches of each form by relevance
|
||||
const rStage2 = {
|
||||
...r,
|
||||
results: r.results.map(x => ({
|
||||
forms: r.forms.map(x => ({
|
||||
...x,
|
||||
matches: relevancySorter.sort(x.matches, searchValue, (obj: {
|
||||
ps: T.PsString;
|
||||
|
@ -48,12 +48,12 @@ export function searchAllInflections(allDocs: T.DictionaryEntry[], searchValue:
|
|||
}))
|
||||
};
|
||||
// then sort the forms by relevance
|
||||
const results = relevancySorter.sort(rStage2.results, searchValue, (obj: InflectionSearchResult, calc: any) => (
|
||||
const forms = relevancySorter.sort(rStage2.forms, searchValue, (obj: InflectionFormMatch, calc: any) => (
|
||||
calc(removeAccents(obj.matches[0].ps[index]))
|
||||
));
|
||||
return {
|
||||
...r,
|
||||
results,
|
||||
forms,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -72,7 +72,7 @@ export function searchAllInflections(allDocs: T.DictionaryEntry[], searchValue:
|
|||
// also do version without directional pronoun on front
|
||||
const searchFun = (ps: T.PsString) => !!ps[script].match(searchRegex)
|
||||
// console.time(timerLabel);
|
||||
const results = allDocs.reduce((all: PowerResult[], entry) => {
|
||||
const results = allDocs.reduce((all: InflectionSearchResult[], entry) => {
|
||||
const type = isNounAdjOrVerb(entry);
|
||||
if (entry.c && type === "verb") {
|
||||
try {
|
||||
|
@ -84,12 +84,12 @@ export function searchAllInflections(allDocs: T.DictionaryEntry[], searchValue:
|
|||
entry,
|
||||
complement,
|
||||
);
|
||||
const results = searchPile(
|
||||
const forms = searchPile(
|
||||
conjugation as any,
|
||||
searchFun,
|
||||
);
|
||||
if (results.length) {
|
||||
return [...all, { entry, results }];
|
||||
if (forms.length) {
|
||||
return [...all, { entry, forms }];
|
||||
}
|
||||
return all;
|
||||
} catch (e) {
|
||||
|
@ -101,9 +101,9 @@ export function searchAllInflections(allDocs: T.DictionaryEntry[], searchValue:
|
|||
if (entry.c && type === "nounAdj") {
|
||||
const inflections = inflectWord(entry);
|
||||
if (!inflections) return all;
|
||||
const results = searchPile(inflections as any, searchFun);
|
||||
if (results.length) {
|
||||
return [...all, { entry, results }];
|
||||
const forms = searchPile(inflections as any, searchFun);
|
||||
if (forms.length) {
|
||||
return [...all, { entry, forms }];
|
||||
}
|
||||
}
|
||||
return all;
|
||||
|
|
|
@ -17,7 +17,7 @@ import { personFromVerbBlockPos } from "@lingdocs/pashto-inflector";
|
|||
import {
|
||||
InflectionName,
|
||||
PluralInflectionName,
|
||||
InflectionSearchResult,
|
||||
InflectionFormMatch,
|
||||
} from "../types/dictionary-types";
|
||||
|
||||
const inflectionNames: { inflections: InflectionName[], plural: PluralInflectionName[] } = {
|
||||
|
@ -42,17 +42,17 @@ function isPsString(x: T.PsString | ObPile): x is T.PsString {
|
|||
);
|
||||
}
|
||||
|
||||
function isBlockResult(x: InflectionSearchResult[] | BlockResult): x is BlockResult {
|
||||
function isBlockResult(x: InflectionFormMatch[] | BlockResult): x is BlockResult {
|
||||
return "ps" in x[0];
|
||||
}
|
||||
|
||||
// NOTE: perfectiveSplit needs to be ignored because the [PsString, PsString] structure breaks the search!
|
||||
const defaultFieldsToIgnore = ["info", "type", "perfectiveSplit"];
|
||||
|
||||
export function searchPile(pile: ObPile, searchFun: (s: T.PsString) => boolean, toIgnore: string[] = []): InflectionSearchResult[] {
|
||||
export function searchPile(pile: ObPile, searchFun: (s: T.PsString) => boolean, toIgnore: string[] = []): InflectionFormMatch[] {
|
||||
const fieldsToIgnore = [...defaultFieldsToIgnore, toIgnore];
|
||||
|
||||
function searchObRecord(record: ObRec): null | BlockResult | SinglePsResult | InflectionSearchResult[] {
|
||||
function searchObRecord(record: ObRec): null | BlockResult | SinglePsResult | InflectionFormMatch[] {
|
||||
// hit a bottom part a tree, see if what we're looking for is there
|
||||
if (Array.isArray(record)) {
|
||||
// @ts-ignore
|
||||
|
@ -68,7 +68,7 @@ export function searchPile(pile: ObPile, searchFun: (s: T.PsString) => boolean,
|
|||
return searchPile(record, searchFun);
|
||||
}
|
||||
|
||||
return Object.entries(pile).reduce((res: InflectionSearchResult[], entry): InflectionSearchResult[] => {
|
||||
return Object.entries(pile).reduce((res: InflectionFormMatch[], entry): InflectionFormMatch[] => {
|
||||
const [name, value] = entry;
|
||||
if (fieldsToIgnore.includes(name)) {
|
||||
return res;
|
||||
|
@ -83,7 +83,7 @@ export function searchPile(pile: ObPile, searchFun: (s: T.PsString) => boolean,
|
|||
return [
|
||||
...res,
|
||||
{
|
||||
form: [name],
|
||||
path: [name],
|
||||
matches: [{ ps: result, pos: null }],
|
||||
},
|
||||
];
|
||||
|
@ -96,18 +96,18 @@ export function searchPile(pile: ObPile, searchFun: (s: T.PsString) => boolean,
|
|||
return [
|
||||
...res,
|
||||
{
|
||||
form: [name],
|
||||
path: [name],
|
||||
matches: result,
|
||||
}
|
||||
];
|
||||
}
|
||||
// Result: Have to keep looking down recursively
|
||||
// add in the current path to all the results
|
||||
const rb: InflectionSearchResult[] = [
|
||||
const rb: InflectionFormMatch[] = [
|
||||
...res,
|
||||
...result.map((r) => ({
|
||||
...r,
|
||||
form: [name, ...r.form]
|
||||
path: [name, ...r.path]
|
||||
})),
|
||||
]
|
||||
return rb;
|
||||
|
|
|
@ -257,7 +257,7 @@ function IsolatedEntry({ state, dictionary, isolateEntry }: {
|
|||
<Results
|
||||
state={{ ...state, results: relatedEntries }}
|
||||
isolateEntry={isolateEntry}
|
||||
handlePowerSearch={() => null}
|
||||
handleInflectionSearch={() => null}
|
||||
/>
|
||||
</> : <div style={{ height: "500px" }} />}
|
||||
<Modal
|
||||
|
|
|
@ -15,20 +15,19 @@ import {
|
|||
import { isPashtoScript } from "../lib/is-pashto";
|
||||
import Entry from "../components/Entry";
|
||||
import { Helmet } from "react-helmet";
|
||||
import InflectionSearchResultDisplay from "../components/InflectionSearchResultDisplay";
|
||||
import InflectionFormMatchDisplay from "../components/InflectionFormMatchDisplay";
|
||||
import { getTextOptions } from "../lib/get-text-options";
|
||||
import {
|
||||
State,
|
||||
InflectionSearchResult,
|
||||
} from "../types/dictionary-types";
|
||||
|
||||
export const inflectionSearchIcon = "fas fa-search-plus";
|
||||
|
||||
// TODO: put power results in a prop so we can do it from outside with the keyboard shortcut
|
||||
function Results({ state, isolateEntry, handlePowerSearch }: {
|
||||
function Results({ state, isolateEntry, handleInflectionSearch }: {
|
||||
state: State,
|
||||
isolateEntry: (ts: number) => void,
|
||||
handlePowerSearch: () => void,
|
||||
handleInflectionSearch: () => void,
|
||||
}) {
|
||||
const [suggestionState, setSuggestionState] = useState<"none" | "editing" | "received">("none");
|
||||
const [comment, setComment] = useState<string>("");
|
||||
|
@ -67,34 +66,34 @@ function Results({ state, isolateEntry, handlePowerSearch }: {
|
|||
addSubmission(newEntry, state.user);
|
||||
setSuggestionState("received");
|
||||
}
|
||||
const powerResults = state.powerResults;
|
||||
const inflectionResults = state.inflectionSearchResults;
|
||||
return <div className="width-limiter">
|
||||
<Helmet>
|
||||
<title>LingDocs Pashto Dictionary</title>
|
||||
</Helmet>
|
||||
{(state.user && (window.location.pathname !== "/word") && suggestionState === "none" && powerResults === undefined) && <button
|
||||
{(state.user && (window.location.pathname !== "/word") && suggestionState === "none" && inflectionResults === undefined) && <button
|
||||
type="button"
|
||||
className={`btn btn-outline-secondary bg-white entry-suggestion-button${state.options.searchBarPosition === "bottom" ? " entry-suggestion-button-with-bottom-searchbar" : ""}`}
|
||||
onClick={startSuggestion}
|
||||
>
|
||||
<i className="fas fa-plus" style={{ padding: "3px" }} />
|
||||
</button>}
|
||||
{(powerResults === undefined && suggestionState === "none" && window.location.pathname === "/search") && <button
|
||||
{(inflectionResults === undefined && suggestionState === "none" && window.location.pathname === "/search") && <button
|
||||
type="button"
|
||||
className={`btn btn-outline-secondary bg-white conjugation-search-button${state.options.searchBarPosition === "bottom" ? " conjugation-search-button-with-bottom-searchbar" : ""}`}
|
||||
onClick={handlePowerSearch}
|
||||
onClick={handleInflectionSearch}
|
||||
>
|
||||
<i className={inflectionSearchIcon} style={{ padding: "3px" }} />
|
||||
</button>}
|
||||
{powerResults === "searching" && <div>
|
||||
{inflectionResults === "searching" && <div>
|
||||
<p className="lead mt-1">Searching conjugations/inflections... <i className="fas fa-hourglass-half" /></p>
|
||||
</div>}
|
||||
{Array.isArray(powerResults) && <div>
|
||||
{Array.isArray(inflectionResults) && <div>
|
||||
<h4 className="mt-1 mb-3">Conjugation/Inflection Results</h4>
|
||||
{powerResults.length === 0 && <div className="mt-4">
|
||||
{inflectionResults.length === 0 && <div className="mt-4">
|
||||
<div>No conjugation/inflection matches found for <strong>{state.searchValue}</strong></div>
|
||||
</div>}
|
||||
{powerResults.map((p) => (
|
||||
{inflectionResults.map((p) => (
|
||||
<div key={p.entry.ts}>
|
||||
<Entry
|
||||
key={p.entry.i}
|
||||
|
@ -103,11 +102,11 @@ function Results({ state, isolateEntry, handlePowerSearch }: {
|
|||
isolateEntry={isolateEntry}
|
||||
/>
|
||||
<div className="mb-3 ml-2">
|
||||
{p.results.map((result: InflectionSearchResult, i) => (
|
||||
<InflectionSearchResultDisplay
|
||||
key={"inf-result" + i}
|
||||
{p.forms.map((form, i) => (
|
||||
<InflectionFormMatchDisplay
|
||||
key={"inf-form" + i}
|
||||
textOptions={textOptions}
|
||||
result={result}
|
||||
form={form}
|
||||
entry={p.entry}
|
||||
/>
|
||||
))}
|
||||
|
@ -115,7 +114,7 @@ function Results({ state, isolateEntry, handlePowerSearch }: {
|
|||
</div>
|
||||
))}
|
||||
</div>}
|
||||
{powerResults === undefined && suggestionState === "none" && state.results.map((entry) => (
|
||||
{inflectionResults === undefined && suggestionState === "none" && state.results.map((entry) => (
|
||||
<Entry
|
||||
key={entry.i}
|
||||
entry={entry}
|
||||
|
@ -199,7 +198,7 @@ function Results({ state, isolateEntry, handlePowerSearch }: {
|
|||
Thanks for the help!
|
||||
</div>
|
||||
}
|
||||
{(((powerResults === undefined) && suggestionState === "none" && state.searchValue && (!state.results.length))) && <div>
|
||||
{(((inflectionResults === undefined) && suggestionState === "none" && state.searchValue && (!state.results.length))) && <div>
|
||||
<h5 className="mt-2">No Results Found in {state.options.language}</h5>
|
||||
{state.options.language === "Pashto" && isPashtoScript(state.searchValue) && <p className="mt-3">
|
||||
Click on the <i className={inflectionSearchIcon} /> to search inflections and conjugations
|
||||
|
|
|
@ -11,7 +11,7 @@ export type State = {
|
|||
reviewTasks: import("./functions-types").ReviewTask[],
|
||||
dictionaryInfo: import("@lingdocs/pashto-inflector").Types.DictionaryInfo | undefined,
|
||||
user: undefined | import("./account-types").LingdocsUser,
|
||||
powerResults: undefined | "searching" | PowerResult[],
|
||||
inflectionSearchResults: undefined | "searching" | InflectionSearchResult[],
|
||||
}
|
||||
|
||||
export type DictionaryAPI = {
|
||||
|
@ -160,13 +160,13 @@ export type PluralInflectionName = "plural" | "2nd";
|
|||
// for each form
|
||||
// the possible matches, and their person/inflection number
|
||||
|
||||
export type PowerResult = {
|
||||
entry: import("@lingdocs/pashto-inflector").Types.DictionaryEntry,
|
||||
results: InflectionSearchResult[],
|
||||
};
|
||||
|
||||
export type InflectionSearchResult = {
|
||||
form: string[],
|
||||
entry: import("@lingdocs/pashto-inflector").Types.DictionaryEntry,
|
||||
forms: InflectionFormMatch[],
|
||||
}
|
||||
|
||||
export type InflectionFormMatch = {
|
||||
path: string[],
|
||||
matches: {
|
||||
ps: import("@lingdocs/pashto-inflector").Types.PsString,
|
||||
pos: InflectionName[] | import("@lingdocs/pashto-inflector").Types.Person[] | null,
|
||||
|
|
Loading…
Reference in New Issue