sparna-git / Sparnatural

Sparnatural : visual knowledge graph explorer with SPARQL, in the browser, configurable with SHACL
http://sparnatural.eu
GNU Lesser General Public License v3.0
224 stars 41 forks source link

"Tree Widget" : widget to select a value in a tree #147

Closed tfrancart closed 2 years ago

tfrancart commented 4 years ago

Use-case : select inside a thesaurus. To be combined with an autocomplete to search inside the ConceptScheme.

tfrancart commented 4 years ago

Also : this implies potentially activating query expansion to also search on all descendant concepts of the selected one. This could be done either in the query ( ?x dct:subject/(skos:broader|skos:narrower)* http://concept.uri) or by fetching and injecting all concept values in the query beforehand.

tfrancart commented 4 years ago

Also : it would be good to disable values in the tree if the value is never used in the data

tfrancart commented 4 years ago

See ResearchSpace : https://demo.researchspace.org/resource/Search then search "Thing has type Concept" then click on icon "browse full hierarchy". try opening tree, or searching for "bro"

What is needed is:

plus : add an option "activate autoposting yes/no" (= check all descendants boxes) ("étendre la recherche")

tooltip avec l'URI

tfrancart commented 4 years ago

Use JSTree : https://www.jstree.com/docs/json/

Screenshot of the ResearchSpace tree

image

tfrancart commented 4 years ago

La propriété de l'arborescence doit pouvoir être configurable (pas seulement skos:broader / narrower)

antoine37120 commented 2 years ago

@tfrancart Voici dans la doc la structure de données attendue :

// Alternative format of the node (id & parent are required)
{
  id          : "string" // required
  parent      : "string" // required
  text        : "string" // node text
  icon        : "string" // string for custom
  state       : {
    opened    : boolean  // is the node open
    disabled  : boolean  // is the node disabled
    selected  : boolean  // is the node selected
  },
  li_attr     : {}  // attributes for the generated LI node
  a_attr      : {}  // attributes for the generated A node
}

Et il y a effectivement bien la possibilité de charger les enfants d'un terme avec la fonction open_node (obj [, callback, animation]) :

$('#tree').jstree({
'core' : {
  'data' : {
    'url' : function (node) {
      return node.id === '#' ?
        'ajax_roots.json' :
        'ajax_children.json';
    },
    'data' : function (node) {
      return { 'id' : node.id };
    }
  }
});

Reste à voir si on peut intégrer la donnée du nombre de termes enfant dans les données du terme parent. Je n'est pas l'assurance que la méthode disable_node n'empèchera pas de selctionner le terme. reste donc à voir comment sera géré le cas des termes sans enfants.

antoine37120 commented 2 years ago

@tfrancart Dans les spécifications pour ce widget nous avons prévu une recherche plein texte. Ce n'est pas compatible avec l'idée de charger le contenu de l'arborescence au fur et à mesure que l'on déplit les éléments. Laissons nous la recherche plein texte ?

antoine37120 commented 2 years ago

Il y a aussi le fait de sélectionner tous les descendants lorsque l'on sélectionne un élément. Cela va nous poser problème si on limite la sélection à 3 valeurs.

tfrancart commented 2 years ago

Laissons tomber cette recherche plein texte pour l’instant.

Hier j’ai commité la nouvelle valeur de type de widget TREE_PROPERTY, tu peux faire un update.

Thomas

Le sam. 12 févr. 2022 à 12:55, antoine37120 @.***> a écrit :

@tfrancart https://github.com/tfrancart Dans les spécifications pour ce widget nous avons prévu une recherche plein texte. Ce n'est pas compatible avec l'idée de charger le contenu de l'arborescence au fur et à mesure que l'on déplit les éléments. Laissons nous la recherche plein texte ?

— Reply to this email directly, view it on GitHub https://github.com/sparna-git/Sparnatural/issues/147#issuecomment-1037178311, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAU2H4JUHP52JFUATVKBNPLU2ZDEDANCNFSM4LEI3EQQ . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub.

You are receiving this because you were mentioned.Message ID: @.***>

--

Thomas Francart - SPARNA Web de données | Architecture de l'information | Accès aux connaissances blog : blog.sparna.fr, site : sparna.fr, linkedin : fr.linkedin.com/in/thomasfrancart tel : +33 (0)6.71.11.25.97, skype : francartthomas

tfrancart commented 2 years ago

Le sam. 12 févr. 2022 à 13:00, antoine37120 @.***> a écrit :

Il y a aussi le fait de sélectionner tous les descendants lorsque l'on sélectionne un élément. Cela va nous poser problème si on limite la sélection à 3 valeurs.

Dans un premier temps laisse tomber ça. On pourra le remettre après, mais le principe est que même si l’arbre affiche que les descendants sont cochés, en réalité seul l’item initialement coché doit apparaître comme valeur dans le critère.

C’est la requête sparql qui étend automatiquement la recherche aux descendants.

Reply to this email directly, view it on GitHub https://github.com/sparna-git/Sparnatural/issues/147#issuecomment-1037181439, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAU2H4JZMPLPOM2MUYFGS3TU2ZDT7ANCNFSM4LEI3EQQ . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub.

You are receiving this because you were mentioned.Message ID: @.***>

--

Thomas Francart - SPARNA Web de données | Architecture de l'information | Accès aux connaissances blog : blog.sparna.fr, site : sparna.fr, linkedin : fr.linkedin.com/in/thomasfrancart tel : +33 (0)6.71.11.25.97, skype : francartthomas

antoine37120 commented 2 years ago

@tfrancart Parfait, merci

antoine37120 commented 2 years ago

@tfrancart Un premier commit pour intégrer le la librairie jstree avec un premier exemple pour dev de son utilisation avec Personne => Mouvement. Le chargement différé pour les termes enfants fonctionne. 2 fichiers servent à charger les données en ajax dans /dist/stubs/. un premier pour les termes en root et l'autre pour les enfants du 3ème terme en root "Root node 3". Pour ce terme, le json correspondant est : { "id" : "ajson3", "parent" : "#", "text" : "Root node 3", "count":6 } Au moment du succés de la requête ajax, les données reçues sont traitées pour ajouter une propriété à l'élément et modifier son label si celui ci contient des enfants. Voici le code correspondant :

'success' : function(data) {
    for (var i = 0; i < data.length; i++) {
        if(data[i].count > 0) {
            data[i].children = true ;
            data[i].text += ' ('+data[i].count+')' ;
        } 
    }
    return data ;
}

Je pense que ce sera plus simple pour tout le monde de seulement fournir un count qui soit ensuite pris en compte par le composant lui même pour gérer la propriéte children. On peut ajouter une fonction dans SparqlTreeHandler pour ce traitement. Ici, est aussi ajouté le nombre d'enfants à la fin du label. A toi de me dire si c'est souhaitable.

Je me suis inspirer de ce qu'il y avait dans le fichier AutocompleteAndListHandlers.js pour créer TreeHandler.js Les fonctions `treeRootUrl(), treeChildsUrl sont utilisées par le widget pour charger les données.

Je vais continuer d'ici demain sur le design de ce widget pour ajouter les éléments d'interaction et essayer de faire en sorte que les données sélectionnées puisse être prises en compte dans la requête.

tfrancart commented 2 years ago

Merci. Si tu peux te concentrer sur l'intégration graphique pour vendredi, ca permettrait de le montrer:

  1. Mettre l'arbre dans son menu, avec ouverture par le bouton.

image

  1. Pouvoir valider une valeur

image

  1. Ajouter les valeurs dans la ligne du critère

Pour le count, ca me va. Il y a un autre aspect à prendre en compte pour les noeuds: on va vouloir rendre certains noeuds disabled dans le cas où on sait qu'aucun objet a cette valeur. Peux-tu prévoir ce comportement dans les données de test ?

antoine37120 commented 2 years ago

Pour le count, ca me va. Il y a un autre aspect à prendre en compte pour les noeuds: on va vouloir rendre certains noeuds disabled dans le cas où on sait qu'aucun objet a cette valeur. Peux-tu prévoir ce comportement dans les données de test ?

@tfrancart tu peux voir cela en exemple dans ce dernier commit. Dans les données en json ça donne "exist" : "disabled". Mais à quoi préfererais tu que cela ressemble (nom de la clef et type de valeur. Ce pourrait être aussi "found" : false "found" : true. Tu me diras pour le formalisme.

antoine37120 commented 2 years ago

@tfrancart Pour le reste, cela me parait réalisable, on se fait un point demain après midi ?

tfrancart commented 2 years ago

Utilisons simplement "disabled" : true. Si la clé n'est pas présente ou est à fausse, par défaut tous les noeuds sont actifs.

antoine37120 commented 2 years ago

@tfrancart Donc voici pour le design et interactions. Reste la sélection à traiter pour ajouter les valeurs sur la ligne.

antoine37120 commented 2 years ago

@tfrancart L'ajout des valeurs dans le critère y est aussi maintenant !

antoine37120 commented 2 years ago

Et une petite correction pour que les uris apparaissent bien dans la requête Sparql

tfrancart commented 2 years ago

Excellent merci pour tout ça. Voilà déjà quelques retours de test:

  1. petit overlap du bouton et de l'arbre

image

  1. Quand on sélectionne un noeud, il faut voir visuellement que les fils sont cochés, mais par contre dans l'ajout du critère dans la ligne, seul le concept effectivement coché doit apparaitre, pas tous ses fils:

image

En fait, non je crois que ca ne marche pas. Tout simplement il ne faut pas sélectionner automatiquement les fils du noeud coché dans l'arbre, sinon on va avoir trop de problèmes. Je verrai dans un second temps.

  1. Quand on clique sur le "+" pour ajouter une valeur, est-ce que tu penses qu'on pourrait ouvrir directement l'arbre ? plutôt que d'avoir à cliquer sur l'icône ? ce n'est peut-être pas possible car c'est un comportement générique quel que soit le widget

image

antoine37120 commented 2 years ago

@tfrancart je viens d'ajouter des vraie données de test pour la démo, ainsi on vois de vraies uri dan requête et ça marche !

Oui, pour le petit décalage. Il était sur les maquette alors j'ai fait pareil mais ok c'est modifié.

J'ai trouvé une autre fonction pour récupérer seulement les parent sélectionnés des termes aussi sélectionnés.

Tu peux re tester

antoine37120 commented 2 years ago

Et du coup avec ce dernier commit le widget n'est pas remit à zéro si on souhaite ajouter d'autres valeurs ultérieurement. Les éléments déjà sélectionnés sont toujours cochés.

tfrancart commented 2 years ago

Merci Antoine. Pour le décalage, oui c'est vrai il était sur les maquettes mais avec la zone de search qui était en haut. Sans la zone de search ca fait bizarre.

  1. Peux-tu faire la zone de l'arbre un peu plus haute ? on va vite se sentir à l'étroit. Ou mieux, je ne sais pas si c'est possible, mais qu'elle s'agrandisse quand on déplie l'arbre, jusqu'à une hauteur max.
  2. Enlève la sélection des noeuds fils du noeuds cliqué. Sinon ca va être confus
  3. Il faudrait trouver le moyen de bloquer le nombre de sélection dans l'arbre au nombre maximum de valeurs autorisées dans le critère. Y compris quand il y a déjà un critère et qu'on a cliqué sur le "+"

Sinon c'est déjà effectivement très très cool, il ne reste déjà quasiment plus qu'à brancher les données !

tfrancart commented 2 years ago

Ha oui mais avec ce derni commit ca peut poser des soucis : sélectionne 2 valeurs dans l'arbre, puis dans le critère tu enlève la première valeur, et tu cliques sur le "+" : la première valeur est toujours sélectionée dans l'arbre.

tfrancart commented 2 years ago
  1. Quand on clique sur le "+" pour réafficher l'arbre, et qu'on sélectionne ou qu'on désélectionne une valeur, réinitialiser l'ensemble des valeurs sélectionnées dans la ligne du critère

  2. Désélectionner les valeurs cochées dans l'arbre lorsqu'on fait un remove de valeur dans la ligne du critère

  3. Limiter le nombre de noeuds cochés au nombre de valeurs du critères

  4. Traitement pour la sélection automatique des enfants :

    • Quand on sélectionne un noeud qui a des enfants, alors sélectionner automatiquement tous ses descendants (= toute la branche en dessous)
    • Et désactiver tous sens enfants
    • Quand on réouvre l'arbre, et qu'on désélectionne une valeur alors qu'on en avait sélectionné le maximum, alors précéder en 2 temps :
      1. Réactiver tous les autres noeuds
      2. Déclencher la désactivation de tous les descendants des noeuds cochés
tfrancart commented 2 years ago

Prévoir un comportement par défaut si la requête de remplissage de l'arbre ne ramène aucun résultat. Mettre un mesage:

tfrancart commented 2 years ago

@antoine37120 J'ai un sérieux problème : jsTree essaie d'insérer directement le JSON renvoyé par le serveur dans son arbre. Je n'ai pas de moyen de modifier le JSON renvoyé pour le mettre dans le bon format attendu. Donc pour l'instant je ne vois pas comment faire rentrer les résultats SPARQL dans le jsTree...

Dans tes tests les fichiers JSON statiques ont déjà la structure attendue par JsTree. Mais essaie avec une structure différente que tu devrais transformer, et tu va voir que ça coince...

tfrancart commented 2 years ago

I lva probablement falloir passer par la 3ème option "using a function" (décrite dans la doc : https://www.jstree.com/docs/json/) et faire l'appel Ajax nous-même pour intercaler l'étape de transformation du résultat SPARQL en JSON de JSTree.

tfrancart commented 2 years ago

@antoine37120 Donc finalement... ca marche :-) tu peux faire un update de ton côté.

antoine37120 commented 2 years ago
  1. Quand on clique sur le "+" pour réafficher l'arbre, et qu'on sélectionne ou qu'on désélectionne une valeur, réinitialiser l'ensemble des valeurs sélectionnées dans la ligne du critère
  2. Désélectionner les valeurs cochées dans l'arbre lorsqu'on fait un remove de valeur dans la ligne du critère

@tfrancart Les points 1 et 2 sont commités, tu peux tester ;-)

antoine37120 commented 2 years ago
  1. Limiter le nombre de nœuds cochés au nombre de valeurs du critères.
  2. Traitement pour la sélection automatique des enfants :

@tfrancart pour ce troisième et quatrième point, c'est bon aussi. Concernant l'éventuel chargement d'éléments enfants si on ouvre un item, une fois l'item ouvert, est vérifié si nous somme déjà à la sélection max et dans cette condition les nouveaux nœuds sont désactivés. Le cas d'un nœud déjà désactivé (lors du chargement) est bien pris en compte. J'ai pas mal joué avec et ne voit pas de cas ou ça ne marche pas. A toi d'essayer !

antoine37120 commented 2 years ago

@tfrancart Et dis moi, il ne reste qu'a gérer les cas ou il n'y aurait rien à afficher dans l'arbre ?

antoine37120 commented 2 years ago

@tfrancart du nouveau la aussi pour :

Prévoir un comportement par défaut si la requête de remplissage de l'arbre ne ramène aucun résultat. Mettre un mesage:

  • fr: "Aucune donnée trouvée pour cet arbre..."
  • en: "No data could be found for this tree..."
antoine37120 commented 2 years ago

Et l'action add Or value déclenche directement l'affichage de l'arbre au lieu d'avoir à recliquer sur l'icon.

tfrancart commented 2 years ago

@antoine37120 il faut ajouter une croix de fermeture du dialogue de l'arbre pour le fermer quand on veut.

tfrancart commented 2 years ago

Comportement bizarre : je déplie l'arbre "Peintre par siècle > Peintre francais du XXème siècle" et je sélectionne "Yves Klein" : Le noeud "Yves Klein" devient disabled. Il devrait rester normal, et ses descendants devraient être disabled :

image

Et quand je valide ma sélection, c'est le noeud parent "Peintre du XXeme siècle" qui est sélectionné, pas Yves Klein, ca c'est embetant...

Pour le reste, ca me semble bon

antoine37120 commented 2 years ago

@tfrancart ces deux derniers points sont faits.

tfrancart commented 2 years ago

C'est tout bon, je merge et je ferme, merci