# Comments Client

This is a client library that enables to interact with the generic Wix comments infrastructure.

## Usage

Create a client.

```javascript
const {client} = require('@wix/comments-client');

const commentsClient = client({
    contextToken: 'context-token-received-from-the-hosting-app',
    signedInstance: 'signed-instance-received-from-the-hosting-app',
    baseUrl: '/relative-to-document'  // optional, default: 'https://social.wix.com'
});

const comment = await client.get({
  commentId: 'comment-id'
});
```

## API

### `CommentsClient.get(req: GetComment): Promise<Comment>`

Get a single comment.

#### GetComment
```typescript
interface GetComment {
    commentId?: (string | null);
}
```

### `CommentsClient.list(req: GetList): Promise<CommentsPage>`

Get a list of comments or replies. Cursor should be provided as null to get the first page.

To list the next page of replies, take the `Replies.nextCursor` value and use it in `cursorPaging.cursor`.

#### Flatten to depth

In case a limited depth of comments -> replies are required, `pagingContextSetup.flattenToDepth` param can be used optionally when setting up a new pagination context.

I.e.
Comment A
 - Reply 1
   - Reply 2   
Comment B 
 - Reply 3
 
In case flattenToDepth=1 is provided, this hierarchy would be returned as
Comment A
 - Reply 1

All cursors will include this information

#### Getting comments "newest first"

In order to get the comments in newest first order, value ordering for ordering has to be set LATEST_FIRST  

#### GetList

```typescript
interface GetList {
    pagingContextSetup?: PagingContextSetup  // start a new pagination context
    cursorPaging?: CursorPaging;  // continue paging (as set up from pagingContextSetup)
    query?: CommentsQuery
}

interface PagingContextSetup {
    entityId?: string;
    flattenToDepth?: number;
    limit?: number;
    ordering: Ordering;
}

interface CommentsQuery {
    repliesToLoad: number;
}

enum Ordering {
  OLDEST_FIRST,
  LATEST_FIRST
}
```

### `CommentsClient.create(req: CreateComment): Promise<Comment>`

Create a comment.

#### CreateComment

```typescript
interface CreateComment {
    entityId?: string  // entityId
    comment: UpdateCommentEntity
}
```

### `CommentsClient.update(req: UpdateComment): Promise<Comment>`

Update a comment.

#### UpdateComment

```typescript
interface UpdateComment {
    commentId: string
    comment: UpdateCommentEntity
}
```

### `CommentsClient.createReply(req: CreateReply): Promise<Comment>`

Create a comment reply.

#### CreateReply

```typescript
interface CreateReply {
  commentOrReplyId: string,
  reply: UpdateCommentEntity
}
```

### `CommentsClient.delete(req: DeleteComment): Promise<CommentWithCommentsPage>`

Delete a comment and optionally get a list of comments.

#### DeleteComment

```typescript
interface DeleteComment {
    commentId: string,
    list?: GetList // optionally get an updated list of comments
}
```

#### CommentWithCommentsPage

```typescript
interface CommentWithCommentsPage {
  comment: Comment
  commentsPage: CommentsPage | null
}
```

### `CommentsClient.uploadFile(req: UploadFile): Promise<Resource>`

Upload a comment resource.

Example:
```typescript

const resource = await commentsClient.uploadFile({
    file: fileInputElement.files[0]
});
```

#### UploadFile

```typescript
interface UploadFile {
  file: Blob | File,
  name?: string
}
```

### `CommentsClient.report(req: ReportComment): Promise<Comment>`

Report a comment.

#### ReportComment

```typescript
interface ReportComment {
  commentId: string,
  reportType: ReportType
}
```

### `CommentsClient.getReported(req: GetReported): Promise<Reported>`

Get reported summary for comment.

#### GetReported

```typescript
interface GetReported {
  commentId: string
}
```

### `CommentsClient.queryProfiles(req: QueryProfiles): Promise<QueryProfilesResponse>`

Query profiles.

#### QueryProfiles

```typescript
interface QueryProfiles {
  searchText: string
  limit: number
}

interface QueryProfilesResponse {
  profiles: Profile[];
  nextCursor: string | null;
}
```

### `CommentsClient.listMoreProfiles(req: CursorPaging): Promise<QueryProfilesResponse>`

List more profiles for the same query.

### Message types

#### CommentsPage
```typescript
interface CommentsPage {
    availableActions: Action[]
    total: number
    comments?: (Comment[] | null)
    cursor?: (string | null)
    nextCursor?: (string | null)
    previousCursor?: (string | null)
    remainingCount: number
    loggedInProfile: Profile | null
}
```

#### Comment
```typescript
interface Comment {
  commentId: string
  containerId?: string
  comment: CommentEntity,
  reactions: Reactions,
  replies: Replies
  reported: Reported | null,
  createdAt: Date
  updatedAt: Date | null
  availableActions: Action[]
  createdBy: Profile
}
```

#### CommentEntity

```typescript
interface CommentEntity {
    text: (Text | null);
    mentions?: (Mention[] | null);
    attachments?: (Resource[] | null);
}
```

#### UpdateCommentEntity

```typescript
interface UpdateCommentEntity {
    text: (Text | null);
    mentions?: (UpdateMention[] | null);
    attachments?: (Resource[] | null);
}

interface UpdateMention {
    subjectId: string;
}
```

#### Reactions

```typescript
interface Reactions {
    count: number;
}
```

#### Replies

```typescript
interface Replies {
  count: number
  comments: Comment[]
  cursor?: string
  nextCursor?: string
  remainingCount: number
}
```

#### Reported

```typescript
interface Reported {
  count: number | null
  reportedTypes?: ReportType[]
}
```

#### ReportType

```typescript
enum ReportType {
  UnwantedContent = 'UNWANTED_CONTENT',
  Harassment = 'HARASSMENT',
  InappropriateContent = 'INAPPROPRIATE_CONTENT',
  HateSpeechOrGraphic = 'HATE_SPEECH_OR_GRAPHIC'
}
```

#### Action

```typescript
enum Action {
  View = 'VIEW',
  AddComment = 'ADD_COMMENT',
  React = 'REACT',
  Unreact = 'UNREACT',
  Report = 'REPORT',
  Edit = 'EDIT',
  Delete = 'DELETE'
}
```

#### Resource

```typescript
interface Resource {
    uri?: (string | null);
    id?: (string | null);
    mediaType?: (MediaType | null);
    pixelDimensions: PixelDimensions | null;
    mimeType: string | null;
}
```

#### MediaType

```typescript
enum MediaType {
    ATTACHMENT = 'ATTACHMENT',
    IMAGE = 'IMAGE',
    VIDEO = 'VIDEO',
}
```

#### PixelDimensions

```typescript
interface PixelDimensions {
  width: number;
  height: number;
}
```

#### Image

```typescript
interface Text {
    contentType?: (ContentType | null);
    content?: (string | null);
}
```

#### Content Type

```typescript
enum ContentType {
    PLAIN_TEXT = 'PLAIN_TEXT',
    DRAFTJS = 'DRAFTJS',
}
```

#### Mention

```typescript
interface Mention {
    profile: Profile
}
```

#### Profile

```typescript
interface Profile {
  id: string
  nickname: string
  imageUrl?: string
}
```

#### CursorPaging

```typescript
interface CursorPaging {
    limit?: (number | null);
    cursor?: (string | null);
}
```
