Uitgebreid Zoeken

From A-Eskwiki
Revision as of 21:22, 20 March 2019 by Timb (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search


In het nieuwe Uitgebreid Zoeken kunnen gebruikers hun eigen kwerries samenstellen door sleuren en pleuren. Dit wordt dan op de server omgezet tot een SQL-query, die op de database uitgevoerd wordt, en waarvoor vervolgens de juiste weergave gekozen wordt. De zoekkwerrie wordt overgestuurd als een JSON-object, als een soort fancy s-expressie.

Front-end: sleuren en pleuren

We gebruiken de Javascriptlibrary HTML5 Dropzone, die een fijne wrapper geeft om de sleur-en-pleurfunctionaliteit in HTML5. Je hebt hier een niet al te antieke browser voor nodig dus. Voor elk soort item die de gebruiker in de query kan doen, maken we een template aan (iets met class "zoek-item"), die de gebruiker kan kopiëren naar gaten (iets met class "zoek-gat") in de query. Deze gaten worden dan gevuld met (maar niet vervangen door) kopietjes van dit item. In dit item mogen ook weer gaten voorkomen, bijvoorbeeld voor de "EN"- en "OF"-operatoren. Omdat we gaten niet vervangen, hebben we ook replacement-functionaliteit: wil je een item vervangen met een ander item, dan pleur je het nieuwe item over het andere item heen. De eventhandlers van het gat zorgen ervoor dat de vervanging goedgaat. De hele state van de query wordt in de structuur van de html-elementen opgeslagen, zodat er niets gedesynct wordt. Een nadeel is dat je niet al te veel fancy's kunt doen met de opmaak, want we gaan ervan uit dat de kwerrie eruit ziet als een .zoek-gat-element met als (direct) kind precies 1 .zoek-root-element, met als (direct) kind een aantal .zoek-gat-elementen, etc. In feite is de hele structuur niets meer dan een s-expressie met pretentie.

De notatie die we nu gaan aanhouden: als je een item hebt met een paar (oningevulde) gaten, schrijven we die op als (zoektype ? ? ... ?), en als er een paar gaten zijn ingevuld, wordt het bijvoorbeeld (en (of (vakid) ?) (niet (actief)))

Op dit moment werkt het verplaatsen van al geplaatste items nog niet heel netjes: bij het pleuren wordt namelijk alleen een nieuw item gemaakt van de wortel van hetgeen wat je sleept. Een kopie van (en (vakid) (actief)) ziet er dus uit als (en ? ?), niet (en (vakid) (actief)).

Om formvelden binnen items te ondersteunen (denk aan "lid sinds <datum>"), kunnen items ook een dict attrs van extra waarden, naast de invulling van gaten, meedragen. In de HTML worden deze weergegeven als attributen van de vorm data-zoek-*, zodat data-zoek-bla overeenkomt met een key bla in de attrs. Je moet in Javascript ervoor zorgen dat deze bij elke update van het formveld dit in de attributen geupdate wordt.

Serialisatie

Als de gebruiker vervolgens op de zoekknop drukt, wordt een geserialiseerde kwerrie opgestuurd. Op basis van de HTML wordt een JSON-object gemaakt dat de zoekkwerrie encodeert. Omdat de structuur om en om bestaat uit gat met misschien een item, en item met een lijst gaten, doen we ook twee serialisatiestappen in mutuele recursie. Een gat serialiseert tot ofwel de serialisatie van het item dat erinzit, ofwel null. Een item serialiseert tot een JSON-object van de vorm {'head': ... , 'tail': ... , 'attrs': ...}. De head is het zoektype van dit item ('en' voor de logische conjunctieoperator, 'vakid', etc.), de tail is een lijst van alle (geserialiseerde) gaten van dit item (inclusief null voor oningevulde!), en de attrs zijn een dict met strings, de extra attributen (zoals de waarden van inputs in dit zoekitem).

Zo wordt bijvoorbeeld de s-expressie:

(of (vakid) (en (actiefCie) (niet (actiefAlles))))

geserialiseerd naar:

{"head":"of","tail":[{"head":"vakid","tail":[],"attrs":{}},{"head":"en","tail":[{"head":"actiefCie","tail":[],"attrs":{}},{"head":"niet","tail":[{"head":"actiefAlles","tail":[],"attrs":{}}],"attrs":{}}],"attrs":{}}],"attrs":{}}

TODO: voorbeeld met attributen

Itemsoorten

De volgende itemsoorten worden ondersteund:

Zoektype Gaten Attributen Betekenis
en 2 {} conjunctie: (en l r) bestaat uit de doorsnede van iedereen in l en iedereen in r
of 2 {} disjunctie: (of l r) bestaat uit de vereniging van iedereen in l met iedereen in r
niet 1 {} negatie: (niet q) bestaat uit iedereen die niet in q zit
lidtoestand 0 {'lidtoestand': ...} lidtoestand komt overeen met attrs.lidtoestand: 'lid': "gewoon" huidig lid of BAL; 'oudlid': vroeger, maar niet meer, lid; 'bijnalid': heeft zich ingeschreven voor de intro maar is nog niet lid geworden; 'bal': Bijzonder Actief Lid (staat bij huidige leden, niet bij oudleden); 'erelid': erelid (staat niet bij huidige leden); 'verdienste': lid van verdienste (staat niet bij huidige leden).
studeert 0 {'studie': ...} doet op dit moment de gegeven studie. attrs.studie is het ID van een Studie-object in de database.
studeerde 0 {'studie': ...} studeerde vroeger, niet meer, de gegeven studie. Zie studeert voor info over attrs.studie.
studieOnbekend 0 {} geen studiegegevens bekend
vakidPost 0 {} heeft aangegeven de Vakidioot per post te willen ontvangen
aesRoots 0 {} heeft aangegeven de A–Eskwadraat√roots te willen ontvangen
actiefCie 0 {} is actief in een commissie
actiefAlles 0 {} is actief in een commissie, groep of dispuut
actiefRecent 0 {} is, of was afgelopen jaar, actief in een commissie, groep of dispuut
deelnemer 0 {} staat bij de deelnemers voor een activiteit afgelopen jaar
adresBekend 0 {} adres bekend in de database
emailBekend 0 {} email bekend in de database
donateur 0 {} is op dit moment donateur
donateurGeweest 0 {} was donateur maar nu niet meer
afgestudeerd 0 {'coljaar': ...} afgestudeerd in attrs.coljaar. Collegejaren worden gegeven als string van het jaar waarin ze beginnen, dus '2017' is 3 sept 2017 - 3 sept 2018.
almaOK 0 {} willen opgenomen worden in de almanak
geluksvogel 0 {} jonger dan 18 jaar
kart 0 {} zit in de kart van de gebruiker
lidVan 0 {'coljaar': ...} lid geworden in attrs.coljaar. Collegejaren worden gegeven als string van het jaar waarin ze beginnen, dus '2017' is 3 sept 2017 - 3 sept 2018.
lidTot 0 {'coljaar': ...} lid-af in attrs.coljaar. Collegejaren worden gegeven als string van het jaar waarin ze beginnen, dus '2017' is 3 sept 2017 - 3 sept 2018.
voornaamwoord 0 {'voornaamwoordID': ...} gebruikt persoonlijk voornaamwoord met ID attrs.voornaamwoordID.
bounces 0 {} heeft bounces: e-mails die door de site zijn verstuurd maar niet zijn aangekomen