-
Notifications
You must be signed in to change notification settings - Fork 204
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Query from url #254
Query from url #254
Conversation
Codecov Report
@@ Coverage Diff @@
## master #254 +/- ##
==========================================
+ Coverage 76.16% 76.19% +0.02%
==========================================
Files 117 117
Lines 5811 5817 +6
Branches 950 952 +2
==========================================
+ Hits 4426 4432 +6
Misses 1385 1385
Continue to review full report at Codecov.
|
Hello @greebie ,
Is the reason for this restriction to avoid changing in the I don't think there is anything stopping us from changing the format of the fragment after the initial |
The only reason for this restriction is that this was the existing restriction for #annotations. I can edit to make the alterations to accommodate Q: [a-zA-z_-:] no problem. While we are at it, any concerns about Q: [a-zA-z_:\+-]? This would fix the multi-word query problem as well (replace '+' with whitespace). |
Okay the change in reference should be fixed now. Thanks. The new syntax is https://www.example.com#annotations:(query: or Q:){filter} the filter can include any of user:, tag:, any: or text: |
Hello @greebie - Sorry for taking such a long time to get back to you on this. Would you mind squashing everything down to one commit on your branch? |
Yes. No worries! Will have this done today. |
I've had another read through this, some thoughts:
|
This project enables the user to include a default filter query as part of a url. The syntax works with the #annotations: fragment. If a Q: or Query: (case insensitive) is included, whatever follows the query will be included in a search filter as a default. user tags may be included in this query string. For instance user:USERNAME will filter for the user called USERNAME. Using an @hypothes.is will search for exactly that user. So far, the user, tag or any tags are the main permissible items. So http://www.example.com/path/to/file#annotations:Q:user:USERNAMEtag:TAGany:KEYWORD will filter the page for annotations by USERNAME tagged TAG and containing KEYWORD.
All squished and fixed from my perspective! Thanks for the helpful feedback. Just a note that this commit takes a slightly modified approach to have extractAnnotationQuery return an object. The function now creates a setting variable called "query" that sets the default filter. Thus some minor changes to config and the sidebar. |
filter = null; | ||
} | ||
} catch (err) { | ||
filter = null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What specific error are you trying to guard against here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was just following the previous codebase (function extractURLFromID formerly) I think.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was looking at the code and the only possible error is a URIError which would not be caught by this code. I'll remove the try/catch.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are two tests that fail if the try-catch code is not included, so I kept it in.
var annotationIds = require('../extract-annotation-query'); | ||
|
||
describe('annotation queries', function () { | ||
var annotation = annotationIds.extractAnnotationQuery('http://localhost:3000#annotations:alphanum3ric_-only'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have a utility called unroll
for writing data-driven tests which I think would be useful here. See this test for an example.
var annotation = annotationIds.extractAnnotationQuery('http://localhost:3000#annotations:alphanum3ric_-only'); | ||
var queryVarA = annotationIds.extractAnnotationQuery('http://localhost:3000#annotations:q:user:USERNAME'); | ||
var queryVarB = annotationIds.extractAnnotationQuery('http://localhost:3000#annotations:QuerY:user:USERNAME'); | ||
var invalid = annotationIds.extractAnnotationQuery('http://localhost:3000#annotations:\"TRYINGTOGETIN\";EVILSCRIPT()'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A general comment about these tests is that it is easier to follow if the preparation/arrangement is part of the test case instead of being a separate step that happens in beforeEach
. The exception is if you're using a particular fixture across several test cases. We generally try to follow the 'Arrange Act Assert' formula for structuring individual test cases.
URL queries should now use uri encoded strings for all default filter queries.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tested this with a range of queries and IDs. All looks good. Thank-you!
I left a couple of notes about minor issues which can be addressed separately.
// | ||
// The Chrome extension or proxy may already have provided this config | ||
// via a tag injected into the DOM, which avoids the problem where the page's | ||
// JS rewrites the URL before Hypothesis loads. | ||
// | ||
// In environments where the config has not been injected into the DOM, | ||
// we try to retrieve it from the URL here. | ||
var directLinkedID = annotationIDs.extractIDFromURL(window_.location.href); | ||
var directLinkedID = annotationQuery.extractAnnotationQuery(window_.location.href); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The name of this variable needs an update.
} | ||
|
||
module.exports = { | ||
extractAnnotationQuery: extractAnnotationQuery, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Usually if a module exports a single function then we use module.exports = <function name>
rather than exporting an object with one field.
Thanks Ryan, Robert! This is terrific. |
@adam3smith - The client gets uploaded to a CDN a few minutes after the GitHub release is created. It takes about half an hour to become available after that. It is now available through Via. You may need to clear your browser cache if you don't see it straight away. You can check the version via Account -> Help in the client. The version of the client with this release is v1.4.0. The Chrome extension takes an hour or two to go through malware checks in the Chrome Web Store. |
Note that the PR that automatically activates the extension when a URL contains |
My colleagues at the Qualitative Data Repository requested the ability to link to a specific page and show only a specific user's annotations.
This change provides a solution by using Hypothesis's existing search filter and the "#annotations:" url fragment. By using the url
https://www.example.com#annotations:query__{filter}
The client opens the search filter window and filters the annotations for {filter}, provided that the filter is base64 compliant (alphanumeric, underscore or hyphen only). Including the terms user__USERNAME, any__ANYTHING or tag__ATAG will create the filter for user: USERNAME, any: ANYTHING and tag: ATAG respectively.
So https://www.example.com#annotations:query__user__USERNAMEany__ANYTHING will filter for "user:USERNAME any:ANYTHING."
#Limitations:
The current solution does not support multi-word queries (because % and whitespace are illegal in url fragments). This behavior can be imitated using query__any__WORDany__ANOTHERWORDany__ANDANOTHER.
The syntax was selected to impact the hypothesis architecture as little as possible. A more intuitive solution could be to permit a #filter: fragment instead or even to permit colons directly. This is why the functions to detect the query and prepare the query are separated. Colons are not currently permissible in base64, so I opted for the double-underscore rather than trying to permit something that otherwise hadn't been.
The current syntax will not work in the bouncer. I have a solution for that will be submitted for pull request shortly.