docs+client/users: document user filtering

This commit is contained in:
rr- 2016-04-14 19:37:05 +02:00
parent f34e83b325
commit 286df9faf3
10 changed files with 526 additions and 403 deletions

200
API.md
View File

@ -77,11 +77,11 @@ data.
## Listing users
**Request**
- **Request**
`GET /users/?page=<page>&pageSize=<page-size>&query=<query>`
**Output**
- **Output**
```json5
{
@ -101,47 +101,53 @@ data.
...where `<user>` is an [user resource](#user) and `query` contains standard
[search query](#search).
**Errors**
- **Errors**
- privileges are too low
**Description**
- **Description**
Searches for users.
Available search named tokens:
**Anonymous tokens**
| name | ranged? | array? |
| ----------------- | ------- | ------ |
| (anonymous) | | ✓ |
| `name` | | ✓ |
| `creation-date` | ✓ | ✓ |
| `creation-time` | ✓ | ✓ |
| `last-login-date` | ✓ | ✓ |
| `last-login-time` | ✓ | ✓ |
| `login-date` | ✓ | ✓ |
| `login-time` | ✓ | ✓ |
Same as `name` token.
Anonymous search tokens are equivalent to `name` token.
**Named tokens**
Available search orders:
| `<value>` | Description |
| ----------------- | ------------------------------------------------ |
| `name` | having given name (doesn't accept wildcards yet) |
| `creation-date` | registered at given date |
| `creation-time` | alias of `creation-date` |
| `last-login-date` | whose most recent login date matches given date |
| `last-login-time` | alias of `last-login-date` |
| `login-date` | alias of `last-login-date` |
| `login-time` | alias of `last-login-date` |
- `random`
- `name`
- `creation-date`
- `creation-time`
- `last-login-date`
- `last-login-time`
- `login-date`
- `login-time`
**Order tokens**
| `<value>` | Description |
| ----------------- | -------------------------- |
| `random` | as random as it can get |
| `name` | A to Z |
| `creation-date` | newest to oldest |
| `creation-time` | alias of `creation-date` |
| `last-login-date` | recently active first |
| `last-login-time` | alias of `last-login-date` |
| `login-date` | alias of `last-login-date` |
| `login-time` | alias of `last-login-date` |
**Special tokens**
None.
## Creating user
**Request**
- **Request**
`POST /users`
**Input**
- **Input**
```json5
{
@ -151,7 +157,7 @@ Available search orders:
}
```
**Output**
- **Output**
```json5
{
@ -160,29 +166,29 @@ Available search orders:
```
...where `<user>` is an [user resource](#user).
**Errors**
- **Errors**
- such user already exists (names are case insensitive)
- either user name, password or email are invalid
- privileges are too low
**Description**
- **Description**
Creates a new user using specified parameters. Names and passwords must match
`user_name_regex` and `password_regex` from server's configuration,
respectively. Email address is optional. If the user happens to be the first
user ever created, they're granted highest available rank, becoming an
administrator. Subsequent users will be given the rank indicated by
Creates a new user using specified parameters. Names and passwords must
match `user_name_regex` and `password_regex` from server's configuration,
respectively. Email address is optional. If the user happens to be the
first user ever created, they're granted highest available rank, becoming
an administrator. Subsequent users will be given the rank indicated by
`default_rank` in the server's configuration.
## Updating user
**Request**
- **Request**
`PUT /user/<name>`
**Input**
- **Input**
```json5
{
@ -194,11 +200,11 @@ administrator. Subsequent users will be given the rank indicated by
}
```
**Files**
- **Files**
- `avatar` - the content of the new avatar.
**Output**
- **Output**
```json5
{
@ -207,7 +213,7 @@ administrator. Subsequent users will be given the rank indicated by
```
...where `<user>` is an [user resource](#user).
**Errors**
- **Errors**
- the user does not exist
- the user with new name already exists (names are case insensitive)
@ -217,23 +223,24 @@ administrator. Subsequent users will be given the rank indicated by
- privileges are too low
- avatar is missing for manual avatar style
**Description**
- **Description**
Updates an existing user using specified parameters. Names and passwords must
match `user_name_regex` and `password_regex` from server's configuration,
respectively. All fields are optional - update concerns only provided fields.
To update last login time, see [authentication](#authentication). Avatar style
can be either `gravatar` or `manual`. `manual` avatar style requires client to
pass also `avatar` file - see [file uploads](#file-uploads) for details.
Updates an existing user using specified parameters. Names and passwords
must match `user_name_regex` and `password_regex` from server's
configuration, respectively. All fields are optional - update concerns only
provided fields. To update last login time, see
[authentication](#authentication). Avatar style can be either `gravatar` or
`manual`. `manual` avatar style requires client to pass also `avatar`
file - see [file uploads](#file-uploads) for details.
## Getting user
**Request**
- **Request**
`GET /user/<name>`
**Output**
- **Output**
```json5
{
@ -242,70 +249,71 @@ pass also `avatar` file - see [file uploads](#file-uploads) for details.
```
...where `<user>` is an [user resource](#user).
**Errors**
- **Errors**
- the user does not exist
- privileges are too low
**Description**
- **Description**
Retrieves information about an existing user.
## Removing user
**Request**
- **Request**
`DELETE /user/<name>`
**Output**
- **Output**
```json5
{}
```
**Errors**
- **Errors**
- the user does not exist
- privileges are too low
**Description**
- **Description**
Deletes existing user.
## Password reset - step 1: mail request
**Request**
- **Request**
`GET /password-reset/<email-or-name>`
**Output**
- **Output**
```
{}
```
**Errors**
- **Errors**
- the user does not exist
- the user hasn't provided an email address
**Description**
- **Description**
Sends a confirmation email to given user. The email contains link containing a
token. The token cannot be guessed, thus using such link proves that the person
who requested to reset the password also owns the mailbox, which is a strong
indication they are the rightful owner of the account.
Sends a confirmation email to given user. The email contains link
containing a token. The token cannot be guessed, thus using such link
proves that the person who requested to reset the password also owns the
mailbox, which is a strong indication they are the rightful owner of the
account.
## Password reset - step 2: confirmation
**Request**
- **Request**
`POST /password-reset/<email-or-name>`
**Input**
- **Input**
```json5
{
@ -313,7 +321,7 @@ indication they are the rightful owner of the account.
}
```
**Output**
- **Output**
```json5
{
@ -321,16 +329,16 @@ indication they are the rightful owner of the account.
}
```
**Errors**
- **Errors**
- the token is missing
- the token is invalid
- the user does not exist
**Description**
- **Description**
Generates a new password for given user. Password is sent as plain-text, so it
is recommended to connect through HTTPS.
Generates a new password for given user. Password is sent as plain-text, so
it is recommended to connect through HTTPS.
@ -354,29 +362,39 @@ is recommended to connect through HTTPS.
# Search
Nomenclature:
Search queries are built of tokens that are separated by spaces. Each token can
be of following form:
- Tokens - search terms inside a query, separated by white space.
- Anonymous tokens - tokens of form `<value>`, used to filter the search
results.
- Named tokens - tokens of form `<key>:<value>`, used to filter the search
results.
- Special tokens - tokens of form `special:<value>`, used to filter the search
results.
- Order tokens - tokens of form `order:<value>`, used to sort the search
results.
| Syntax | Token type | Description |
| ----------------- | ----------------- | ------------------------------------------ |
| `<value>` | anonymous tokens | basic filters |
| `<key>:<value>` | named tokens | advanced filters |
| `order:<style>` | order tokens | sort results |
| `special:<value>` | special tokens | filters usually tied to the logged in user |
Features:
Most of anonymous and named tokens support ranged and composite values that
take following form:
- Most tokens can be negated like so: `-token`. Used with order tokens, it
flips the sort direction.
- Some tokens support multiple values like so: `3,4,5`.
- Some tokens support ranges like so: `100..`, `..200`, `100..200`.
- Date token values can contain following values: `today`, `yesterday`,
`<year>`, `<year>-<month>`, `<year>-<month>-<day>`.
- Order token values can be appended with `,asc` and `,desc` suffixes, which
control the sort direction.
| `<value>` | Description |
| --------- | ----------------------------------------------------- |
| `a,b,c` | will show things that satisfy either `a`, `b` or `c`. |
| `1..` | will show things that are equal to or greater than 1. |
| `..4` | will show things that are equal to at most 4. |
| `1..4` | will show things that are equal to 1, 2, 3 or 4. |
Example how it works:
Date/time values can be of following form:
haruhi -kyon fav-count:3.. order:fav-count,desc -special:liked
- `today`
- `yesterday`
- `<year>`
- `<year>-<month>`
- `<year>-<month>-<day>`
**Example**
Searching for posts with following query:
sea -fav-count:8.. type:swf uploader:Pirate
will show flash files tagged as sea, that were liked by seven people at most,
uploaded by user Pirate.

View File

@ -17,6 +17,10 @@ form
margin-bottom: 1em
.buttons
margin-top: 1em
a
margin-left: 1em
.fa-question-circle-o
font-size: 120%
.input li:first-child label:not(.radio):not(.checkbox):not(.file-dropper),
.input li:first-child
padding-top: 0

View File

@ -1,11 +1,17 @@
@import colors
#help
width: 40em
nav
margin-bottom: 1.5em
td
padding-right: 1em
td, th
padding: 0 0.5em
&:first-child
white-space: pre
.section
margin-top: 2em
h1
margin-top: 2.5em
font-size: 1.6em
&:first-child
margin-top: 0

View File

@ -12,6 +12,9 @@ h1, h2, h3
font-weight: normal
margin-bottom: 1em
th
font-weight: normal
a
color: $main-color
text-decoration: none

View File

@ -24,11 +24,6 @@
margin: 0 0 0.5em 0
#login
.buttons a
margin-left: 1em
#user
width: 30em
.text-nav
@ -99,6 +94,6 @@
.user-list-header
text-align: left
form
max-width: auto
width: auto
input[name=search-text]
max-width: 15em

View File

@ -1,265 +1,345 @@
<h1>General search syntax</h1>
<p>Search queries are built of tokens that are separated by spaces. Each token
can be of following form:</p>
<table>
<thead>
<tr>
<th>Command</th>
<th>Syntax</th>
<th>Token type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><a href='/posts/query=Haruhi'><code>Haruhi</code></a></td>
<td>containing tag “Haruhi”</td>
<td><code>&lt;value&gt;</code></td>
<td>anonymous tokens</td>
<td>basic filters</td>
</tr>
<tr>
<td><a href='/posts/query=-Kyon'><code>-Kyon</code></a></td>
<td>not containing tag “Kyon”</td>
<td><code>&lt;key&gt;:&lt;value&gt;</code></td>
<td>named tokens</td>
<td>advanced filters</td>
</tr>
<tr>
<td><a href='/posts/query=uploader:David'><code>uploader:David</code></a></td>
<td>uploaded by user David</td>
<td><code>order:&lt;style&gt;</code></td>
<td>order tokens</td>
<td>sort results</td>
</tr>
<tr>
<td><a href='/posts/query=comment:David'><code>comment:David</code></a></td>
<td>commented by David</td>
</tr>
<tr>
<td><a href='/posts/query=fav:David'><code>fav:David</code></a></td>
<td>favorited by David</td>
</tr>
<tr>
<td><a href='/posts/query=fav-count:4'><code>fav-count:4</code></a></td>
<td>favorited by exactly four users</td>
</tr>
<tr>
<td><a href='/posts/query=fav-count:4,5'><code>fav-count:4,5</code></a></td>
<td>favorited by four or five users</td>
</tr>
<tr>
<td><a href='/posts/query=fav-count:4..'><code>fav-count:4..</code></a></td>
<td>favorited by at least four users</td>
</tr>
<tr>
<td><a href='/posts/query=fav-count:..4'><code>fav-count:..4</code></a></td>
<td>favorited by at most four users</td>
</tr>
<tr>
<td><a href='/posts/query=fav-count:4..6'><code>fav-count:4..6</code></a></td>
<td>favorited by at least four, but no more than six users</td>
</tr>
<tr>
<td><a href='/posts/query=comment-count:3'><code>comment-count:3</code></a></td>
<td>having exactly three comments</td>
</tr>
<tr>
<td><a href='/posts/query=score:4'><code>score:4</code></a></td>
<td>having score of 4</td>
</tr>
<tr>
<td><a href='/posts/query=tag-count:7'><code>tag-count:7</code></a></td>
<td>tagged with exactly seven tags</td>
</tr>
<tr>
<td><a href='/posts/query=note-count:1..'><code>note-count:1..</code></a></td>
<td>having at least one post note</td>
</tr>
<tr>
<td><a href='/posts/query=feature-count:1..'><code>feature-count:1..</code></a></td>
<td>having been featured at least once</td>
</tr>
<tr>
<td><a href='/posts/query=date:today'><code>date:today</code></a></td>
<td>posted today</td>
</tr>
<tr>
<td><a href='/posts/query=date:yesterday'><code>date:yesterday</code></a></td>
<td>posted yesterday</td>
</tr>
<tr>
<td><a href='/posts/query=date:2000'><code>date:2000</code></a></td>
<td>posted in year 2000</td>
</tr>
<tr>
<td><a href='/posts/query=date:2000-01'><code>date:2000-01</code></a></td>
<td>posted in January, 2000</td>
</tr>
<tr>
<td><a href='/posts/query=date:2000-01-01'><code>date:2000-01-01</code></a></td>
<td>posted on January 1st, 2000</td>
</tr>
<tr>
<td><a href='/posts/query=id:1'><code>id:1</code></a></td>
<td>having specific post ID</td>
</tr>
<tr>
<td><a href='/posts/query=name:hash'><code>name:<em>hash</em></code></a></td>
<td>having specific post name (hash in full URLs)</td>
</tr>
<tr>
<td><a href='/posts/query=file-size:100..'><code>file-size:100..</code></a></td>
<td>having at least 100 bytes</td>
</tr>
<tr>
<td><a href='/posts/query=image-width:100..'><code>image-width:100..</code></a></td>
<td>being at least 100 pixels wide</td>
</tr>
<tr>
<td><a href='/posts/query=image-height:100..'><code>image-height:100..</code></a></td>
<td>being at least 100 pixels tall</td>
</tr>
<tr>
<td><a href='/posts/query=image-area:10000..'><code>image-area:10000..</code></a></td>
<td>having at least 10000 pixels</td>
</tr>
<tr>
<td><a href='/posts/query=type:image'><code>type:image</code></a></td>
<td>only image posts</td>
</tr>
<tr>
<td><a href='/posts/query=type:flash'><code>type:flash</code></a></td>
<td>only Flash posts</td>
</tr>
<tr>
<td><a href='/posts/query=type:youtube'><code>type:youtube</code></a></td>
<td>only Youtube posts</td>
</tr>
<tr>
<td><a href='/posts/query=type:video'><code>type:video</code></a></td>
<td>only video posts</td>
</tr>
<tr>
<td><a href='/posts/query=special:liked'><code>special:liked</code></a></td>
<td>posts liked by currently logged in user</td>
</tr>
<tr>
<td><a href='/posts/query=special:disliked'><code>special:disliked</code></a></td>
<td>posts disliked by currently logged in user</td>
</tr>
<tr>
<td><a href='/posts/query=special:fav'><code>special:fav</code></a></td>
<td>posts added to favorites by currently logged in user</td>
</tr>
<tr>
<td><a href='/posts/query=special:tumbleweed'><code>special:tumbleweed</code></a></td>
<td>posts with score of 0, without comments and without favorites</td>
<td><code>special:&lt;value&gt;</code></td>
<td>special tokens</td>
<td>filters usually tied to the logged in user</td>
</tr>
</tbody>
</table>
<p>Most of the commands support ranged and composites values, e.g.
<code>id:<em>number</em></code> operator supports respectively
<a href='/posts/query=id:5..7'><code>id:5..7</code></a> and
<a href='/posts/query=id:5,10,15'><code>id:5,10,15</code></a>.
You can combine tags and negate any of them for interesting results.
<a href='/posts/query=sea -fav-count:..8 type:flash uploader:Pirate'><code>sea -fav-count:8.. type:swf uploader:Pirate</code></a>
will show you flash files tagged as sea, that were liked by seven people at
most, uploaded by user Pirate.</p>
<p>All of the above can be sorted using additional tag in form of
<code>order:<em>keyword</em></code>:</p>
<p>Most of anonymous and named tokens support ranged and composite values that
take following form:</p>
<table>
<thead>
<tr>
<th>Command</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><a href='/posts/query=order:random'><code>order:random</code></a></td>
<td><code>a,b,c</code></td>
<td>will show things that satisfy either <code>a</code>,
<code>b</code> or <code>c</code>.</td>
</tr>
<tr>
<td><code>1..</code></td>
<td>will show things that are equal to or greater than 1.</td>
</tr>
<tr>
<td><code>..4</code></td>
<td>will show things that are equal to at most 4.</td>
</tr>
<tr>
<td><code>1..4</code></td>
<td>will show things that are equal to 1, 2, 3 or 4.</td>
</tr>
</tbody>
</table>
<p>Date/time values can be of following form:</p>
<ul>
<li><code>today</code></li>
<li><code>yesterday</code></li>
<li><code>&lt;year&gt;</code></li>
<li><code>&lt;year&gt;-&lt;month&gt;</code></li>
<li><code>&lt;year&gt;-&lt;month&gt;-&lt;day&gt;</code></li>
</ul>
<p>All tokens can be negated by prepending them with <code>-</code>.</p>
<p>Order token values can be appended with <code>,asc</code> or
<code>,desc</code> to control the sort direction, which can be also controlled
by negating the whole token.</p>
<h1>Example</h1>
<p>Searching for posts with following query:</p>
<pre><code>sea -fav-count:8.. type:swf uploader:Pirate</code></pre>
<p>will show flash files tagged as sea, that were liked by seven people at
most, uploaded by user Pirate.</p>
<h1 id='post-search-help'>Post search tokens</h1>
<p><strong>Anonymous tokens</strong></p>
<p>Filter posts tagged with given <code>&lt;value&gt;</code>.</p>
<p><strong>Named tokens</strong></p>
<table>
<tbody>
<tr>
<td><code>id</code></td>
<td>having specific post ID</td>
</tr>
<tr>
<td><code>score</code></td>
<td>having given score</td>
</tr>
<tr>
<td><code>uploader</code></td>
<td>uploaded by given user</td>
</tr>
<tr>
<td><code>comment</code></td>
<td>commented by given user</td>
</tr>
<tr>
<td><code>fav</code></td>
<td>favorited by given user</td>
</tr>
<tr>
<td><code>fav-count</code></td>
<td>favorited by given number of users</td>
</tr>
<tr>
<td><code>comment-count</code></td>
<td>having given number of comments</td>
</tr>
<tr>
<td><code>tag-count</code></td>
<td>having given number of tags</td>
</tr>
<tr>
<td><code>note-count</code></td>
<td>having given number of annotations</td>
</tr>
<tr>
<td><code>feature-count</code></td>
<td>having been featured given number of times</td>
</tr>
<tr>
<td><code>date</code></td>
<td>posted at given date</td>
</tr>
<tr>
<td><code>file-size</code></td>
<td>having given file size (in bytes)</td>
</tr>
<tr>
<td><code>image-width</code></td>
<td>having given image width (where applicable)</td>
</tr>
<tr>
<td><code>image-height</code></td>
<td>having given image height (where applicable)</td>
</tr>
<tr>
<td><code>image-area</code></td>
<td>having given number of pixels (image width * image height)</td>
</tr>
<tr>
<td><code>type</code></td>
<td>given type of posts (<code>&lt;value&gt;</code> can be either <code>image</code>, <code>flash</code>/<code>swf</code>, <code>youtube</code>/<code>yt</code>, <code>video</code> or <code>animation</code>)</td>
</tr>
</tbody>
</table>
<p><strong>Order tokens</strong></p>
<table>
<tbody>
<tr>
<td><code>random</code></td>
<td>as random as it can get</td>
</tr>
<tr>
<td><a href='/posts/query=order:id'><code>order:id</code></a></td>
<td>highest to lowest post ID (default browse view)</td>
<td><code>id</code></td>
<td>highest to lowest post ID</td>
</tr>
<tr>
<td><a href='/posts/query=order:creation-date'><code>order:creation-date</code></a></td>
<td>newest to oldest (pretty much same as above)</td>
</tr>
<tr>
<td><a href='/posts/query=-order:creation-date'><code>-order:creation-date</code></a></td>
<td>oldest to newest</td>
</tr>
<tr>
<td><a href='/posts/query=order:creation-date,asc'><code>order:creation-date,asc</code></a></td>
<td>oldest to newest (ascending order, default = descending)</td>
</tr>
<tr>
<td><a href='/posts/query=order:edit-date'><code>order:edit-date</code></a></td>
<td>like <code>creation-date</code>, only looks at last edit time</td>
</tr>
<tr>
<td><a href='/posts/query=order:score'><code>order:score</code></a></td>
<td><code>score</code></td>
<td>highest scored</td>
</tr>
<tr>
<td><a href='/posts/query=order:file-size'><code>order:file-size</code></a></td>
<td>largest files first</td>
</tr>
<tr>
<td><a href='/posts/query=order:image-width'><code>order:image-width</code></a></td>
<td>widest images first</td>
</tr>
<tr>
<td><a href='/posts/query=order:image-height'><code>order:image-height</code></a></td>
<td>tallest images first</td>
</tr>
<tr>
<td><a href='/posts/query=order:image-area'><code>order:image-area</code></a></td>
<td>largest images first</td>
</tr>
<tr>
<td><a href='/posts/query=order:tag-count'><code>order:tag-count</code></a></td>
<td>with most tags</td>
</tr>
<tr>
<td><a href='/posts/query=order:fav-count'><code>order:fav-count</code></a></td>
<td><code>fav-count</code></td>
<td>loved by most</td>
</tr>
<tr>
<td><a href='/posts/query=order:comment-count'><code>order:comment-count</code></a></td>
<td><code>comment-count</code></td>
<td>most commented first</td>
</tr>
<tr>
<td><a href='/posts/query=order:fav-date'><code>order:fav-date</code></a></td>
<td>recently added to favorites</td>
<td><code>tag-count</code></td>
<td>with most tags</td>
</tr>
<tr>
<td><a href='/posts/query=order:comment-date'><code>order:comment-date</code></a></td>
<td>recently commented</td>
<td><code>note-count</code></td>
<td>with most annotations</td>
</tr>
<tr>
<td><a href='/posts/query=order:feature-date'><code>order:feature-date</code></a></td>
<td><code>file-size</code></td>
<td>largest files first</td>
</tr>
<tr>
<td><code>image-width</code></td>
<td>widest images first</td>
</tr>
<tr>
<td><code>image-height</code></td>
<td>tallest images first</td>
</tr>
<tr>
<td><code>image-area</code></td>
<td>largest images first</td>
</tr>
<tr>
<td><code>creation-date</code></td>
<td>newest to oldest (pretty much same as <code>id</code>)</td>
</tr>
<tr>
<td><code>edit-date</code></td>
<td>like <code>creation-date</code>, only looks at last edit time</td>
</tr>
<tr>
<td><code>fav-date</code></td>
<td>recently added to favorites by anyone</td>
</tr>
<tr>
<td><code>comment-date</code></td>
<td>recently commented by anyone</td>
</tr>
<tr>
<td><code>feature-date</code></td>
<td>recently featured</td>
</tr>
<tr>
<td><a href='/posts/query=order:feature-count'><code>order:feature-count</code></a></td>
<td><code>feature-count</code></td>
<td>most often featured</td>
</tr>
</tbody>
</table>
<p>As shown with <a
href='/posts/query=-order:creation-date'><code>-order:creation-date</code></a>,
any of them can be reversed in the same way as negating other tags: by placing
a dash before the tag.</p>
<p><strong>Special tokens</strong></p>
<table>
<tbody>
<tr>
<td><code>liked</code></td>
<td>posts liked by currently logged in user</td>
</tr>
<tr>
<td><code>disliked</code></td>
<td>posts disliked by currently logged in user</td>
</tr>
<tr>
<td><code>fav</code></td>
<td>posts added to favorites by currently logged in user</td>
</tr>
<tr>
<td><code>tumbleweed</code></td>
<td>posts with score of 0, without comments and without favorites</td>
</tr>
</tbody>
</table>
<h1 id='user-search-help'>User search tokens</h1>
<p><strong>Anonymous tokens</strong></p>
<p>Same as <code>name</code> token.</p>
<p><strong>Named tokens</strong></p>
<table>
<tbody>
<tr>
<td><code>name</code></td>
<td>having given name (doesn't accept wildcards yet)</td>
</tr>
<tr>
<td><code>creation-date</code></td>
<td>registered at given date</td>
</tr>
<tr>
<td><code>creation-time</code></td>
<td>alias of <code>creation-date</code></td>
</tr>
<tr>
<td><code>last-login-date</code>
<td>whose most recent login date matches given date</td>
</tr>
<tr>
<td><code>last-login-time</code>
<td>alias of <code>last-login-date</code>
</tr>
<tr>
<td><code>login-date</code>
<td>alias of <code>last-login-date</code>
</tr>
<tr>
<td><code>login-time</code></td>
<td>alias of <code>last-login-date</code>
</tr>
</tbody>
</table>
<p><strong>Order tokens</strong></p>
<table>
<tbody>
<tr>
<td><code>random</code></td>
<td>as random as it can get</td>
</tr>
<tr>
<td><code>name</code></td>
<td>A to Z</td>
</tr>
<tr>
<td><code>creation-date</code></td>
<td>newest to oldest</td>
</tr>
<tr>
<td><code>creation-time</code></td>
<td>alias of <code>creation-date</code></td>
</tr>
<tr>
<td><code>last-login-date</code></td>
<td>recently active first</td>
</tr>
<tr>
<td><code>last-login-time</code></td>
<td>alias of <code>last-login-date</code></td>
</tr>
<tr>
<td><code>login-date</code></td>
<td>alias of <code>last-login-date</code></td>
</tr>
<tr>
<td><code>login-time</code></td>
<td>alias of <code>last-login-date</code></td>
</tr>
</tbody>
</table>
<p><strong>Special tokens</strong></p>
<p>None.</p>

View File

@ -5,7 +5,7 @@
<meta name='viewport' content='width=device-width, initial-scale=1.0'>
<title><!-- confiured in config file --></title>
<link href='/bundle.min.css' rel='stylesheet' type='text/css'/>
<link href='//maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css' rel='stylesheet' type='text/css'/>
<link href='//maxcdn.bootstrapcdn.com/font-awesome/4.6.0/css/font-awesome.min.css' rel='stylesheet' type='text/css'/>
<link href='//fonts.googleapis.com/css?family=Droid+Sans' rel='stylesheet' type='text/css'/>
<link rel='shortcut icon' type='image/png' href='/favicon.png'/>
</head>

View File

@ -9,6 +9,7 @@
</div>
<div class='buttons'>
<input type='submit' value='Search'/>
<a href='/help/search#user-search-help'><i class='fa fa-question-circle-o'></i></a>
</div>
</form>
</div>

View File

@ -126,6 +126,19 @@ function showView(target, source) {
}
}
function scrollToHash() {
window.setTimeout(() => {
if (!window.location.hash) {
return;
}
const el = document.getElementById(
window.location.hash.replace(/#/, ''));
if (el) {
el.scrollIntoView();
}
}, 10);
}
module.exports = {
htmlToDom: htmlToDom,
getTemplate: getTemplate,
@ -137,4 +150,5 @@ module.exports = {
decorateValidator: decorateValidator,
makeVoidElement: makeVoidElement,
makeNonVoidElement: makeNonVoidElement,
scrollToHash: scrollToHash,
};

View File

@ -38,6 +38,8 @@ class HelpView {
views.listenToMessages(target);
views.showView(target, source);
views.scrollToHash();
}
}