From 286df9faf33edb9e58c82f9beca4e104938d2591 Mon Sep 17 00:00:00 2001 From: rr- <rr-@sakuya.pl> Date: Thu, 14 Apr 2016 19:37:05 +0200 Subject: [PATCH] docs+client/users: document user filtering --- API.md | 398 +++++++++++++------------ client/css/forms.styl | 4 + client/css/help.styl | 16 +- client/css/main.styl | 3 + client/css/users.styl | 7 +- client/html/help-search.hbs | 482 ++++++++++++++++++------------- client/html/index.htm | 2 +- client/html/user_list_header.hbs | 1 + client/js/util/views.js | 14 + client/js/views/help_view.js | 2 + 10 files changed, 526 insertions(+), 403 deletions(-) diff --git a/API.md b/API.md index cacf301..ecc9d06 100644 --- a/API.md +++ b/API.md @@ -77,260 +77,268 @@ data. ## Listing users -**Request** +- **Request** -`GET /users/?page=<page>&pageSize=<page-size>&query=<query>` + `GET /users/?page=<page>&pageSize=<page-size>&query=<query>` -**Output** +- **Output** -```json5 -{ - "query": "rr-", - "users": [ - <user>, - <user>, - <user>, - <user>, - <user> - ], - "page": 1, - "pageSize": 5, - "total": 7 -} -``` -...where `<user>` is an [user resource](#user) and `query` contains standard -[search query](#search). + ```json5 + { + "query": "rr-", + "users": [ + <user>, + <user>, + <user>, + <user>, + <user> + ], + "page": 1, + "pageSize": 5, + "total": 7 + } + ``` + ...where `<user>` is an [user resource](#user) and `query` contains standard + [search query](#search). -**Errors** +- **Errors** -- privileges are too low + - privileges are too low -**Description** +- **Description** -Searches for users. + 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` + `POST /users` -**Input** +- **Input** -```json5 -{ - "name": <user-name>, - "password": <user-password>, - "email": <email> -} -``` + ```json5 + { + "name": <user-name>, + "password": <user-password>, + "email": <email> + } + ``` -**Output** +- **Output** -```json5 -{ - "user": <user> -} -``` -...where `<user>` is an [user resource](#user). + ```json5 + { + "user": <user> + } + ``` + ...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 + - 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 -`default_rank` in the server's configuration. + 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>` + `PUT /user/<name>` -**Input** +- **Input** -```json5 -{ - "name": <user-name>, - "password": <user-password>, - "email": <email>, - "rank": <rank>, - "avatarStyle": <avatar-style> -} -``` + ```json5 + { + "name": <user-name>, + "password": <user-password>, + "email": <email>, + "rank": <rank>, + "avatarStyle": <avatar-style> + } + ``` -**Files** +- **Files** -- `avatar` - the content of the new avatar. + - `avatar` - the content of the new avatar. -**Output** +- **Output** -```json5 -{ - "user": <user> -} -``` -...where `<user>` is an [user resource](#user). + ```json5 + { + "user": <user> + } + ``` + ...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) -- either user name, password, email or rank are invalid -- the user is trying to update their or someone else's rank to higher than - their own -- privileges are too low -- avatar is missing for manual avatar style + - the user does not exist + - the user with new name already exists (names are case insensitive) + - either user name, password, email or rank are invalid + - the user is trying to update their or someone else's rank to higher than + their own + - 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>` + `GET /user/<name>` -**Output** +- **Output** -```json5 -{ - "user": <user> -} -``` -...where `<user>` is an [user resource](#user). + ```json5 + { + "user": <user> + } + ``` + ...where `<user>` is an [user resource](#user). -**Errors** +- **Errors** -- the user does not exist -- privileges are too low + - the user does not exist + - privileges are too low -**Description** +- **Description** -Retrieves information about an existing user. + Retrieves information about an existing user. ## Removing user -**Request** +- **Request** -`DELETE /user/<name>` + `DELETE /user/<name>` -**Output** +- **Output** -```json5 -{} -``` + ```json5 + {} + ``` -**Errors** +- **Errors** -- the user does not exist -- privileges are too low + - the user does not exist + - privileges are too low -**Description** +- **Description** -Deletes existing user. + Deletes existing user. ## Password reset - step 1: mail request -**Request** +- **Request** -`GET /password-reset/<email-or-name>` + `GET /password-reset/<email-or-name>` -**Output** +- **Output** -``` -{} -``` + ``` + {} + ``` -**Errors** +- **Errors** -- the user does not exist -- the user hasn't provided an email address + - 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>` + `POST /password-reset/<email-or-name>` -**Input** +- **Input** -```json5 -{ - "token": <token-from-email> -} -``` + ```json5 + { + "token": <token-from-email> + } + ``` -**Output** +- **Output** -```json5 -{ - "password": <new-password> -} -``` + ```json5 + { + "password": <new-password> + } + ``` -**Errors** +- **Errors** -- the token is missing -- the token is invalid -- the user does not exist + - 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. diff --git a/client/css/forms.styl b/client/css/forms.styl index f6c684b..532b153 100644 --- a/client/css/forms.styl +++ b/client/css/forms.styl @@ -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 diff --git a/client/css/help.styl b/client/css/help.styl index 76db6c1..a2532ac 100644 --- a/client/css/help.styl +++ b/client/css/help.styl @@ -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 diff --git a/client/css/main.styl b/client/css/main.styl index e35ee62..9f8c478 100644 --- a/client/css/main.styl +++ b/client/css/main.styl @@ -12,6 +12,9 @@ h1, h2, h3 font-weight: normal margin-bottom: 1em +th + font-weight: normal + a color: $main-color text-decoration: none diff --git a/client/css/users.styl b/client/css/users.styl index 4d783f5..629fcf6 100644 --- a/client/css/users.styl +++ b/client/css/users.styl @@ -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 diff --git a/client/html/help-search.hbs b/client/html/help-search.hbs index e4e373e..7586326 100644 --- a/client/html/help-search.hbs +++ b/client/html/help-search.hbs @@ -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><value></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><key>:<value></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:<style></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> + <td><code>special:<value></code></td> + <td>special tokens</td> + <td>filters usually tied to the logged in user</td> + </tr> + </tbody> +</table> + +<p>Most of anonymous and named tokens support ranged and composite values that +take following form:</p> + +<table> + <tbody> + <tr> + <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><a href='/posts/query=fav:David'><code>fav:David</code></a></td> - <td>favorited by David</td> + <td><code>1..</code></td> + <td>will show things that are equal to or greater than 1.</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> + <td><code>..4</code></td> + <td>will show things that are equal to at most 4.</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> + <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><year></code></li> + <li><code><year>-<month></code></li> + <li><code><year>-<month>-<day></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><value></code>.</p> + +<p><strong>Named tokens</strong></p> + +<table> + <tbody> <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><code>id</code></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> + <td><code>score</code></td> + <td>having given score</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> + <td><code>uploader</code></td> + <td>uploaded by given user</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> + <td><code>comment</code></td> + <td>commented by given user</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> + <td><code>fav</code></td> + <td>favorited by given user</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> + <td><code>fav-count</code></td> + <td>favorited by given number of users</td> </tr> <tr> - <td><a href='/posts/query=type:image'><code>type:image</code></a></td> - <td>only image posts</td> + <td><code>comment-count</code></td> + <td>having given number of comments</td> </tr> <tr> - <td><a href='/posts/query=type:flash'><code>type:flash</code></a></td> - <td>only Flash posts</td> + <td><code>tag-count</code></td> + <td>having given number of tags</td> </tr> <tr> - <td><a href='/posts/query=type:youtube'><code>type:youtube</code></a></td> - <td>only Youtube posts</td> + <td><code>note-count</code></td> + <td>having given number of annotations</td> </tr> <tr> - <td><a href='/posts/query=type:video'><code>type:video</code></a></td> - <td>only video posts</td> + <td><code>feature-count</code></td> + <td>having been featured given number of times</td> </tr> <tr> - <td><a href='/posts/query=special:liked'><code>special:liked</code></a></td> + <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><value></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><code>id</code></td> + <td>highest to lowest post ID</td> + </tr> + <tr> + <td><code>score</code></td> + <td>highest scored</td> + </tr> + <tr> + <td><code>fav-count</code></td> + <td>loved by most</td> + </tr> + <tr> + <td><code>comment-count</code></td> + <td>most commented first</td> + </tr> + <tr> + <td><code>tag-count</code></td> + <td>with most tags</td> + </tr> + <tr> + <td><code>note-count</code></td> + <td>with most annotations</td> + </tr> + <tr> + <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><code>feature-count</code></td> + <td>most often featured</td> + </tr> + </tbody> +</table> + +<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><a href='/posts/query=special:disliked'><code>special:disliked</code></a></td> + <td><code>disliked</code></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><code>fav</code></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><code>tumbleweed</code></td> <td>posts with score of 0, without comments and without favorites</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> +<h1 id='user-search-help'>User search tokens</h1> -<p>All of the above can be sorted using additional tag in form of -<code>order:<em>keyword</em></code>:</p> +<p><strong>Anonymous tokens</strong></p> + +<p>Same as <code>name</code> token.</p> + +<p><strong>Named tokens</strong></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>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> - </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>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>loved by most</td> - </tr> - - <tr> - <td><a href='/posts/query=order:comment-count'><code>order:comment-count</code></a></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> - </tr> - - <tr> - <td><a href='/posts/query=order:comment-date'><code>order:comment-date</code></a></td> - <td>recently commented</td> - </tr> - - <tr> - <td><a href='/posts/query=order:feature-date'><code>order:feature-date</code></a></td> - <td>recently featured</td> - </tr> - - <tr> - <td><a href='/posts/query=order:feature-count'><code>order:feature-count</code></a></td> - <td>most often featured</td> - </tr> + <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>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>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> diff --git a/client/html/index.htm b/client/html/index.htm index 1509bb2..dbbd34a 100644 --- a/client/html/index.htm +++ b/client/html/index.htm @@ -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> diff --git a/client/html/user_list_header.hbs b/client/html/user_list_header.hbs index b340f02..27c6ed2 100644 --- a/client/html/user_list_header.hbs +++ b/client/html/user_list_header.hbs @@ -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> diff --git a/client/js/util/views.js b/client/js/util/views.js index a7d9888..c7c297f 100644 --- a/client/js/util/views.js +++ b/client/js/util/views.js @@ -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, }; diff --git a/client/js/views/help_view.js b/client/js/views/help_view.js index 2a5c4ec..12439d2 100644 --- a/client/js/views/help_view.js +++ b/client/js/views/help_view.js @@ -38,6 +38,8 @@ class HelpView { views.listenToMessages(target); views.showView(target, source); + + views.scrollToHash(); } }