Skip to content

Commit

Permalink
Yes
Browse files Browse the repository at this point in the history
  • Loading branch information
lucapette committed Apr 26, 2021
1 parent d9aaec1 commit d540a2e
Show file tree
Hide file tree
Showing 14 changed files with 74 additions and 132 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit.jupiter.SpringExtension;

import java.util.concurrent.TimeUnit;

import static co.airy.test.Timing.retryOnException;
import static org.hamcrest.CoreMatchers.is;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
Expand Down Expand Up @@ -74,7 +73,7 @@ void beforeEach() throws Exception {

@Test
void canManageTags() throws Exception {
final String name = "awesome-tag";
final String name = "flag";
final String color = "tag-red";
final String payload = "{\"name\":\"" + name + "\",\"color\": \"" + color + "\"}";

Expand All @@ -87,34 +86,33 @@ void canManageTags() throws Exception {
final JsonNode jsonNode = objectMapper.readTree(createTagResponse);
final String tagId = jsonNode.get("id").textValue();

//TODO wait for tag to be there
TimeUnit.SECONDS.sleep(5);

webTestHelper.post("/tags.list", "{}")
.andExpect(status().isOk())
.andExpect(jsonPath("$.data.length()", is(1)))
.andExpect(jsonPath("$.data[0].id").value(is(tagId)))
.andExpect(jsonPath("$.data[0].name").value(is(name)))
.andExpect(jsonPath("$.data[0].color").value(is("RED")));
retryOnException(() ->
webTestHelper.post("/tags.list", "{}")
.andExpect(status().isOk())
.andExpect(jsonPath("$.data.length()", is(1)))
.andExpect(jsonPath("$.data[0].id").value(is(tagId)))
.andExpect(jsonPath("$.data[0].name").value(is(name)))
.andExpect(jsonPath("$.data[0].color").value(is("tag-red"))),
"could not create tag");

webTestHelper.post("/tags.update",
"{\"id\": \"" + tagId + "\", \"name\": \"new-name\", \"color\": \"" + color + "\"}")
"{\"id\": \"" + tagId + "\", \"name\": \"new-flag\", \"color\": \"" + color + "\"}")
.andExpect(status().isNoContent());

webTestHelper.post("/tags.list", "{}")
.andExpect(status().isOk())
.andExpect(jsonPath("$.data.length()", is(1)))
.andExpect(jsonPath("$.data[0].id").value(is(tagId)))
.andExpect(jsonPath("$.data[0].name").value(is("new-name")))
.andExpect(jsonPath("$.data[0].color").value(is("RED")));
retryOnException(() -> webTestHelper.post("/tags.list", "{}")
.andExpect(status().isOk())
.andExpect(jsonPath("$.data.length()", is(1)))
.andExpect(jsonPath("$.data[0].id").value(is(tagId)))
.andExpect(jsonPath("$.data[0].name").value(is("new-flag")))
.andExpect(jsonPath("$.data[0].color").value(is("tag-red"))),
"could not update tag");

webTestHelper.post("/tags.delete", "{\"id\": \"" + tagId + "\"}").andExpect(status().isNoContent());

//TODO wait for tag deletion
TimeUnit.SECONDS.sleep(5);

webTestHelper.post("/tags.list", "{}")
.andExpect(status().isOk())
.andExpect(jsonPath("$.data.length()", is(0)));
retryOnException(() -> webTestHelper.post("/tags.list", "{}")
.andExpect(status().isOk())
.andExpect(jsonPath("$.data.length()", is(0))),
"could not delete tag");
}
}
4 changes: 2 additions & 2 deletions backend/model/tag/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ custom_java_library(
srcs = glob(["src/main/java/co/airy/model/tag/**/*.java"]),
visibility = ["//visibility:public"],
exports = [
"//backend/avro/communication:tag-avro",
"//backend/avro:tag-avro",
"//lib/java/kafka/schema:application-communication-tags",
],
deps = [
"//:jackson",
"//:lombok",
"//backend/avro/communication:tag-avro",
"//backend/avro:tag-avro",
],
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public class TagPayload {
public static TagPayload fromTag(Tag tag) {
return TagPayload.builder()
.id(tag.getId())
.color(tag.getColor().toString())
.color("tag-"+tag.getColor().toString().toLowerCase())
.name(tag.getName())
.build();
}
Expand Down
16 changes: 9 additions & 7 deletions docs/docs/api/endpoints/chatplugin.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ title: Chat Plugin
sidebar_label: Chat Plugin
---

Refer to our [Chat Plugin introduction](sources/chatplugin/overview.md) for
Refer to our [Chat Plugin overview](sources/chatplugin/overview.md) document for
more information.

The HTTP api adheres to standards laid out in the [core
Expand All @@ -16,8 +16,9 @@ API](/api/introduction#authentication).
The request returns an authentication token that needs to be included in the
WebSocket connection handshake.

You can either pass the `channel_id` for a new conversation or a `resume_token` that was obtained in a
previous conversation using the [resume endpoint](#get-a-resume-token).
You can either pass the `channel_id` for a new conversation or a `resume_token`
that was obtained in a previous conversation using the [resume
endpoint](#get-a-resume-token).

**Sample request**

Expand Down Expand Up @@ -75,8 +76,9 @@ endpoint](#authenticating-web-users) as an `Authorization` header.
}
```

You can also obtain a resume token on behalf of the user. To do so you need to call this endpoint with the
system API token set on the `Authorization` header and with the channel and conversation id.
You can also obtain a resume token on behalf of the user. To do so you need to
call this endpoint with the system API token set on the `Authorization` header
and with the channel and conversation id.

**Sample request**

Expand All @@ -89,8 +91,8 @@ system API token set on the `Authorization` header and with the channel and conv

#### Send message

You must set the `token` obtained on the [authorization endpoint](#authenticating-web-users) as an `Authorization`
header.
You must set the `token` obtained on the [authorization
endpoint](#authenticating-web-users) as an `Authorization` header.

`POST /chatplugin.send`

Expand Down
8 changes: 4 additions & 4 deletions docs/docs/api/endpoints/messages.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ title: Messages
sidebar_label: Messages
---

Refer to our [messages](getting-started/glossary.md#message) definition
for more information.
Refer to our [message](getting-started/glossary.md#message) definition for more
information.

## List

`POST /messages.list`

This is a [paginated](#pagination) endpoint. Messages are sorted from oldest to
latest.
This is a [paginated](api/endpoints/introduction#pagination) endpoint. Messages
are sorted from oldest to latest.

**Sample request**

Expand Down
8 changes: 5 additions & 3 deletions docs/docs/api/endpoints/metadata.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ title: Metadata
sidebar_label: Metadata
---

Have a look at our [metadata design](concepts/metadata.md) for more information.
Refer to our [metadata design](concepts/metadata.md) document for more
information.

## Upsert

This endpoint takes a `data` object and upserts the metadata for the `id`. The data may only contain
values of type string or object values (i.e. no lists or numbers).
This endpoint takes a `data` object and upserts the metadata for the `id`. The
data may only contain values of type string or object values (i.e. no lists or
numbers).

`POST /metadata.upsert`

Expand Down
11 changes: 4 additions & 7 deletions docs/docs/api/endpoints/tags.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ title: Tags
sidebar_label: Tags
---

Please refer to our [tag](getting-started/glossary.md#tag) definition for more
Refer to our [tag](getting-started/glossary.md#tag) definition for more
information.

## Create
Expand All @@ -19,7 +19,8 @@ information.
}
```

If the tag is successfully created, the request returns status code `201` (created) with the tag ID in the response body.
If the tag is successfully created, the request returns status code `201`
(created) with the tag ID in the response body.

**Sample response**

Expand All @@ -45,8 +46,6 @@ If the tag is successfully created, the request returns status code `201` (creat
}
```

If action is successful, the request returns status code `200`.

**Empty response (204)**

## Delete
Expand All @@ -61,8 +60,6 @@ If action is successful, the request returns status code `200`.
}
```

If action is successful, returns HTTP status `200`.

**Empty response (204)**

## List
Expand All @@ -77,7 +74,7 @@ If action is successful, returns HTTP status `200`.
{
"id": "TAG-ID",
"name": "name of the tag",
"color": "RED"
"color": "tag-red"
}
]
}
Expand Down
19 changes: 17 additions & 2 deletions docs/docs/api/websocket.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ protocol endpoint at `/ws.communication`.

## Event Payloads

All event updates are sent to the `/events` queue as JSON encoded payloads. The `type`
field informs the client of the kind of update that is encoded in the payload.
All event updates are sent to the `/events` queue as JSON encoded payloads. The
`type` field informs the client of the kind of update that is encoded in the
payload.

### Message

Expand Down Expand Up @@ -81,3 +82,17 @@ field informs the client of the kind of update that is encoded in the payload.
}
}
```

### Tag

```json5
{
"type": "tag",

"payload": {
"id": "{UUID}",
"name": "flag",
"color": "tag-red"
}
}
```
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, {FormEvent, useEffect, useState} from 'react';
import _, {connect, ConnectedProps} from 'react-redux';
import {withRouter} from 'react-router-dom';
import {Tag as TagModel, TagColor, getTags} from 'model';
import {Tag as TagModel, TagColor} from 'model';

import {createTag, listTags} from '../../../../actions/tags';
import {addTagToConversation, removeTagFromConversation} from '../../../../actions/conversations';
Expand Down Expand Up @@ -66,16 +66,7 @@ const ConversationMetadata = (props: ConnectedProps<typeof connector>) => {
return tags.filter(tag => tag.id in (conversation.metadata.tags || {}));
};

const tagSorter = (tagA: TagModel, tagB: TagModel) => {
if (tagA.name < tagB.name) {
return -1;
}
if (tagA.name > tagB.name) {
return 1;
}

return 0;
};
const tagSorter = (a: TagModel, b: TagModel) => a.name.localeCompare(b.name);

const checkIfExists = (value: string) => {
const usedTags = filterForUsedTags(tags);
Expand Down Expand Up @@ -166,9 +157,7 @@ const ConversationMetadata = (props: ConnectedProps<typeof connector>) => {
);
};

const findTag = (tagId: string): TagModel => {
return tags.find(tag => tag.id === tagId);
};
const findTag = (tagId: string): TagModel => tags.find(tag => tag.id === tagId);

const contact = conversation.metadata.contact;
return (
Expand All @@ -194,7 +183,7 @@ const ConversationMetadata = (props: ConnectedProps<typeof connector>) => {

<div className={styles.tagList}>
{tags &&
getTags(conversation)
Object.keys(conversation.metadata.tags || {})
.map(tagId => findTag(tagId))
.sort(tagSorter)
.map(tag => tag && <Tag key={tag.id} tag={tag} removeTag={() => removeTag(tag)} />)}
Expand Down
4 changes: 2 additions & 2 deletions frontend/ui/src/pages/Inbox/Messenger/MessageList/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {debounce, isEmpty} from 'lodash-es';
import {withRouter} from 'react-router-dom';
import {cyMessageList} from 'handles';

import {Message, Suggestions, getSource} from 'model';
import {Message, Suggestions} from 'model';
import {SourceMessage} from 'render';
import {ReactComponent as LightBulbIcon} from 'assets/images/icons/lightbulb.svg';

Expand Down Expand Up @@ -179,7 +179,7 @@ const MessageList = (props: MessageListProps) => {
lastInGroup={lastInGroup}
isChatPlugin={false}
decoration={messageDecoration}>
<SourceMessage source={getSource(conversation)} content={message} contentType="message" />
<SourceMessage source={conversation.channel?.source} content={message} contentType="message" />
</MessageInfoWrapper>
</div>
);
Expand Down
34 changes: 2 additions & 32 deletions lib/typescript/httpclient/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

The HttpClient Library includes a HTTP client for making requests to Airy's API.

The library exports a HttpClient class with public methods that make requests to Airy's API.
The library exports a HttpClient class with public methods that make requests to
Airy's API.

To use the library, you need to instantiate the class with an Airy Core API URL.

Expand All @@ -14,34 +15,3 @@ import {HttpClient} from "httpclient";
const client = new HttpClient("http://airy.core");
client.listChannels().then(channels => console.debug("channels", channels));
```

Here is a list of the public methods the library's class includes:

CHANNELS

- listChannels
- exploreChannels
- connectChannel
- disconnectChannel
- connectFacebookChannel
- exploreFacebookChannels

CONVERSATIONS

- listConversations
- getConversationInfo
- readConversations
- tagConversation
- untagConversation

MESSAGES

- listMessages
- sendMessages

TAGS

- listTags
- createTag
- updateTag
- deleteTag
15 changes: 1 addition & 14 deletions lib/typescript/httpclient/src/endpoints/createTag.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,4 @@
import {Tag} from 'model';

const tagMapper = {
BLUE: 'tag-blue',
RED: 'tag-red',
GREEN: 'tag-green',
PURPLE: 'tag-purple',
};

export const createTagDef = {
endpoint: 'tags.create',
mapResponse: (response: Tag) => ({
id: response.id,
name: response.name,
color: tagMapper[response.color] || 'tag-blue',
}),
mapResponse: response => response,
};

0 comments on commit d540a2e

Please sign in to comment.