RE-QDA / requal

Free and open-source software for computer-assisted qualitative data analysis
https://www.requal.app
Other
14 stars 1 forks source link

Allow overlaying selections #22

Closed buresj closed 2 years ago

buresj commented 3 years ago

Pokusil jsem se zkopírovat tu vaši základní implementaci, která je tu https://github.com/RE-QDA/requal/blob/main/inst/app/www/document_code_js.js

https://codepen.io/asdfgrewq/pen/KKvwgbO

Zatím jsem nenarazil na ten bug, co jsem viděl v pondělí. Určitě tam bude ale problém s intersecting tags, apod.

Neplechu může dělat tohle, zkusil bych console.log tu selection a pozoroval, co se s ní děje. Přidávání nových spanů může měnit ten parentNode.id.

if(window.getSelection().baseNode.parentNode.id != "document_code_ui_1-focal_text") return;

Neřešil jsem tedy ještě to překrývání výběrů, ale vidím tam možná několik hlubších problémů. Největší je ten, že teď vizualizaci i nosičem dat je přímo to HTML, které není prostě uzpůsobené na manipulaci na úrovni znaků a slov. Nějaká JSON mezivrstava bude možná nutná... Ale zkusím se zamyslet, co s tím a držet se v rámci toho co už máte, tj. bez JSONu, jen s HTML.

buresj commented 3 years ago

FYI @skvrnami @hlageek

hlageek commented 3 years ago

@buresj to vypadá fajn! nebudeme to asi moct převzít úplně, protože nějaké věci z tvé implementace bude pro nás lepší řešit na R-kovém backendu, ale snad to @skvrnami z toho zvládne přiohnout, jak budeme potřebovat. Napadá mě při té příležitosti, že budeme potřebovat i tu "remove" funkci, která by měla odstranit jen vybraný konkrétní <mark> element. A teda zase přepočítat, jak to má vypadat, když najednou bude jeden element chybět. Ale určitě se to tím trochu posunuje dopředu, protože samotné značkování se zdá fungovat bez bugů. Pokud bys věděl, jak zajistit, aby ty funkce fungovaly jen v daným node Id a neposílaly pozice z textu jinde na stránce, tak samozřejmě to by taky bylo dobrý, pokud myslíš, že stávající řešení není nejlepší. Já určitě na naší původní implementaci netrvám :)

buresj commented 3 years ago

Včera jsem také přišel na to, jak ošetřit to překrývání. Dnes se k tomu nedostanu, ale zítra udělám něco jako fullscale mockup toho, jak by takové tagování s překráváním (tj. překryv vytvoří nový <mark>) a odstraňováním výběrů mohlo vypadat. Bude to čistě JS apka - od toho se pak odrazíme k implementaci v Shiny/R.

hlageek commented 3 years ago

nejsem si jistý, že samostatná apka je nejlepší cesta - pro integraci se Shiny by bylo lepší mít JS funkce, které si budeme volat z eRka dle potřeby a s plnou kontrolou. Ale nevím. Možná se tomu bráním jen proto, že JS neumím a samostatná apka bude nejlepší cesta. V každém případě díky za pomoc.

buresj commented 3 years ago

JS apka jsou jen JS funkce :)

hlageek commented 3 years ago

@buresj tak to je samozřejmě fajn, jen když se koukám na současný návrh, tak jsou ty elementy propojené, zatímco my budeme potřebovat, abychom si v Shiny na backendu řešili, jaký tlačítko bude volat jakou funkci. Tak bych jen poprosil, abys s tím při návrhu počítal, že ty funkce by měly být maximálně samostatné a nepředpokládali existenci nějakých elementů. Skrze argumenty bychom mohli funkcím posílat v jakém nodu mají operovat, jaké barvy používat, v případě vymazání jednoho kódu na překryvu dvou a více pošleme info o tom, který kód má zmizet (asi tedy by bylo fajn, aby ty marky měly id nebo jméno podle code id, které přidělujeme na backendu)... a pokud naopak potřebujeme nějaký výstup z JS funkce (např. ty koordináty), tak by bylo hezké mít v komentáři, jaký výstup máme čekat. Ale to je všechno nice to have - když to bude fungovat, tak to už snad nějak zvládneme předělat, aby nám to zapadlo do konceptu aplikace.👍

buresj commented 3 years ago

Nakonec, doporučil bych jít cestou méně chytrého (než koordináty a vkládání <mark> tagů), ale robustnějšího řešení - každé slovo má svoje id a svůj stav. Potom je velmi snadné přepínat stav jednotlivých slov a komunikace mezi backendem a klientem je jasná, protože běží přes JSON.

Na první načtení, klient dostane JSON, který rendruje do HTML. Uživatel pak manipule s HTML, jakákoliv relevantní změna (otagování textu) je poslaná jako malý JSON na server, klient pak přijme JSON s udáji o změně a přerendruje HTML. Takhe je normální architektura single page aplikací, tj. aplikací, kde nedochází k reloadu stránky. Backend vůbec neřeší HTML/DOM.

Tohle není bohužel bez problémů. Za prvé, nejmenším prvkem je slovo :(. Za druhé, je to více náročné na výkon - ale to se dá vyřešit.

Výhoda je "normálnost" implementace, backend je single source of truth, který drží identitu slov a jejich stav, není třeba řešit průniky koordinátů, není třeba složitě manipulovat s DOMem - je se mění stav elementů, nikoliv struktura.

A JS je MNOHEM jednodušší -

Žádné měření pozice kurzoru, nebo vysekávání selectů a klonování mark tagů. Nabízí se pak možnost se zaměřit na zlepšení UX/UI. Např. přidání možnosti přepínat tagy, odstraňovat vrstvy tagů, fulltext search pro hromadné označování. Určitě bych proto doporučil, aby třeba každý výběr byl "kliknutelný" a vyběhlo menu s dalšími možnostmi.

Můžeme se pak pobavit, co a jak ... já jsem se v tom chtěl primárně zorientovat a nastudovat si dostupnou API, teď je otázka, jestli implementace, co navrhuji je pro vás použitelná. Doufám, že jste to nezavrhli, protože právě chcete mít výběry citlivější než slovo...

Tady je to moje technické demo/studie problému. Ten backend request je mockup, teď o průnicích rozhoduje uživatel.

https://github.com/buresj/cross-annotate https://cross-annotate.pages.dev/

martin-hajek commented 3 years ago

Díky @buresj za funkční návrh. Já zde zastupuji uživatelský pohled a návrh je pro mne použitelný.

To jsou moje první dojmy :-)

martin-hajek commented 2 years ago

Budete @buresj ve vývoji pokračovat nebo to byl jen takový výkřik do tmy?

buresj commented 2 years ago

To je dotaz spíše na Radima (@hlageek). Já pouze vystřelil, co můžu zhruba nabídnout, resp. co si myslím, že by byla vhodná implementace.

Nyní záleží jestli to zapadá do plánu/architektury aplikace... Radim totiž chtěl původně pomoci s drobným bugem, já to pojal trochu jinak.

hlageek commented 2 years ago

My jsme dneska se @skvrnami zkouseli nejake veci a v podstate se dostavame k tomu, ze vic a vic toho resime na backendu v R, kde je nam dobre. Zkusili jsme uplne zrusit zvyraznovani pres JavaScript a pri kazdem pridani kodu znovu zobrazujeme cely text. Na osobnim pocitaci si uzivatel ani u rozsahlejsich textu nevsimne, ze se neco stalo. Tak spis smerujeme k reseni, kdy jedine, co budeme po JS chtit, bude ziskavat hlaseni o pozici kurzoru v textu. Reseni od @buresj bych si schoval do zalohy, jen pokud by to zlobilo, a zkusil to na urovni znaku. Mam pocit, ze nam pomohlo nahrazeni <span> tagu za <mark>.

buresj commented 2 years ago

Super, to je dobře, že se podařilo :)

hlaseni o pozici kurzoru v textu.

K tomu jen drobné varování: Obecně se identita neurčuje na klientovi, ale drží se v databazí a je tak neměnná. Pokud budete používat koordináty výběru, tzn. identifikovat výběr na klientovi, tak si pohlídejte, aby se text nezměnil. Pokud přidáte do editovaného dokumentu jeden znak kdekoliv, tak to vlastně rozbije pozici všech výběrů oproti textu.

Další potenciální problém, který jsem tam viděl, byl v tom, že text musí být jednolitý paragraf oddělený <br> tagy pro odstavce. Netuším, jak máte v plánu import dokumentů, ale ověřte si, jestli ten způsob získávání výběrů/pozic kurzoru, funguje napříč odstavci. Nejsem si teď jistý, ale třeba <article><p>par1</p><p>par2</p></article> by vám nemělo jít, ale musíte mít <p>par1<br><br>par2<p>.

Pokud bude cokoliv potřeba, jsem na příjmu.