/** * Copyright (c) 2021 lingdocs.com * * This source code is licensed under the GPL3 license found in the * LICENSE file in the root directory of this source tree. * */ import { useEffect, useState } from "react"; import classNames from "classnames"; import { Link } from "react-router-dom"; import { VPExplorer } from "@lingdocs/ps-react"; import { entryFeeder } from "../lib/dictionary"; import { InflectionsTable, inflectWord, Types as T, InlinePs, validateEntry, typePredicates, } from "@lingdocs/ps-react"; import Entry from "../components/Entry"; import * as FT from "../types/functions-types"; import { submissionBase, addSubmission } from "../lib/submissions"; import { Helmet } from "react-helmet"; import { TextOptions } from "@lingdocs/ps-react/dist/types"; import * as AT from "../types/account-types"; import { DictionaryAPI } from "../types/dictionary-types"; import { ErrorBoundary } from "react-error-boundary"; const textFields: { field: T.DictionaryEntryTextField; label: string }[] = [ { field: "p", label: "Pashto" }, { field: "f", label: "Phonetics" }, { field: "e", label: "English" }, { field: "c", label: "Part of Speech" }, { field: "infap", label: "1st Masc. Irreg. Inflect. P" }, { field: "infaf", label: "1st Masc. Irreg. Inflect. F" }, { field: "infbp", label: "2nd Irreg. Inflect. Base P" }, { field: "infbf", label: "2nd Irreg. Inflect. Base F" }, { field: "app", label: "Arabic Plural P" }, { field: "apf", label: "Arabic Plural F" }, { field: "ppp", label: "Pashto Plural P" }, { field: "ppf", label: "Pashto Plural F" }, { field: "psp", label: "Imperf. Stem P" }, { field: "psf", label: "Imperf. Stem F" }, { field: "ssp", label: "Perf. Stem P" }, { field: "ssf", label: "Perf. Stem F" }, { field: "prp", label: "Perf. Root P" }, { field: "prf", label: "Perf. Root F" }, { field: "pprtp", label: "Past Part. P" }, { field: "pprtf", label: "Past Part. F" }, { field: "tppp", label: "3rd Pers. Masc. Sing P." }, { field: "tppf", label: "3rd Pers. Masc. Sing F." }, { field: "ec", label: "English Verb Conjugation" }, { field: "ep", label: "English Verb Particle" }, ]; const booleanFields: { field: T.DictionaryEntryBooleanField; label: string }[] = [ { field: "noInf", label: "no inflection" }, { field: "shortIntrans", label: "short intrans" }, { field: "noOo", label: "no oo prefix" }, { field: "sepOo", label: "sep. oo prefix" }, { field: "diacExcept", label: "diacritics except." }, ]; const numberFields: { field: T.DictionaryEntryNumberField; label: string }[] = [ { field: "l", label: "link" }, { field: "separationAtP", label: "seperation at P" }, { field: "separationAtF", label: "seperation at F" }, ]; function OneField(props: { value: string | number | undefined; field: { field: T.DictionaryEntryField; label: string | JSX.Element }; errored?: boolean; handleChange: (e: React.ChangeEvent) => void; }) { return (
); } function EntryEditor({ isolatedEntry, dictionary, searchParams, textOptions, user, }: { isolatedEntry: T.DictionaryEntry | undefined; textOptions: TextOptions; dictionary: DictionaryAPI; searchParams: URLSearchParams; user: AT.LingdocsUser | undefined; // removeFromSuggestions: (sTs: number) => void, }) { const [entry, setEntry] = useState( isolatedEntry ?? { ts: 0, i: 0, p: "", f: "", g: "", e: "" } ); const [matchingEntries, setMatchingEntries] = useState( isolatedEntry ? searchForMatchingEntries(isolatedEntry.p) : [] ); const [erroneusFields, setErroneousFields] = useState< T.DictionaryEntryField[] >([]); const [errors, setErrors] = useState([]); const [submitted, setSubmitted] = useState(false); const [deleted, setDeleted] = useState(false); const [willDeleteSuggestion, setWillDeleteSuggestion] = useState(true); const comment = searchParams.get("comment"); const sTsString = searchParams.get("sTs"); const sTs = sTsString && sTsString !== "0" ? parseInt(sTsString) : undefined; const suggestedWord = searchParams.get("p") || searchParams.get("f") ? { p: searchParams.get("p") || "", f: searchParams.get("f") || "", } : undefined; useEffect(() => { setEntry(isolatedEntry ?? { ts: 1, i: 0, p: "", f: "", g: "", e: "" }); setMatchingEntries( isolatedEntry ? searchForMatchingEntries(isolatedEntry.p) : [] ); // eslint-disable-next-line }, [isolatedEntry]); function searchForMatchingEntries(s: string): T.DictionaryEntry[] { return dictionary .exactPashtoSearch(s) .filter((w) => w.ts !== isolatedEntry?.ts); } function handleInputChange(event: React.ChangeEvent) { const target = event.target; const value = target.type === "checkbox" ? target.checked : target.value; const name = target.name; setEntry({ ...entry, [name]: value && numberFields.find((x) => x.field === name) && typeof value === "string" ? parseInt(value) : value, }); if (erroneusFields.length) setErroneousFields([]); if (name === "f" || name === "p") { setMatchingEntries(searchForMatchingEntries(value as string)); } } function handleDelete() { if (!user) return; const submission: FT.EntryDeletion = { ...submissionBase(user), type: "entry deletion", ts: entry.ts, }; addSubmission(submission, user); setDeleted(true); } function handleSubmit(e: any) { setErroneousFields([]); setErrors([]); e.preventDefault(); if (!user) return; const result = validateEntry(entry); if ("errors" in result) { setErroneousFields(result.erroneousFields); setErrors(result.errors); return; } // TODO: Check complement if checkComplement const submission: FT.NewEntry | FT.EntryEdit = { ...submissionBase(user), type: entry.ts === 1 ? "new entry" : "entry edit", entry: { ...entry, ts: entry.ts === 1 ? Date.now() : entry.ts }, }; addSubmission(submission, user); setSubmitted(true); // TODO: Remove from suggestions // if (willDeleteSuggestion && sTs) { // removeFromSuggestions(sTs); // } } const complement = entry.l ? dictionary.findOneByTs(entry.l) : undefined; const inf = ((): T.InflectorOutput | false => { try { return inflectWord(entry); } catch (e) { console.error("error inflecting entry", entry); return false; } })(); const linkField: { field: "l"; label: string | JSX.Element } = { field: "l", label: ( <> link{" "} {entry.l ? ( complement ? ( ) : ( "not found" ) ) : ( "" )} ), }; return (
Edit - LingDocs Pashto Dictionary {isolatedEntry && ( null} /> )} {suggestedWord && } {comment &&

Comment: "{comment}"

} {submitted ? ( "Edit submitted/saved" ) : deleted ? ( "Entry Deleted" ) : (
{matchingEntries.length > 0 && (
Matching Entries: {matchingEntries.map((entry) => (
))}
)}
{[textFields[0]].map((field) => ( ))}
{[textFields[1]].map((field) => ( ))}
{[textFields[2]].map((field) => ( ))}
{[textFields[3]].map((field) => ( ))}
{[numberFields[0]].map((field) => ( ))}
{textFields.slice(4, 13).map((field) => ( ))} {numberFields.slice(1).map((field) => ( ))}
{textFields.slice(12, 23).map((field) => ( ))}
{booleanFields.map((field) => (
))}
{sTs && (
setWillDeleteSuggestion(e.target.checked)} />
)}
{errors.length > 0 && (
    {errors.map((error) => (
  • {error}
  • ))}
)} {inf && inf.inflections && ( )} {inf && "plural" in inf && inf.plural !== undefined && ( )} {inf && "arabicPlural" in inf && inf.arabicPlural !== undefined && ( )} {/* TODO: aay tail from state options */} {typePredicates.isVerbEntry({ entry, complement }) && (
Error conjugating verb}>
)}
)}
); } export default EntryEditor;