add docs from readme on the site

This commit is contained in:
Pavel Mineev
2021-07-27 04:22:40 -05:00
committed by Umputun
parent 5abdaaf793
commit 07b6454b79
16 changed files with 625 additions and 62 deletions
+224
View File
@@ -3,3 +3,227 @@ title: API
parent: Contributing
order: 400
---
## Authorization
- `GET /auth/{provider}/login?from=http://url&site=site_id&session=1` - perform "social" login with one of [supported providers](#register-oauth2-providers) and redirect to `url`. Presence of `session` (any non-zero value) change the default cookie expiration and makes them session-only
- `GET /auth/logout` - logout
```go
type User struct {
Name string `json:"name"`
ID string `json:"id"`
Picture string `json:"picture"`
Admin bool `json:"admin"`
Blocked bool `json:"block"`
Verified bool `json:"verified"`
}
```
## Commenting
- `POST /api/v1/comment` - add a comment, _auth required_
```go
type Comment struct {
ID string `json:"id"` // comment ID, read only
ParentID string `json:"pid"` // parent ID
Text string `json:"text"` // comment text, after md processing
Orig string `json:"orig"` // original comment text
User User `json:"user"` // user info, read only
Locator Locator `json:"locator"` // post locator
Score int `json:"score"` // comment score, read only
Vote int `json:"vote"` // vote for the current user, -1/1/0
Controversy float64 `json:"controversy,omitempty"` // comment controversy, read only
Timestamp time.Time `json:"time"` // time stamp, read only
Edit *Edit `json:"edit,omitempty" bson:"edit,omitempty"` // pointer to have empty default in JSON response
Pin bool `json:"pin"` // pinned status, read only
Delete bool `json:"delete"` // delete status, read only
PostTitle string `json:"title"` // post title
}
type Locator struct {
SiteID string `json:"site"` // site ID
URL string `json:"url"` // post URL
}
type Edit struct {
Timestamp time.Time `json:"time" bson:"time"`
Summary string `json:"summary"`
}
```
- `POST /api/v1/preview` - preview comment in HTML. Body is `Comment` to render
- `GET /api/v1/find?site=site-id&url=post-url&sort=fld&format=tree|plain` - find all comments for given post
This is the primary call used by UI to show comments for the given post. It can return comments in two formats - `plain` and `tree`. In plain format result will be sorted list of `Comment`. In tree format this is going to be tree-like object with this structure:
```go
type Tree struct {
Nodes []Node `json:"comments"`
Info store.PostInfo `json:"info,omitempty"`
}
type Node struct {
Comment store.Comment `json:"comment"`
Replies []Node `json:"replies,omitempty"`
}
```
Sort can be `time`, `active` or `score`. Supported sort order with prefix -/+, i.e. `-time`. For `tree` mode sort will be applied to top-level comments only and all replies are always sorted by time.
- `PUT /api/v1/comment/{id}?site=site-id&url=post-url` - edit comment, allowed once in `EDIT_TIME` minutes since creation. Body is `EditRequest` JSON
```go
type EditRequest struct {
Text string `json:"text"` // updated text
Summary string `json:"summary"` // optional, summary of the edit
Delete bool `json:"delete"` // delete flag
}{}
```
- `GET /api/v1/last/{max}?site=site-id&since=ts-msec` - get up to `{max}` last comments, `since` (epoch time, milliseconds) is optional
- `GET /api/v1/id/{id}?site=site-id` - get comment by `comment id`
- `GET /api/v1/comments?site=site-id&user=id&limit=N` - get comment by `user id`, returns `response` object
```go
type response struct {
Comments []store.Comment `json:"comments"`
Count int `json:"count"`
}{}
```
- `GET /api/v1/count?site=site-id&url=post-url` - get comment's count for `{url}`
- `POST /api/v1/count?site=siteID` - get number of comments for posts from post body (list of post IDs)
- `GET /api/v1/list?site=site-id&limit=5&skip=2` - list commented posts, returns array or `PostInfo`, limit=0 will return all posts
```go
type PostInfo struct {
URL string `json:"url"`
Count int `json:"count"`
ReadOnly bool `json:"read_only,omitempty"`
FirstTS time.Time `json:"first_time,omitempty"`
LastTS time.Time `json:"last_time,omitempty"`
}
```
- `GET /api/v1/user` - get user info, _auth required_
- `PUT /api/v1/vote/{id}?site=site-id&url=post-url&vote=1` - vote for comment. `vote`=1 will increase score, -1 decrease, _auth required_
- `GET /api/v1/userdata?site=site-id` - export all user data to gz stream, _auth required_
- `POST /api/v1/deleteme?site=site-id` - request deletion of user data, _auth required_
- `GET /api/v1/config?site=site-id` - returns configuration (parameters) for given site
```go
type Config struct {
Version string `json:"version"`
EditDuration int `json:"edit_duration"`
MaxCommentSize int `json:"max_comment_size"`
Admins []string `json:"admins"`
AdminEmail string `json:"admin_email"`
Auth []string `json:"auth_providers"`
LowScore int `json:"low_score"`
CriticalScore int `json:"critical_score"`
PositiveScore bool `json:"positive_score"`
ReadOnlyAge int `json:"readonly_age"`
MaxImageSize int `json:"max_image_size"`
EmojiEnabled bool `json:"emoji_enabled"`
}
```
- `GET /api/v1/info?site=site-idd&url=post-url` - returns `PostInfo` for site and URL
## Streaming API
Streaming API provides server-sent events for post updates as well as a site update:
- `GET /api/v1/stream/info?site=site-idd&url=post-url&since=unix_ts_msec` - returns stream (`event: info`) with `PostInfo` records for the site and URL. `since` is optional
- `GET /api/v1/stream/last?site=site-id&since=unix_ts_msec` - returns updates stream (`event: last`) with comments for the site, `since` is optional
<details><summary>Response example</summary>
```
data: {"url":"https://radio-t.com/blah1","count":2,"first_time":"2019-06-18T12:53:48.125686-05:00","last_time":"2019-06-18T12:53:48.142872-05:00"}
event: info
data: {"url":"https://radio-t.com/blah1","count":3,"first_time":"2019-06-18T12:53:48.125686-05:00","last_time":"2019-06-18T12:53:48.157709-05:00"}
event: info
data: {"url":"https://radio-t.com/blah1","count":4,"first_time":"2019-06-18T12:53:48.125686-05:00","last_time":"2019-06-18T12:53:48.172991-05:00"}
event: info
data: {"url":"https://radio-t.com/blah1","count":5,"first_time":"2019-06-18T12:53:48.125686-05:00","last_time":"2019-06-18T12:53:48.188429-05:00"}
event: info
data: {"url":"https://radio-t.com/blah1","count":6,"first_time":"2019-06-18T12:53:48.125686-05:00","last_time":"2019-06-18T12:53:48.204742-05:00"}
event: info
data: {"url":"https://radio-t.com/blah1","count":7,"first_time":"2019-06-18T12:53:48.125686-05:00","last_time":"2019-06-18T12:53:48.220692-05:00"}
event: info
data: {"url":"https://radio-t.com/blah1","count":8,"first_time":"2019-06-18T12:53:48.125686-05:00","last_time":"2019-06-18T12:53:48.23817-05:00"}
event: info
data: {"url":"https://radio-t.com/blah1","count":9,"first_time":"2019-06-18T12:53:48.125686-05:00","last_time":"2019-06-18T12:53:48.254669-05:00"}
```
</details>
## RSS Feeds
- `GET /api/v1/rss/post?site=site-id&url=post-url` - RSS feed for a post
- `GET /api/v1/rss/site?site=site-id` - RSS feed for given site
- `GET /api/v1/rss/reply?site=site-id&user=user-id` - RSS feed for replies to user's comments
## Images Management
- `GET /api/v1/picture/{user}/{id}` - load stored image
- `POST /api/v1/picture` - upload and store image, uses post form with `FormFile("file")`. Returns `{"id": user/imgid}`, _auth required_
_returned ID should be appended to load image URL on caller side_
## Email Subscription
- `GET /api/v1/email?site=site-id` - get user's email, _auth required_
- `POST /api/v1/email/subscribe?site=site-id&address=user@example.org` - makes confirmation token and sends it to user over email, _auth required_
Trying to subscribe to the same email a second time will return response code `409 Conflict` and explaining error message
- `POST /api/v1/email/confirm?site=site-id&tkn=token` - uses provided token parameter to set email for the user, _auth required_
Setting email subscribe user for all first-level replies to his messages
- `DELETE /api/v1/email?site=siteID` - removes user's email, _auth required_
## Admin
- `DELETE /api/v1/admin/comment/{id}?site=site-id&url=post-url` - delete comment by `id`
- `PUT /api/v1/admin/user/{userid}?site=site-id&block=1&ttl=7d` - block or unblock user with optional TTL (default=permanent)
- `GET api/v1/admin/blocked&site=site-id` - list of blocked user IDs
```go
type BlockedUser struct {
ID string `json:"id"`
Name string `json:"name"`
Until time.Time `json:"time"`
}
```
- `GET /api/v1/admin/export?site=site-id&mode=[stream|file]` - export all comments to JSON stream or gz file
- `POST /api/v1/admin/import?site=site-id` - import comments from the backup, uses post body
- `POST /api/v1/admin/import/form?site=site-id` - import comments from the backup, user post form
- `POST /api/v1/admin/remap?site=site-id` - remap comments to different URLs. Expect list of "from-url new-url" pairs separated by \n. From-url and new-url parts are separated by space. If URLs end with an asterisk (\*) it means matching by the prefix. Remap procedure based on export/import chain so make the backup first
```
http://oldsite.com* https://newsite.com*
http://oldsite.com/from-old-page/1 https://newsite.com/to-new-page/1
```
- `GET /api/v1/admin/wait?site=site-id` - wait for completion for any async migration ops (import or remap)
- `PUT /api/v1/admin/pin/{id}?site=site-id&url=post-url&pin=1` - pin or unpin comment
- `GET /api/v1/admin/user/{userid}?site=site-id` - get user's info
- `DELETE /api/v1/admin/user/{userid}?site=site-id` - delete all user's comments
- `PUT /api/v1/admin/readonly?site=site-id&url=post-url&ro=1` - set read-only status
- `PUT /api/v1/admin/verify/{userid}?site=site-id&verified=1` - set verified status
- `GET /api/v1/admin/deleteme?token=token` - process deleteme user's request
_all admin calls require auth and admin privilege_
@@ -1,5 +0,0 @@
---
title: Code of Conduct
parent: Contributing
order: 100
---
@@ -1,6 +0,0 @@
---
title: Development Environment
menuTitle: Environment
parent: Contributing
order: 300
---
@@ -2,6 +2,8 @@
title: Backend Development Guidelines
menuTitle: Backend
key: Backend Guidelines
parent: Guidelines
parent: Development
order: 100
---
In Progress...
@@ -0,0 +1,43 @@
---
title: Frontend Development Guidelines
menuTitle: Frontend
key: Frontend Guidelines
parent: Development
order: 100
---
### Code Style
- project uses TypeScript to statically analyze code
- project uses `eslint` and `stylelint` to check frontend code. You can manually run via `npm run lint`
- Git Hooks (via husky) installed automatically on `npm install` and check and try to fix code style if possible, otherwise commit will be rejected
- if you want IDE integration, you need `eslint` and `stylelint` plugin to be installed
### CSS Styles
- now we are migrating to CSS Modules and this is a recommended way to stylization. A file with styles should be named like `component.module.css`
- old component styles use BEM notation (at least it should): `block__element_modifier`. Also, there are `mix` classes: `block_modifier`
- new way to naming CSS selectors is camel-case like `blockElemenModifier` and use `classnames` to combine it
- component base style resides in the component's root directory with a name of component converted to kebab-case. For example, `ListComments` style is located in `./app/components/list-comments/list-component.tsx`
- any other files should be named also in kebab-case. For example, `./app/utils/get-param.ts`
### Imports
- imports for TypeScript, JavaScript files should be without extension: `./index`, not `./index.ts`
- if the file resides in the same directory or subdirectory import should be relative: `./types/something`
- otherwise it should be imported by absolute path relative to `src` folder like `common/store` which mapped to `./app/common/store.ts` in webpack, tsconfig and Jest
### Testing
- project uses `jest` as test harness
- Jest checks files that match regex `\.(test|spec)\.ts(x?)$`, i.e. `comment.test.tsx`, `comment.spec.ts`
- tests are running on push attempt
- example tests can be found in `./app/store/user/reducers.test.ts`, `./app/components/auth-panel/auth-panel.test.tsx`
### How to add new locale
Please see [this documentation](/site/src/docs/contributing/translations/index.md).
### Notes
- frontend part being bundled on docker env gets placed on `/src/web` and is available via `http://{host}/web`. For example, `embed.js` entry point will be available at `http://{host}/web/embed.js`
@@ -0,0 +1,75 @@
---
title: Development
parent: Contributing
order: 200
---
You can use a fully functional local version to develop and test both frontend and backend. It requires at least 2GB RAM or swap enabled.
To bring it up run:
```shell
# if you mainly work on backend
cp compose-dev-backend.yml compose-private.yml
# if you mainly work on frontend
cp compose-dev-frontend.yml compose-private.yml
# now, edit / debug `compose-private.yml` to your heart's content
# build and run
docker-compose -f compose-private.yml build
docker-compose -f compose-private.yml up
```
It starts Remark42 on `127.0.0.1:8080` and adds local OAuth2 provider "Dev". To access the UI demo page go to `127.0.0.1:8080/web`. By default, you would be logged in as `dev_user` which is defined as admin. You can tweak any of [supported parameters](#parameters) in corresponded yml file.
Backend Docker Compose config by default skips running frontend related tests. Frontend Docker Compose config by default skips running backend related tests and sets `NODE_ENV=development` for frontend build.
### Backend development
To run backend locally (development mode, without Docker) you have to have the latest stable `go` toolchain [installed](https://golang.org/doc/install).
To run backend - `cd backend; go run app/main.go server --dbg --secret=12345 --url=http://127.0.0.1:8080 --admin-passwd=password --site=remark`. It stars backend service with embedded bolt store on port `8080` with basic auth, allowing to authenticate and run requests directly, like this:
`HTTP http://admin:password@127.0.0.1:8080/api/v1/find?site=remark&sort=-active&format=tree&url=http://127.0.0.1:8080`
### Frontend development
#### Developer guide
Frontend guide can be found here: [./frontend/README.md](./frontend/README.md).
#### Build
You should have at least 2GB RAM or swap enabled for building.
- install [Node.js 12.11](https://nodejs.org/en/) or higher
- install [NPM 6.13.4](https://www.npmjs.com/package/npm)
- run `npm install` inside `./frontend`
- run `npm run build` there
- result files will be saved in `./frontend/public`
**Note:** Running `npm install` will set up pre-commit hooks into your git repository. It used to reformat your frontend code using `prettier` and lint with `eslint` and `stylelint` before every commit.
#### Development server
For local development mode with Hot Reloading use `npm start` instead of `npm run build`. In this case, `webpack` will serve files using `webpack-dev-server` on `localhost:9000`. By visiting `127.0.0.1:9000/web` you will get a page with the main comments widget communicating with a demo server backend running on `https://demo.remark42.com`. But you will not be able to log in with any OAuth providers due to security reasons.
You can attach to the locally running backend by providing `REMARK_URL` environment variable.
```shell
npx cross-env REMARK_URL=http://127.0.0.1:8080 npm start
```
**Note:** If you want to redefine env variables such as `PORT` on your local instance you can add `.env` file to `./frontend` folder and rewrite variables as you wish. For such functional, we use `dotenv`.
The best way to start a local developer environment:
```shell
cp compose-dev-frontend.yml compose-private-frontend.yml
docker-compose -f compose-private-frontend.yml up --build
cd frontend
npm run dev
```
Developer build running by `webpack-dev-server` supports devtools for [React](https://github.com/facebook/react-devtools) and
[Redux](https://github.com/zalmoxisus/redux-devtools-extension).
@@ -1,7 +0,0 @@
---
title: Frontend Development Guidelines
menuTitle: Frontend
key: Frontend Guidelines
parent: Guidelines
order: 100
---
@@ -1,5 +0,0 @@
---
title: Guidelines
parent: Contributing
order: 200
---
@@ -5,7 +5,7 @@ parent: Contributing
order: 300
---
## How to add new language translation to Remark42
## Add a New Language to Remark42
Translation files are stored in [/frontend/app/locales](https://github.com/umputun/remark42/tree/master/frontend/app/locales)
directory with `.json` extension and content like following:
@@ -15,47 +15,38 @@ directory with `.json` extension and content like following:
"anonymousLoginForm.length-limit": "Username must be at least 3 characters long",
"anonymousLoginForm.log-in": "Log in",
"anonymousLoginForm.symbol-limit": "Username must start from the letter and contain only latin letters, numbers, underscores, and spaces",
<...>
<...>
}
```
### How to add a new translation
### Add a new translation
We truly appreciate people spending time contributing their translations to remark42. Please go through the steps
below in order to have your translation start being available to all remark42 users and included in the next release.
1. create a fork of [umputun/remark42](https://github.com/umputun/remark42) repo, and if you already have one please
pull the latest changes from the upstream master branch. It could be done like that:
```shell
git remote add upstream https://github.com/umputun/remark42.git
git fetch upstream
git rebase upstream/master
git push
```
1. add a new locale with [two-letter code](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes)
of the language you want to make the translation into to list in
[frontend/tasks/supportedLocales.json](https://github.com/umputun/remark42/blob/master/frontend/tasks/supportedLocales.json)
1. run `npm install` in `frontend` folder
1. run `npm run translation:extract` in `frontend` folder
1. run `npm run translation:generate` in `frontend` folder
1. translate all values in the newly created json file in
[frontend/app/locales/](https://github.com/umputun/remark42/blob/master/frontend/app/locales/)
1. commit all changes above in your fork
1. test your changes in the interface:
1. Create a fork of [umputun/remark42](https://github.com/umputun/remark42) repo, and if you already have one please pull the latest changes from the upstream master branch. It could be done like that:
1. uncomment `locale: "ru"` line in [frontend/index.ejs](https://github.com/umputun/remark42/blob/master/frontend/index.ejs#L133)
and replace `ru` with your translation language code
1. [run remark42 in Docker](https://github.com/umputun/remark42#development) by issuing following commands
from the root directory of your remark42 fork:
```shell
git remote add upstream https://github.com/umputun/remark42.git
git fetch upstream
git rebase upstream/master
git push
```
```shell
docker-compose -f compose-dev-frontend.yml build
docker-compose -f compose-dev-frontend.yml up
```
1. Add a new locale with [two-letter code](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) of the language you want to make the translation into to list in [frontend/tasks/supportedLocales.json](https://github.com/umputun/remark42/blob/master/frontend/tasks/supportedLocales.json)
1. Run `npm install` in `frontend` folder
1. Run `npm run translation:extract` in `frontend` folder
1. Run `npm run translation:generate` in `frontend` folder
1. Translate all values in the newly created json file in
[frontend/app/locales/](https://github.com/umputun/remark42/blob/master/frontend/app/locales/)
1. Commit all changes above in your fork
1. Test your changes in the interface:
1. open [http://127.0.0.1:8080/web](http://127.0.0.1:8080/web), log in, make a comment, make a reply to a comment,
and make sure your translation looks as you expect it to look
1. make a screenshot from [http://127.0.0.1:8080](http://127.0.0.1:8080) with your translation in place
1. Uncomment `locale: "ru"` line in [frontend/index.ejs](https://github.com/umputun/remark42/blob/master/frontend/index.ejs#L133) and replace `ru` with your translation language code
2. [Run remark42 in Docker](https://github.com/umputun/remark42#development) by issuing following commands from the root directory of your remark42 fork:
`shell docker-compose -f compose-dev-frontend.yml build docker-compose -f compose-dev-frontend.yml up `
1. after all previous steps are done, create a [Pull Request](https://github.com/umputun/remark42/pulls) to umputun/remark42
repo with your changes, attaching a screenshot or two from your local test instance to it
3. open [http://127.0.0.1:8080/web](http://127.0.0.1:8080/web), log in, make a comment, make a reply to a comment, and make sure your translation looks as you expect it to look
4. make a screenshot from [http://127.0.0.1:8080](http://127.0.0.1:8080) with your translation in place
1. after all previous steps are done, create a [Pull Request](https://github.com/umputun/remark42/pulls) to umputun/remark42 repo with your changes, attaching a screenshot or two from your local test instance to it