Page MenuHomePhabricator

investigate sharing of query builder queries via URL [timebox: 4h]
Closed, ResolvedPublic

Description

Problem:
People share queries a lot. In the Query Service we enable this ba encoding the query in the URL. We need to have something similar for the Query Builder where we can encode specific visual queries in the URL. We need to figure out how to do this.

Existing things worth looking at:

  • Wikidata Query Service
  • Jakob's query builder

Acceptance criteria:

  • we understand the way forward for sharing visual queries via URL
  • we have tickets describing the next steps

Event Timeline

Restricted Application added a subscriber: Aklapper. · View Herald TranscriptNov 1 2020, 1:56 PM
Lydia_Pintscher renamed this task from investigate sharing of query builder queries via URL to investigate sharing of query builder queries via URL [timebox: 4h].Nov 20 2020, 1:25 PM

Came up in the nav summit slightly, I thought the topic was mainly short urls but seemingly its just about the urls in the address bar? ;)
I'll put some links here anyway!

In terms of short URLs:

@Addshore it's mainly about how to encode the visual query in the URL so it can be shared for example for bug reporting

guergana.tzatchkova added a comment.EditedNov 26 2020, 4:40 PM

Jakob's Query Builder shares the visual representation of the query in an encoded json. Example of query for female mayors.

The URL has a query parameter assigned to a json object, the object looks like this:

{
"statements": {
  "item": {
    "item_s_0": {
      "property": {
        "id":"P31/wdt:P279*",
        "label":"instance of"},
        "value":{"id":"Q515",
        "label":"city"}
       },
    "item_s_1":{
      "property":{
        "id":"P6","label":"head of government"},
        "value":{
          "object":"item_s_1",
          "id":"X1",
          "label":
          "any item matching..."}
        }
     },
     "item_s_1":{
        "item_s_1_s_0":{
            "property":{
                "id":"P21",
                "label":"sex or gender"
              },
              "value":{
                 "id":"Q6581072",
                 "label":"female"
                }
              }
            }
         },
     "qualifiers":{},
"select":{
"item":{
  "id":true,
  "label":true,
  "properties": [
   {  
    "id":"P1082",
     "label":"population"
    }
]}},
"limit":""}

The relevant parts of the code where the url is being generated and parsed are here: initializeFromUrl method and generateShareUrl.

generateShareUrl uses the QuerySerializer and initializeFromUrl uses QueryDeserializer.

There are also serializers and deserializer for statements and qualifiers.

guergana.tzatchkova added a comment.EditedNov 26 2020, 4:52 PM

In the Query Service, some of the examples have a somewhat incomplete visual representation. Example of rock band names that start with the letter M

Investigation not finished. TODO: check the Query Service implementation.

guergana.tzatchkova added a comment.EditedNov 30 2020, 5:59 PM

The Query Service uses the QueryHelper implementation to generate the GUI of the Query.

+ QueryHelper

The functions setQuery and getQuery create the Query from the Visual Editor and vice versa.

There is a method to get the i18n labels and put them inside of a span.

The draw function creates the elements from the query:

Triples: It extracts the triples and creates a table row for each triple.
Limit: there is a getLimitSection
Variable: there is an isVariable method

+ SparqlQuery

is used to separate the query into objects for easier processing of the query, some relevant methods are:

getTriples: returns an array with all the triples (only has cases bgp, optional and union.
findSubqueries: selfexplanatory
addTriple: adds a triple to the query
getTripleVariables
getBoundVariables
getServices
getComment: will we use this one? (for comments written in the query. start with #)

+ QueryTemplate

This codes generates templates if the template code is given as part of the query in a comment.

Example:

This query has a template:

#TEMPLATE={"template":"Presidents of ?country and their spouses","variables":{"?country":{"query":" SELECT ?id WHERE { ?id wdt:P31 wd:Q6256 . }"} } }

SELECT ?p ?pLabel ?ppicture ?w ?wLabel ?wpicture WHERE {
  BIND(wd:Q30 AS ?country)
  ?country (p:P6/ps:P6) ?p.
  ?p wdt:P26 ?w.
  OPTIONAL {
    ?p wdt:P18 ?ppicture.
    ?w wdt:P18 ?wpicture.
  }
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". }
}

and looks like this:

guergana.tzatchkova added a comment.EditedNov 30 2020, 6:20 PM

Findings:

Both analyzed projects generate a query representation in a query object that has (at least) these attributes variables, triples, services, limit.

In our codebase a triple is equivalent to a ConditionRow (variable, property, value).

While Jakob's QB sends a custom created object in the URL, the Query Builder Helper encodes the exact query that has been introduced and uses a cookie to verify if the user has the Query Helper open or not.

Thanks for this. Quick question, is there an easy way to store/retrieve Vue state in URL? Like a library that serialize and unserialize it. That would simplify the work a lot.

Thanks for this. Quick question, is there an easy way to store/retrieve Vue state in URL? Like a library that serialize and unserialize it. That would simplify the work a lot.

@Ladsgroup please check: https://phabricator.wikimedia.org/T266960#6651782 , the part after the code.

Just a reminder from user research: Participants love a sharing option; the problem with storing state in URLs is that the data that the URL can carry was, at least for some the handwritten requests, rather limited and people started to code-golf their queries.

@Ladsgroup: Vue state is a magic-ified javascript objects as far as I am concerned so one can probably URL-encode, URL-decode, JSON-parse and then use them in Vue (maybe in some hook or so, not sure exactly where). (The answer is clearer for vue3 since they split the reactivity from the main lib and here your objects and arrays are reactivized by getting the return of ref(yourdata) or reactive(yourdata))

Okay then, I think this investigation is done :)

Lydia_Pintscher closed this task as Resolved.Wed, Jan 13, 8:43 AM