Open russellmorley opened 1 year ago
Hi @gerfen
question: Do the "v" characters represent the sorting direction on the columns?
Answer: Yes, they are sorted columns and the 'v' represents sort direction.
question: Is "add as form for..." literal?
answer: yes it is literal, with nothing else. It means add this source in the UIImport as the form for (which when clicked, goes to the LexiconEditUI) this (the picked) lexeme.
@romanpoz First phase up through '8(a) Import UI' has been merged into DEV branch. Development continues with '8(b) LexiconEditUI', which was a stretch goal for release 1.2.
1. Story
Users need a way to import lexicon and gloss related information from drafting tools like paratext so they don't need to double enter them into both systems and so auto-glossing results in Dashboard can be made even better, quickly and with less effort.
Because imported data needs to be 'scrubbed' in some cases, users need a user interface to perform this function. To reduce the number of UIs users must learn, increase UI consistency, and reduce development costs, the user interface for this function can, and should, do 'double duty', serving in both the scrub function and the general lexicon view/edit function of Dashboard.
While the existing PINs tool attempts to enable users to view lexicon data, it is flawed -- mixing dissimilar data elements in a common view resulting in duplicated information that is inconsistent, it only provides a view over paratext data and does not otherwise integrate with Dashboard's data, and its codebase is not maintainable.
This design proposes providing these benefits to users in three phases, bringing meaningful value to users as rapidly as possible then building upon it in logical steps, one on 'top' of the other : bring data in from paratext so users don't have to enter it again, provide a way for users to scrub it, then provide a consistent, logical way for users to view and edit the lexicon within Dashboard so they can more clearly understand the target language and at the same time build a body of translation knowledge about it to empower future translation and quality checking work.
2. Dependencies
This feature works in conjunction with [this feature], the latter of which provides users with the ability to break down Tokens in Dashboard to a level that matches the data imported from Paratext.
3. Phases
4. Trigger
Dashboard menu option 'import lexicon from paratext project' triggers LexiconImportViewModel
5. Workflow
6. 2.Import data into memory
6(a) Interface:
6(a)(i) Plugin CQRS Query
ParatextPlugin
GetLexiconQueryController
(signalr controller)GetLexiconQueryHandler : ParatextRequestHandler<GetLexiconQuery, RequestResult<Lexicon>, Lexicon>
Implementation uses instance ofLexiconFromXmlFiles : ILexiconObtainable
ParatextPlugin.CQRS/Features/Lexicon/
GetLexiconQuery : IRequest<RequestResult<Lexicon>>
ClearDashboard.DAL.Features/Lexicion/
GetLexiconQueryHandler : ParatextRequestHandler<GetLexiconQuery, RequestResult<Lexicon> ,Lexicon>
GetLexiconQuery : IRequest<RequestResult<Lexicon>>
6(a)(ii) DB CQRS Query
ClearDashboard.DAL.Alignment/Features/Lexicon
GetLexiconQueryHandler : ProjectDbContextCommandHandler<GetLexiconQuery, RequestResult<Lexicon>,Lexicon>
GetLexiconQuery : IRequest<RequestResult<Lexicon>>
6(b) class
LexiconFromXmlFiles : ILexiconObtainable
implementation6(b)(i) Paratext lexicon info
provides
Contained in
Example of data
Sense Id is used as gloss id in interlinear files. Believe sense can be viewed as a 'meaning', in our terminology, with each gloss under it corresponding to a translation. In the case of paratext it appears there is only one translation per sense, language pair, which is different than Dashboard's which supports more than one translation per meaining (i.e. synonyms).
6(b)(ii) Paratext BiblicalTerms info
provides
Contained in
Looks like data is extracted from 1->3, where terms from lower number take precedence over higher numbers, e.g. for a term in both 2 and 3 the entry in 2 is used.
Hebrew/Greek -> English extracted from
<gloss>
element, when present.Renderings
Biblical terms
<Term Id="Δέρβη">
id links to termsrederings<TermRendering Id="Δέρβη" Guess="false">
id.Hebrew/Greek -> Translation extracted from
<Renderings>
element when<TermRendering Id="Δέρβη" Guess="false">
guess=false.7. 3(a)Select and save data into lexicon: Phase 1: import and save only imported entries that don't match any lexeme, form, or translation
7(a) Manager
abstractions/services/LexiconManager
usesClearDashboard.ParatextPlugin.CQRS.Features.GetLexiconQuery
to obtain the lexicon from paratext andClearDashboard.DAL.Alignment.Features.Lexicon.GetLexiconQuery
to obtain lexicon from the database. Would be nice to remove the ParatextPlugin hardcoding from this so this can be extended to other drafting tools without having to change this code7(a)(i) New Methods:
public Lexicon GetExternalLexiconNotInInternal(Lexicon externalLexicion, Lexicon internalLexicon)
returnsexternalLexicon.WHERE(el => InternalLexicon..Count(il => il.lexeme == el.lexeme) == 0 && InternalLexicon..Count(il => il.lexeme in el.forms) == 0 && InternalLexicon..Count(il => il.translations.Intersect(el.translations).Count() > 0) == 0)
public void Save(Lexicon lexicon)
7(b) LexiconImportViewModel
private Lexicon GetExternalLexiconNotInInternal(Lexicon externalLexicion, Lexicon internalLexicon)
returnsexternalLexicon.WHERE(el => InternalLexicon..Count(il => il.lexeme == el.lexeme) == 0 && InternalLexicon..Count(il => il.lexeme in el.forms) == 0 && InternalLexicon..Count(il => il.translations in el.translations) == 0)
7(c) Data model enhancements
7(c)(i) New field on
Translation
entityjson OriginatedFrom
(or can be xml) that contains:7(d)(i) New field for lexeme/form
type
7(e) implementation
Menu trigger LexiconImportViewModel, which then
ParatextPlugin.CQRS.Features.Lexicon.GetLexiconQuery
to obtain lexicon entries from paratext.LexiconManager.GetExternalLexiconNotInInternal()
to find paratext lexicon entries that don't match entries in Dashboard's lexicon.LexiconMnager.Save()
.8. Select and save data into lexicon, Phase 2
8(a) Import UI
Mockup
[Button: Import checked (A)]
LexiconManager.GetExternalLexiconNotInInternal()
pre-checkedLexiconMnager.Save()
to save entries checked then dismisses dialog.externalLexicon.WHERE(el => InternalLexicon.Count(il => il.translations.Intersect(el.translations).Count() > 0) > 0)
LexiconEditUI((sourceLanguage, targetLanguage, targetWord, MatchOnTranslation, sourceWord)
externalLexicon.WHERE(el => internalLexicon.Count(il => il.lexeme.Contains(el.lexeme) > -1 || il.forms.Contains(el.lexeme)) > 0
LexiconEditUI((sourceLanguage, targetLanguage, sourceWord, PartialMatchOnLexemeOrForm, targetWord)
8(b) LexiconEditUI
Parameters:
sourceLanguage=null targetLanguage=null string toMatch Mode PartialMatchOnLexemeOrForm | MatchOnTranslation | Edit string other
Mockup
[Drop down: Source Language drop down v (A)] [Drop down: Target Language drop down v (B)]
Find all [checkbox: lexeme (C)] [select: partially|fully (D)] [or (E)] [checkbox: forms (F) ] [select: partially|fully (G)] [matching (H)] [textbox:(I)] [select: and | or (J)] [checkbox: translation (K)] fully matching [textbox: (L)]
[Save changes (N)]
LexiconManager.Save(Lexicon lexicon)