From 5b5b043a8b1e86b4228a36908ac20445404d068d Mon Sep 17 00:00:00 2001 From: Martin Lopez Date: Mon, 14 Aug 2023 15:44:49 -0300 Subject: [PATCH 01/16] feat: add initial implementation --- README.md | 43 ++++-- pom.xml | 17 +-- .../addons/chatassistant/ChatAssistant.java | 142 ++++++++++++++++++ .../vaadin/addons/chatassistant/Message.java | 118 +++++++++++++++ .../vaadin/addons/chatassistant/Sender.java | 69 +++++++++ .../frontend/styles/chat-assistant-styles.css | 36 +++++ .../frontend/styles/static_addon_styles | 1 - .../META-INF/resources/static_addon_resources | 1 - .../flowingcode/vaadin/addons/DemoLayout.java | 6 +- .../addons/chatbot/ChatAssistantDemo.java | 79 ++++++++++ .../ChatAssistantDemoView.java} | 14 +- .../{template => chatbot}/DemoView.java | 10 +- .../it/AbstractViewTest.java | 14 +- .../vaadin/addons/chatbot/it/BasicIT.java | 53 +++++++ .../{template => chatbot}/it/ViewIT.java | 55 +++---- .../chatbot/it/po/ChatAssistantElement.java} | 18 +-- .../chatbot/it/po/ChatBubbleElement.java | 26 ++++ .../test/SerializationTest.java | 15 +- .../vaadin/addons/template/TemplateDemo.java | 17 --- .../styles/chat-assistant-styles-demo.css | 23 +++ .../frontend/styles/shared-styles.css | 1 - .../resources/META-INF/resources/chatbot.png | Bin 0 -> 20632 bytes .../resources/static_addon_test_resources | 1 - 23 files changed, 644 insertions(+), 115 deletions(-) create mode 100644 src/main/java/com/flowingcode/vaadin/addons/chatassistant/ChatAssistant.java create mode 100644 src/main/java/com/flowingcode/vaadin/addons/chatassistant/Message.java create mode 100644 src/main/java/com/flowingcode/vaadin/addons/chatassistant/Sender.java create mode 100644 src/main/resources/META-INF/frontend/styles/chat-assistant-styles.css delete mode 100644 src/main/resources/META-INF/frontend/styles/static_addon_styles delete mode 100644 src/main/resources/META-INF/resources/static_addon_resources create mode 100644 src/test/java/com/flowingcode/vaadin/addons/chatbot/ChatAssistantDemo.java rename src/test/java/com/flowingcode/vaadin/addons/{template/TemplateDemoView.java => chatbot/ChatAssistantDemoView.java} (76%) rename src/test/java/com/flowingcode/vaadin/addons/{template => chatbot}/DemoView.java (88%) rename src/test/java/com/flowingcode/vaadin/addons/{template => chatbot}/it/AbstractViewTest.java (93%) create mode 100644 src/test/java/com/flowingcode/vaadin/addons/chatbot/it/BasicIT.java rename src/test/java/com/flowingcode/vaadin/addons/{template => chatbot}/it/ViewIT.java (54%) rename src/{main/java/com/flowingcode/vaadin/addons/template/TemplateAddon.java => test/java/com/flowingcode/vaadin/addons/chatbot/it/po/ChatAssistantElement.java} (57%) create mode 100644 src/test/java/com/flowingcode/vaadin/addons/chatbot/it/po/ChatBubbleElement.java rename src/test/java/com/flowingcode/vaadin/addons/{template => chatbot}/test/SerializationTest.java (81%) delete mode 100644 src/test/java/com/flowingcode/vaadin/addons/template/TemplateDemo.java create mode 100644 src/test/resources/META-INF/frontend/styles/chat-assistant-styles-demo.css delete mode 100644 src/test/resources/META-INF/frontend/styles/shared-styles.css create mode 100644 src/test/resources/META-INF/resources/chatbot.png delete mode 100644 src/test/resources/META-INF/resources/static_addon_test_resources diff --git a/README.md b/README.md index bbe19e3..affd969 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,24 @@ -[![Published on Vaadin Directory](https://img.shields.io/badge/Vaadin%20Directory-published-00b4f0.svg)](https://vaadin.com/directory/component/template-addon) -[![Stars on vaadin.com/directory](https://img.shields.io/vaadin-directory/star/app-layout-addon.svg)](https://vaadin.com/directory/component/template-addon) -[![Build Status](https://jenkins.flowingcode.com/job/template-addon/badge/icon)](https://jenkins.flowingcode.com/job/template-addon) +[![Published on Vaadin Directory](https://img.shields.io/badge/Vaadin%20Directory-published-00b4f0.svg)](https://vaadin.com/directory/component/chat-assistant) +[![Stars on vaadin.com/directory](https://img.shields.io/vaadin-directory/star/app-layout-addon.svg)](https://vaadin.com/directory/component/chat-assistant) +[![Build Status](https://jenkins.flowingcode.com/job/ChatAssistant-addon/badge/icon)](https://jenkins.flowingcode.com/job/ChatAssistant-addon) -# Template Add-on +# Chat Assistant Add-on -This is a template project for building new Vaadin 24 add-ons +Vaadin Addon that displays a chat assistant floating window using [wc-chatbot](https://github.com/yishiashia/wc-chatbot). ## Features -* List the features of your add-on in here +* Messages can be sent by the user or programmatically. +* Listen for new messages written by the user. +* Toggle the chat window on/off. ## Online demo -[Online demo here](http://addonsv24.flowingcode.com/template) +[Online demo here](http://addonsv24.flowingcode.com/chat-assistant) ## Download release -[Available in Vaadin Directory](https://vaadin.com/directory/component/template-addon) +[Available in Vaadin Directory](https://vaadin.com/directory/component/chat-assistant) ### Maven install @@ -25,7 +27,7 @@ Add the following dependencies in your pom.xml file: ```xml org.vaadin.addons.flowingcode - template-addon + chat-assistant X.Y.Z ``` @@ -49,7 +51,7 @@ To see the demo, navigate to http://localhost:8080/ ## Release notes -See [here](https://github.com/FlowingCode/TemplateAddon/releases) +See [here](https://github.com/FlowingCode/ChatAssistant/releases) ## Issue tracking @@ -74,13 +76,30 @@ Then, follow these steps for creating a contibution: This add-on is distributed under Apache License 2.0. For license terms, see LICENSE.txt. -TEMPLATE_ADDON is written by Flowing Code S.A. +Chat Assistant is written by Flowing Code S.A. # Developer Guide ## Getting started -Add your code samples in this section +Simple example showing the basic options: + + ChatAssistant chatAssistant = new ChatAssistant(); + TextArea message = new TextArea(); + message.setLabel("Enter a message from the assistant"); + message.setSizeFull(); + + Button chat = new Button("Chat"); + chat.addClickListener(ev->{ + Message m = new Message(message.getValue(),false,false,0,false,new Sender("Assistant","1","https://ui-avatars.com/api/?name=Bot")); + chatAssistant.sendMessage(m); + message.clear(); + }); + chatAssistant.sendMessage(new Message("Hello, I am here to assist you",false,false,0,false,new Sender("Assistant","1","https://ui-avatars.com/api/?name=Bot"))); + chatAssistant.toggle(); + chatAssistant.addChatSentListener(ev->{ + Notification.show(ev.getMessage()); + }); ## Special configuration when using Spring diff --git a/pom.xml b/pom.xml index b7e1368..3e0ae9e 100644 --- a/pom.xml +++ b/pom.xml @@ -5,10 +5,10 @@ 4.0.0 org.vaadin.addons.flowingcode - template-addon + chat-assistant-addon 1.0.0-SNAPSHOT - Template Add-on - Template Add-on for Vaadin Flow + Chat Assistant Add-on + Chat Assistant Add-on for Vaadin Flow 24.1.2 @@ -19,7 +19,7 @@ UTF-8 ${project.basedir}/drivers 11.0.12 - 3.6.0 + 3.7.1 true @@ -173,14 +173,6 @@ maven-deploy-plugin 2.8.2 - - org.apache.maven.plugins - maven-surefire-plugin - 2.22.1 - - false - - @@ -242,7 +234,6 @@ src/test/resources/META-INF/resources - src/main/resources/META-INF/resources diff --git a/src/main/java/com/flowingcode/vaadin/addons/chatassistant/ChatAssistant.java b/src/main/java/com/flowingcode/vaadin/addons/chatassistant/ChatAssistant.java new file mode 100644 index 0000000..40fc36f --- /dev/null +++ b/src/main/java/com/flowingcode/vaadin/addons/chatassistant/ChatAssistant.java @@ -0,0 +1,142 @@ +/*- + * #%L + * Chat Assistant Add-on + * %% + * Copyright (C) 2023 Flowing Code + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ + +package com.flowingcode.vaadin.addons.chatassistant; + +import com.vaadin.flow.component.ComponentEvent; +import com.vaadin.flow.component.ComponentEventListener; +import com.vaadin.flow.component.DomEvent; +import com.vaadin.flow.component.EventData; +import com.vaadin.flow.component.Tag; +import com.vaadin.flow.component.dependency.CssImport; +import com.vaadin.flow.component.dependency.JsModule; +import com.vaadin.flow.component.dependency.NpmPackage; +import com.vaadin.flow.component.html.Div; +import com.vaadin.flow.shared.Registration; + +/** + * Component that allows to create a floating chat button that will open a chat window that can be + * used to provide a chat assistant feature. + * + * @author mmlopez + */ +@SuppressWarnings("serial") +@NpmPackage(value = "wc-chatbot", version = "0.1.1") +@JsModule("wc-chatbot/dist/wc-chatbot.js") +@CssImport("./styles/chat-assistant-styles.css") +@Tag("chat-bot") +public class ChatAssistant extends Div { + + /** + * Sends a message represented by the string message programmatically to the component, with + * default settings. + * + * @param message + */ + public void sendMessage(String message) { + sendMessage(new Message(message)); + } + + /** Shows or hides the chat window */ + public void toggle() { + getElement().executeJs("setTimeout(() => {this.toggle();})"); + } + + /** + * Sends a message to the component, by using the supplied Message object. + * + * @param message + */ + public void sendMessage(Message message) { + getElement() + .executeJs( + "setTimeout(() => { this.sendMessage('" + + message.getContent() + + "', {\n" + + " continued: " + + message.isContinued() + + ",\n" + + " right: " + + message.isRight() + + ",\n" + + " delay: " + + message.getDelay() + + ",\n" + + " loading: " + + message.isLoading() + + ",\n" + + " sender: {\n" + + " name: '" + + message.getSender().getName() + + "',\n" + + " id: '" + + message.getSender().getId() + + "',\n" + + " avatar: '" + + message.getSender().getAvatar() + + "'\n" + + " }\n" + + "}) });"); + } + + /** + * Adds a listener that will be notified when the ChatSentEvent is fired, allowing to react when a + * message is sent by the user or programmatically. + * + * @param listener + * @return Registration object to allow removing the listener. + */ + public Registration addChatSentListener(ComponentEventListener listener) { + return addListener(ChatSentEvent.class, listener); + } + + /** + * Event that represents a chat being sent to the component. + * + * @author mmlopez + */ + @DomEvent("sent") + public static class ChatSentEvent extends ComponentEvent { + private final String message; + private Boolean right; + + public ChatSentEvent( + ChatAssistant source, + boolean fromClient, + @EventData("event.detail.message.message") String message, + @EventData("event.detail.message.right") Boolean right) { + super(source, fromClient); + this.message = message.replaceAll("^<[^>]+>|<[^>]+>$", ""); + this.right = right; + } + + public String getMessage() { + return message; + } + + public Boolean isRight() { + return right; + } + + public ChatAssistant getChatBot() { + return (ChatAssistant) source; + } + } +} diff --git a/src/main/java/com/flowingcode/vaadin/addons/chatassistant/Message.java b/src/main/java/com/flowingcode/vaadin/addons/chatassistant/Message.java new file mode 100644 index 0000000..274e7ad --- /dev/null +++ b/src/main/java/com/flowingcode/vaadin/addons/chatassistant/Message.java @@ -0,0 +1,118 @@ +/*- + * #%L + * Chat Assistant Add-on + * %% + * Copyright (C) 2023 Flowing Code + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ +package com.flowingcode.vaadin.addons.chatassistant; + +/** + * Class that represents a chat message. It contains several configurations to control the + * appearance of the message, such as: + * + *
    + *
  • continued: when true, the message is continued with the previous one. + *
  • right: when true, the message is aligned to the right. + *
  • delay: it can show some delay before being sent. + *
  • loading: it can show a loading image before showing the message. + *
  • sender: it allows to specify the sender. + *
+ * + * @author mmlopez + */ +public class Message { + + private String content; + private boolean continued; + private boolean right; + private Integer delay = 0; + private boolean loading; + private Sender sender; + + public Message(String content) { + this( + content, + false, + true, + 0, + false, + new Sender("Guest", "2", "https://ui-avatars.com/api/?name=Guest")); + } + + public Message( + String content, + Boolean continued, + Boolean right, + Integer delay, + Boolean loading, + Sender sender) { + super(); + this.content = content; + this.continued = continued; + this.right = right; + this.delay = delay; + this.loading = loading; + this.sender = sender; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public boolean isContinued() { + return continued; + } + + public void setContinued(boolean continued) { + this.continued = continued; + } + + public boolean isRight() { + return right; + } + + public void setRight(boolean right) { + this.right = right; + } + + public Integer getDelay() { + return delay; + } + + public void setDelay(Integer delay) { + this.delay = delay; + } + + public boolean isLoading() { + return loading; + } + + public void setLoading(boolean loading) { + this.loading = loading; + } + + public Sender getSender() { + return sender; + } + + public void setSender(Sender sender) { + this.sender = sender; + } +} diff --git a/src/main/java/com/flowingcode/vaadin/addons/chatassistant/Sender.java b/src/main/java/com/flowingcode/vaadin/addons/chatassistant/Sender.java new file mode 100644 index 0000000..7c32dbe --- /dev/null +++ b/src/main/java/com/flowingcode/vaadin/addons/chatassistant/Sender.java @@ -0,0 +1,69 @@ +/*- + * #%L + * Chat Assistant Add-on + * %% + * Copyright (C) 2023 Flowing Code + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ +package com.flowingcode.vaadin.addons.chatassistant; + +/** + * Class that represents a chat message sender: + * + *
    + *
  • name: The name of the sender. + *
  • id: a special id to identify the sender. + *
  • avatar: an image that represents the sender. + *
+ * + * @author mmlopez + */ +public class Sender { + + private String name; + private String id; + private String avatar; + + public Sender(String name, String id, String avatar) { + super(); + this.name = name; + this.id = id; + this.avatar = avatar; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getAvatar() { + return avatar; + } + + public void setAvatar(String avatar) { + this.avatar = avatar; + } +} diff --git a/src/main/resources/META-INF/frontend/styles/chat-assistant-styles.css b/src/main/resources/META-INF/frontend/styles/chat-assistant-styles.css new file mode 100644 index 0000000..4738758 --- /dev/null +++ b/src/main/resources/META-INF/frontend/styles/chat-assistant-styles.css @@ -0,0 +1,36 @@ +/*- + * #%L + * Chat Assistant Add-on + * %% + * Copyright (C) 2023 Flowing Code + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ + chat-bot { + --chatbot-avatar-bg-color: var(--lumo-primary-color-10pct); + --chatbot-avatar-margin: 10%; + --chatbot-header-bg-color: var(--lumo-primary-color-50pct); + --chatbot-header-title-color: var(--lumo-header-text-color); + --chatbot-body-bg-color: var(--lumo-primary-color-10pct); + --chatbot-send-button-color: var(--lumo-primary-color); + } + + chat-bot::part(chat-bubble) { + --chat-bubble-color: var(--lumo-success-color); + --chat-bubble-right-color: white; + --chat-bubble-font-color: white;; + --chat-bubble-font-right-color: var(--lumo-contrast-90pct); + --chat-bubble-avatar-color: var(--lumo-secondary-color); + --chat-bubble-delay: 0.2s; + } diff --git a/src/main/resources/META-INF/frontend/styles/static_addon_styles b/src/main/resources/META-INF/frontend/styles/static_addon_styles deleted file mode 100644 index c2a6ed1..0000000 --- a/src/main/resources/META-INF/frontend/styles/static_addon_styles +++ /dev/null @@ -1 +0,0 @@ -Place add-on shareable styles in this folder \ No newline at end of file diff --git a/src/main/resources/META-INF/resources/static_addon_resources b/src/main/resources/META-INF/resources/static_addon_resources deleted file mode 100644 index 70832cc..0000000 --- a/src/main/resources/META-INF/resources/static_addon_resources +++ /dev/null @@ -1 +0,0 @@ -Place static add-on resources in this folder \ No newline at end of file diff --git a/src/test/java/com/flowingcode/vaadin/addons/DemoLayout.java b/src/test/java/com/flowingcode/vaadin/addons/DemoLayout.java index 70abf98..2ee7785 100644 --- a/src/test/java/com/flowingcode/vaadin/addons/DemoLayout.java +++ b/src/test/java/com/flowingcode/vaadin/addons/DemoLayout.java @@ -1,15 +1,15 @@ /*- * #%L - * Template Add-on + * Chat Assistant Add-on * %% * Copyright (C) 2023 Flowing Code * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. diff --git a/src/test/java/com/flowingcode/vaadin/addons/chatbot/ChatAssistantDemo.java b/src/test/java/com/flowingcode/vaadin/addons/chatbot/ChatAssistantDemo.java new file mode 100644 index 0000000..fa04d3d --- /dev/null +++ b/src/test/java/com/flowingcode/vaadin/addons/chatbot/ChatAssistantDemo.java @@ -0,0 +1,79 @@ +/*- + * #%L + * Chat Assistant Add-on + * %% + * Copyright (C) 2023 Flowing Code + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ +package com.flowingcode.vaadin.addons.chatbot; + +import com.flowingcode.vaadin.addons.chatassistant.ChatAssistant; +import com.flowingcode.vaadin.addons.chatassistant.Message; +import com.flowingcode.vaadin.addons.chatassistant.Sender; +import com.flowingcode.vaadin.addons.demo.DemoSource; +import com.vaadin.flow.component.button.Button; +import com.vaadin.flow.component.dependency.CssImport; +import com.vaadin.flow.component.notification.Notification; +import com.vaadin.flow.component.orderedlayout.VerticalLayout; +import com.vaadin.flow.component.textfield.TextArea; +import com.vaadin.flow.router.PageTitle; +import com.vaadin.flow.router.Route; + +@DemoSource +@PageTitle("Chat Assistant Add-on Demo") +@SuppressWarnings("serial") +@Route(value = "chat-assistant/basic-demo", layout = ChatAssistantDemoView.class) +@CssImport("./styles/chat-assistant-styles-demo.css") +public class ChatAssistantDemo extends VerticalLayout { + + public ChatAssistantDemo() { + ChatAssistant chatAssistant = new ChatAssistant(); + TextArea message = new TextArea(); + message.setLabel("Enter a message from the assistant"); + message.setSizeFull(); + + Button chat = new Button("Chat"); + chat.addClickListener( + ev -> { + Message m = + new Message( + message.getValue(), + false, + false, + 0, + false, + new Sender("Assistant", "1", "chatbot.png")); + chatAssistant.sendMessage(m); + message.clear(); + }); + chatAssistant.sendMessage( + new Message( + "Hello, I am here to assist you", + false, + false, + 0, + false, + new Sender("Assistant", "1", "chatbot.png"))); + chatAssistant.toggle(); + chatAssistant.addChatSentListener( + ev -> { + if (ev.isRight()) { + Notification.show(ev.getMessage()); + } + }); + + add(message, chat, chatAssistant); + } +} diff --git a/src/test/java/com/flowingcode/vaadin/addons/template/TemplateDemoView.java b/src/test/java/com/flowingcode/vaadin/addons/chatbot/ChatAssistantDemoView.java similarity index 76% rename from src/test/java/com/flowingcode/vaadin/addons/template/TemplateDemoView.java rename to src/test/java/com/flowingcode/vaadin/addons/chatbot/ChatAssistantDemoView.java index 1c3aecd..e8fe9df 100644 --- a/src/test/java/com/flowingcode/vaadin/addons/template/TemplateDemoView.java +++ b/src/test/java/com/flowingcode/vaadin/addons/chatbot/ChatAssistantDemoView.java @@ -1,6 +1,6 @@ /*- * #%L - * Template Add-on + * Chat Assistant Add-on * %% * Copyright (C) 2023 Flowing Code * %% @@ -17,7 +17,7 @@ * limitations under the License. * #L% */ -package com.flowingcode.vaadin.addons.template; +package com.flowingcode.vaadin.addons.chatbot; import com.flowingcode.vaadin.addons.DemoLayout; import com.flowingcode.vaadin.addons.GithubLink; @@ -27,12 +27,12 @@ @SuppressWarnings("serial") @ParentLayout(DemoLayout.class) -@Route("template") -@GithubLink("https://github.com/FlowingCode/AddonStarter24") -public class TemplateDemoView extends TabbedDemo { +@Route("chat-assistant") +@GithubLink("https://github.com/FlowingCode/ChatAssistant") +public class ChatAssistantDemoView extends TabbedDemo { - public TemplateDemoView() { - addDemo(TemplateDemo.class); + public ChatAssistantDemoView() { + addDemo(ChatAssistantDemo.class); setSizeFull(); } } diff --git a/src/test/java/com/flowingcode/vaadin/addons/template/DemoView.java b/src/test/java/com/flowingcode/vaadin/addons/chatbot/DemoView.java similarity index 88% rename from src/test/java/com/flowingcode/vaadin/addons/template/DemoView.java rename to src/test/java/com/flowingcode/vaadin/addons/chatbot/DemoView.java index 951bdb7..a6b6f4a 100644 --- a/src/test/java/com/flowingcode/vaadin/addons/template/DemoView.java +++ b/src/test/java/com/flowingcode/vaadin/addons/chatbot/DemoView.java @@ -1,15 +1,15 @@ /*- * #%L - * Template Add-on + * Chat Assistant Add-on * %% * Copyright (C) 2023 Flowing Code * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -18,7 +18,7 @@ * #L% */ -package com.flowingcode.vaadin.addons.template; +package com.flowingcode.vaadin.addons.chatbot; import com.vaadin.flow.component.orderedlayout.VerticalLayout; import com.vaadin.flow.router.BeforeEnterEvent; @@ -31,6 +31,6 @@ public class DemoView extends VerticalLayout implements BeforeEnterObserver { @Override public void beforeEnter(BeforeEnterEvent event) { - event.forwardTo(TemplateDemoView.class); + event.forwardTo(ChatAssistantDemoView.class); } } diff --git a/src/test/java/com/flowingcode/vaadin/addons/template/it/AbstractViewTest.java b/src/test/java/com/flowingcode/vaadin/addons/chatbot/it/AbstractViewTest.java similarity index 93% rename from src/test/java/com/flowingcode/vaadin/addons/template/it/AbstractViewTest.java rename to src/test/java/com/flowingcode/vaadin/addons/chatbot/it/AbstractViewTest.java index 87ff695..11b61e3 100644 --- a/src/test/java/com/flowingcode/vaadin/addons/template/it/AbstractViewTest.java +++ b/src/test/java/com/flowingcode/vaadin/addons/chatbot/it/AbstractViewTest.java @@ -1,15 +1,15 @@ /*- * #%L - * Template Add-on + * Chat Assistant Add-on * %% * Copyright (C) 2023 Flowing Code * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -18,7 +18,7 @@ * #L% */ -package com.flowingcode.vaadin.addons.template.it; +package com.flowingcode.vaadin.addons.chatbot.it; import com.vaadin.testbench.ScreenshotOnFailureRule; import com.vaadin.testbench.TestBench; @@ -47,8 +47,7 @@ public abstract class AbstractViewTest extends ParallelTest { private final String route; - @Rule - public ScreenshotOnFailureRule rule = new ScreenshotOnFailureRule(this, true); + @Rule public ScreenshotOnFailureRule rule = new ScreenshotOnFailureRule(this, true); public AbstractViewTest() { this(""); @@ -87,8 +86,7 @@ private static String getURL(String route) { private static final String USE_HUB_PROPERTY = "test.use.hub"; /** - * Returns whether we are using a test hub. This means that the starter is - * running tests in + * Returns whether we are using a test hub. This means that the starter is running tests in * Vaadin's CI environment, and uses TestBench to connect to the testing hub. * * @return whether we are using a test hub diff --git a/src/test/java/com/flowingcode/vaadin/addons/chatbot/it/BasicIT.java b/src/test/java/com/flowingcode/vaadin/addons/chatbot/it/BasicIT.java new file mode 100644 index 0000000..96c11c3 --- /dev/null +++ b/src/test/java/com/flowingcode/vaadin/addons/chatbot/it/BasicIT.java @@ -0,0 +1,53 @@ +/*- + * #%L + * Chat Assistant Add-on + * %% + * Copyright (C) 2023 Flowing Code + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ +package com.flowingcode.vaadin.addons.chatbot.it; + +import com.flowingcode.vaadin.addons.chatbot.it.po.ChatAssistantElement; +import com.flowingcode.vaadin.addons.chatbot.it.po.ChatBubbleElement; +import com.vaadin.flow.component.button.testbench.ButtonElement; +import com.vaadin.flow.component.html.testbench.NativeButtonElement; +import com.vaadin.flow.component.html.testbench.ParagraphElement; +import com.vaadin.flow.component.notification.testbench.NotificationElement; +import com.vaadin.flow.component.textfield.testbench.TextAreaElement; +import com.vaadin.testbench.TestBenchElement; +import org.junit.Assert; +import org.junit.Test; + +public class BasicIT extends AbstractViewTest { + + @Test + public void sendMessageTest() { + ChatAssistantElement element = $(ChatAssistantElement.class).first(); + TestBenchElement input = element.$(TestBenchElement.class).id("msg-input"); + input.sendKeys("hello"); + TestBenchElement button = element.$(NativeButtonElement.class).get(1); + button.click(); + String notificationMessage = $(NotificationElement.class).waitForFirst().getText(); + Assert.assertEquals("hello", notificationMessage); + + TextAreaElement ta = $(TextAreaElement.class).first(); + ta.setValue("What can I do for you?"); + ButtonElement chatButton = $(ButtonElement.class).first(); + chatButton.click(); + ChatBubbleElement cb = element.$(ChatBubbleElement.class).get(2); + String chat = cb.$(ParagraphElement.class).first().getText(); + Assert.assertEquals("What can I do for you?", chat); + } +} diff --git a/src/test/java/com/flowingcode/vaadin/addons/template/it/ViewIT.java b/src/test/java/com/flowingcode/vaadin/addons/chatbot/it/ViewIT.java similarity index 54% rename from src/test/java/com/flowingcode/vaadin/addons/template/it/ViewIT.java rename to src/test/java/com/flowingcode/vaadin/addons/chatbot/it/ViewIT.java index 7e4a499..c38f68c 100644 --- a/src/test/java/com/flowingcode/vaadin/addons/template/it/ViewIT.java +++ b/src/test/java/com/flowingcode/vaadin/addons/chatbot/it/ViewIT.java @@ -1,15 +1,15 @@ /*- * #%L - * Template Add-on + * Chat Assistant Add-on * %% * Copyright (C) 2023 Flowing Code * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -18,7 +18,7 @@ * #L% */ -package com.flowingcode.vaadin.addons.template.it; +package com.flowingcode.vaadin.addons.chatbot.it; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.not; @@ -32,32 +32,33 @@ public class ViewIT extends AbstractViewTest { - private Matcher hasBeenUpgradedToCustomElement = new TypeSafeDiagnosingMatcher() { - - @Override - public void describeTo(Description description) { - description.appendText("a custom element"); - } - - @Override - protected boolean matchesSafely(TestBenchElement item, Description mismatchDescription) { - String script = "let s=arguments[0].shadowRoot; return !!(s&&s.childElementCount)"; - if (!item.getTagName().contains("-")) { - return true; - } - if ((Boolean) item.getCommandExecutor().executeScript(script, item)) { - return true; - } else { - mismatchDescription.appendText(item.getTagName() + " "); - mismatchDescription.appendDescriptionOf(is(not(this))); - return false; - } - } - }; + private Matcher hasBeenUpgradedToCustomElement = + new TypeSafeDiagnosingMatcher() { + + @Override + public void describeTo(Description description) { + description.appendText("a custom element"); + } + + @Override + protected boolean matchesSafely(TestBenchElement item, Description mismatchDescription) { + String script = "let s=arguments[0].shadowRoot; return !!(s&&s.childElementCount)"; + if (!item.getTagName().contains("-")) { + return true; + } + if ((Boolean) item.getCommandExecutor().executeScript(script, item)) { + return true; + } else { + mismatchDescription.appendText(item.getTagName() + " "); + mismatchDescription.appendDescriptionOf(is(not(this))); + return false; + } + } + }; @Test public void componentWorks() { - TestBenchElement element = $("paper-input").first(); + TestBenchElement element = $("chat-bot").first(); assertThat(element, hasBeenUpgradedToCustomElement); } } diff --git a/src/main/java/com/flowingcode/vaadin/addons/template/TemplateAddon.java b/src/test/java/com/flowingcode/vaadin/addons/chatbot/it/po/ChatAssistantElement.java similarity index 57% rename from src/main/java/com/flowingcode/vaadin/addons/template/TemplateAddon.java rename to src/test/java/com/flowingcode/vaadin/addons/chatbot/it/po/ChatAssistantElement.java index 5870ed5..6364aba 100644 --- a/src/main/java/com/flowingcode/vaadin/addons/template/TemplateAddon.java +++ b/src/test/java/com/flowingcode/vaadin/addons/chatbot/it/po/ChatAssistantElement.java @@ -1,6 +1,6 @@ /*- * #%L - * Template Add-on + * Chat Assistant Add-on * %% * Copyright (C) 2023 Flowing Code * %% @@ -17,16 +17,10 @@ * limitations under the License. * #L% */ +package com.flowingcode.vaadin.addons.chatbot.it.po; -package com.flowingcode.vaadin.addons.template; +import com.vaadin.testbench.TestBenchElement; +import com.vaadin.testbench.elementsbase.Element; -import com.vaadin.flow.component.Tag; -import com.vaadin.flow.component.dependency.JsModule; -import com.vaadin.flow.component.dependency.NpmPackage; -import com.vaadin.flow.component.html.Div; - -@SuppressWarnings("serial") -@NpmPackage(value = "@polymer/paper-input", version = "3.2.1") -@JsModule("@polymer/paper-input/paper-input.js") -@Tag("paper-input") -public class TemplateAddon extends Div {} +@Element("chat-bot") +public class ChatAssistantElement extends TestBenchElement {} diff --git a/src/test/java/com/flowingcode/vaadin/addons/chatbot/it/po/ChatBubbleElement.java b/src/test/java/com/flowingcode/vaadin/addons/chatbot/it/po/ChatBubbleElement.java new file mode 100644 index 0000000..789fd86 --- /dev/null +++ b/src/test/java/com/flowingcode/vaadin/addons/chatbot/it/po/ChatBubbleElement.java @@ -0,0 +1,26 @@ +/*- + * #%L + * Chat Assistant Add-on + * %% + * Copyright (C) 2023 Flowing Code + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ +package com.flowingcode.vaadin.addons.chatbot.it.po; + +import com.vaadin.testbench.TestBenchElement; +import com.vaadin.testbench.elementsbase.Element; + +@Element("chat-bubble") +public class ChatBubbleElement extends TestBenchElement {} diff --git a/src/test/java/com/flowingcode/vaadin/addons/template/test/SerializationTest.java b/src/test/java/com/flowingcode/vaadin/addons/chatbot/test/SerializationTest.java similarity index 81% rename from src/test/java/com/flowingcode/vaadin/addons/template/test/SerializationTest.java rename to src/test/java/com/flowingcode/vaadin/addons/chatbot/test/SerializationTest.java index 6c226a2..3e695ac 100644 --- a/src/test/java/com/flowingcode/vaadin/addons/template/test/SerializationTest.java +++ b/src/test/java/com/flowingcode/vaadin/addons/chatbot/test/SerializationTest.java @@ -1,15 +1,15 @@ /*- * #%L - * Template Add-on + * Chat Assistant Add-on * %% * Copyright (C) 2023 Flowing Code * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -17,14 +17,14 @@ * limitations under the License. * #L% */ -package com.flowingcode.vaadin.addons.template.test; +package com.flowingcode.vaadin.addons.chatbot.test; +import com.flowingcode.vaadin.addons.chatassistant.ChatAssistant; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; -import com.flowingcode.vaadin.addons.template.TemplateAddon; import org.junit.Assert; import org.junit.Test; @@ -35,7 +35,8 @@ private void testSerializationOf(Object obj) throws IOException, ClassNotFoundEx try (ObjectOutputStream oos = new ObjectOutputStream(baos)) { oos.writeObject(obj); } - try (ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()))) { + try (ObjectInputStream in = + new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()))) { obj.getClass().cast(in.readObject()); } } @@ -43,7 +44,7 @@ private void testSerializationOf(Object obj) throws IOException, ClassNotFoundEx @Test public void testSerialization() throws ClassNotFoundException, IOException { try { - testSerializationOf(new TemplateAddon()); + testSerializationOf(new ChatAssistant()); } catch (Exception e) { Assert.fail("Problem while testing serialization: " + e.getMessage()); } diff --git a/src/test/java/com/flowingcode/vaadin/addons/template/TemplateDemo.java b/src/test/java/com/flowingcode/vaadin/addons/template/TemplateDemo.java deleted file mode 100644 index 5f6e6ee..0000000 --- a/src/test/java/com/flowingcode/vaadin/addons/template/TemplateDemo.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.flowingcode.vaadin.addons.template; - -import com.flowingcode.vaadin.addons.demo.DemoSource; -import com.vaadin.flow.component.html.Div; -import com.vaadin.flow.router.PageTitle; -import com.vaadin.flow.router.Route; - -@DemoSource -@PageTitle("Template Add-on Demo") -@SuppressWarnings("serial") -@Route(value = "demo", layout = TemplateDemoView.class) -public class TemplateDemo extends Div { - - public TemplateDemo() { - add(new TemplateAddon()); - } -} diff --git a/src/test/resources/META-INF/frontend/styles/chat-assistant-styles-demo.css b/src/test/resources/META-INF/frontend/styles/chat-assistant-styles-demo.css new file mode 100644 index 0000000..d69ef15 --- /dev/null +++ b/src/test/resources/META-INF/frontend/styles/chat-assistant-styles-demo.css @@ -0,0 +1,23 @@ +/*- + * #%L + * Chat Assistant Add-on + * %% + * Copyright (C) 2023 Flowing Code + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ + chat-bot { + --chatbot-avatar-img: url(chatbot.png); + --chatbot-avatar-bg-color: white; + } diff --git a/src/test/resources/META-INF/frontend/styles/shared-styles.css b/src/test/resources/META-INF/frontend/styles/shared-styles.css deleted file mode 100644 index 6680e2d..0000000 --- a/src/test/resources/META-INF/frontend/styles/shared-styles.css +++ /dev/null @@ -1 +0,0 @@ -/*Demo styles*/ \ No newline at end of file diff --git a/src/test/resources/META-INF/resources/chatbot.png b/src/test/resources/META-INF/resources/chatbot.png new file mode 100644 index 0000000000000000000000000000000000000000..c4bf3df6b4adc3778d4efd28fde95747ba740d2c GIT binary patch literal 20632 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 Date: Tue, 22 Aug 2023 14:58:41 -0300 Subject: [PATCH 02/16] docs: use hyphen --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index affd969..93f6a1d 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ # Chat Assistant Add-on -Vaadin Addon that displays a chat assistant floating window using [wc-chatbot](https://github.com/yishiashia/wc-chatbot). +Vaadin Add-on that displays a chat assistant floating window using [wc-chatbot](https://github.com/yishiashia/wc-chatbot). ## Features From bb107fe9319908248ba5884a62f412a3fa6e0b74 Mon Sep 17 00:00:00 2001 From: Martin Lopez Date: Tue, 22 Aug 2023 14:59:49 -0300 Subject: [PATCH 03/16] docs: use correct artifactId --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 93f6a1d..ca09152 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ Add the following dependencies in your pom.xml file: ```xml org.vaadin.addons.flowingcode - chat-assistant + chat-assistant-addon X.Y.Z ``` From 563dd89c966dfff7fa6e92f43cfb87157a4b9f8d Mon Sep 17 00:00:00 2001 From: Martin Lopez Date: Tue, 22 Aug 2023 15:04:16 -0300 Subject: [PATCH 04/16] refactor: change chatbot word in package name --- .../{chatbot => chatassistant}/ChatAssistantDemo.java | 2 +- .../{chatbot => chatassistant}/ChatAssistantDemoView.java | 2 +- .../vaadin/addons/{chatbot => chatassistant}/DemoView.java | 2 +- .../{chatbot => chatassistant}/it/AbstractViewTest.java | 2 +- .../addons/{chatbot => chatassistant}/it/BasicIT.java | 6 +++--- .../vaadin/addons/{chatbot => chatassistant}/it/ViewIT.java | 2 +- .../it/po/ChatAssistantElement.java | 2 +- .../{chatbot => chatassistant}/it/po/ChatBubbleElement.java | 2 +- .../{chatbot => chatassistant}/test/SerializationTest.java | 2 +- 9 files changed, 11 insertions(+), 11 deletions(-) rename src/test/java/com/flowingcode/vaadin/addons/{chatbot => chatassistant}/ChatAssistantDemo.java (98%) rename src/test/java/com/flowingcode/vaadin/addons/{chatbot => chatassistant}/ChatAssistantDemoView.java (95%) rename src/test/java/com/flowingcode/vaadin/addons/{chatbot => chatassistant}/DemoView.java (95%) rename src/test/java/com/flowingcode/vaadin/addons/{chatbot => chatassistant}/it/AbstractViewTest.java (98%) rename src/test/java/com/flowingcode/vaadin/addons/{chatbot => chatassistant}/it/BasicIT.java (90%) rename src/test/java/com/flowingcode/vaadin/addons/{chatbot => chatassistant}/it/ViewIT.java (97%) rename src/test/java/com/flowingcode/vaadin/addons/{chatbot => chatassistant}/it/po/ChatAssistantElement.java (93%) rename src/test/java/com/flowingcode/vaadin/addons/{chatbot => chatassistant}/it/po/ChatBubbleElement.java (93%) rename src/test/java/com/flowingcode/vaadin/addons/{chatbot => chatassistant}/test/SerializationTest.java (96%) diff --git a/src/test/java/com/flowingcode/vaadin/addons/chatbot/ChatAssistantDemo.java b/src/test/java/com/flowingcode/vaadin/addons/chatassistant/ChatAssistantDemo.java similarity index 98% rename from src/test/java/com/flowingcode/vaadin/addons/chatbot/ChatAssistantDemo.java rename to src/test/java/com/flowingcode/vaadin/addons/chatassistant/ChatAssistantDemo.java index fa04d3d..9107955 100644 --- a/src/test/java/com/flowingcode/vaadin/addons/chatbot/ChatAssistantDemo.java +++ b/src/test/java/com/flowingcode/vaadin/addons/chatassistant/ChatAssistantDemo.java @@ -17,7 +17,7 @@ * limitations under the License. * #L% */ -package com.flowingcode.vaadin.addons.chatbot; +package com.flowingcode.vaadin.addons.chatassistant; import com.flowingcode.vaadin.addons.chatassistant.ChatAssistant; import com.flowingcode.vaadin.addons.chatassistant.Message; diff --git a/src/test/java/com/flowingcode/vaadin/addons/chatbot/ChatAssistantDemoView.java b/src/test/java/com/flowingcode/vaadin/addons/chatassistant/ChatAssistantDemoView.java similarity index 95% rename from src/test/java/com/flowingcode/vaadin/addons/chatbot/ChatAssistantDemoView.java rename to src/test/java/com/flowingcode/vaadin/addons/chatassistant/ChatAssistantDemoView.java index e8fe9df..207104a 100644 --- a/src/test/java/com/flowingcode/vaadin/addons/chatbot/ChatAssistantDemoView.java +++ b/src/test/java/com/flowingcode/vaadin/addons/chatassistant/ChatAssistantDemoView.java @@ -17,7 +17,7 @@ * limitations under the License. * #L% */ -package com.flowingcode.vaadin.addons.chatbot; +package com.flowingcode.vaadin.addons.chatassistant; import com.flowingcode.vaadin.addons.DemoLayout; import com.flowingcode.vaadin.addons.GithubLink; diff --git a/src/test/java/com/flowingcode/vaadin/addons/chatbot/DemoView.java b/src/test/java/com/flowingcode/vaadin/addons/chatassistant/DemoView.java similarity index 95% rename from src/test/java/com/flowingcode/vaadin/addons/chatbot/DemoView.java rename to src/test/java/com/flowingcode/vaadin/addons/chatassistant/DemoView.java index a6b6f4a..17157c3 100644 --- a/src/test/java/com/flowingcode/vaadin/addons/chatbot/DemoView.java +++ b/src/test/java/com/flowingcode/vaadin/addons/chatassistant/DemoView.java @@ -18,7 +18,7 @@ * #L% */ -package com.flowingcode.vaadin.addons.chatbot; +package com.flowingcode.vaadin.addons.chatassistant; import com.vaadin.flow.component.orderedlayout.VerticalLayout; import com.vaadin.flow.router.BeforeEnterEvent; diff --git a/src/test/java/com/flowingcode/vaadin/addons/chatbot/it/AbstractViewTest.java b/src/test/java/com/flowingcode/vaadin/addons/chatassistant/it/AbstractViewTest.java similarity index 98% rename from src/test/java/com/flowingcode/vaadin/addons/chatbot/it/AbstractViewTest.java rename to src/test/java/com/flowingcode/vaadin/addons/chatassistant/it/AbstractViewTest.java index 11b61e3..1cbb554 100644 --- a/src/test/java/com/flowingcode/vaadin/addons/chatbot/it/AbstractViewTest.java +++ b/src/test/java/com/flowingcode/vaadin/addons/chatassistant/it/AbstractViewTest.java @@ -18,7 +18,7 @@ * #L% */ -package com.flowingcode.vaadin.addons.chatbot.it; +package com.flowingcode.vaadin.addons.chatassistant.it; import com.vaadin.testbench.ScreenshotOnFailureRule; import com.vaadin.testbench.TestBench; diff --git a/src/test/java/com/flowingcode/vaadin/addons/chatbot/it/BasicIT.java b/src/test/java/com/flowingcode/vaadin/addons/chatassistant/it/BasicIT.java similarity index 90% rename from src/test/java/com/flowingcode/vaadin/addons/chatbot/it/BasicIT.java rename to src/test/java/com/flowingcode/vaadin/addons/chatassistant/it/BasicIT.java index 96c11c3..1984bf6 100644 --- a/src/test/java/com/flowingcode/vaadin/addons/chatbot/it/BasicIT.java +++ b/src/test/java/com/flowingcode/vaadin/addons/chatassistant/it/BasicIT.java @@ -17,10 +17,10 @@ * limitations under the License. * #L% */ -package com.flowingcode.vaadin.addons.chatbot.it; +package com.flowingcode.vaadin.addons.chatassistant.it; -import com.flowingcode.vaadin.addons.chatbot.it.po.ChatAssistantElement; -import com.flowingcode.vaadin.addons.chatbot.it.po.ChatBubbleElement; +import com.flowingcode.vaadin.addons.chatassistant.it.po.ChatAssistantElement; +import com.flowingcode.vaadin.addons.chatassistant.it.po.ChatBubbleElement; import com.vaadin.flow.component.button.testbench.ButtonElement; import com.vaadin.flow.component.html.testbench.NativeButtonElement; import com.vaadin.flow.component.html.testbench.ParagraphElement; diff --git a/src/test/java/com/flowingcode/vaadin/addons/chatbot/it/ViewIT.java b/src/test/java/com/flowingcode/vaadin/addons/chatassistant/it/ViewIT.java similarity index 97% rename from src/test/java/com/flowingcode/vaadin/addons/chatbot/it/ViewIT.java rename to src/test/java/com/flowingcode/vaadin/addons/chatassistant/it/ViewIT.java index c38f68c..e191e13 100644 --- a/src/test/java/com/flowingcode/vaadin/addons/chatbot/it/ViewIT.java +++ b/src/test/java/com/flowingcode/vaadin/addons/chatassistant/it/ViewIT.java @@ -18,7 +18,7 @@ * #L% */ -package com.flowingcode.vaadin.addons.chatbot.it; +package com.flowingcode.vaadin.addons.chatassistant.it; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.not; diff --git a/src/test/java/com/flowingcode/vaadin/addons/chatbot/it/po/ChatAssistantElement.java b/src/test/java/com/flowingcode/vaadin/addons/chatassistant/it/po/ChatAssistantElement.java similarity index 93% rename from src/test/java/com/flowingcode/vaadin/addons/chatbot/it/po/ChatAssistantElement.java rename to src/test/java/com/flowingcode/vaadin/addons/chatassistant/it/po/ChatAssistantElement.java index 6364aba..fd9e07b 100644 --- a/src/test/java/com/flowingcode/vaadin/addons/chatbot/it/po/ChatAssistantElement.java +++ b/src/test/java/com/flowingcode/vaadin/addons/chatassistant/it/po/ChatAssistantElement.java @@ -17,7 +17,7 @@ * limitations under the License. * #L% */ -package com.flowingcode.vaadin.addons.chatbot.it.po; +package com.flowingcode.vaadin.addons.chatassistant.it.po; import com.vaadin.testbench.TestBenchElement; import com.vaadin.testbench.elementsbase.Element; diff --git a/src/test/java/com/flowingcode/vaadin/addons/chatbot/it/po/ChatBubbleElement.java b/src/test/java/com/flowingcode/vaadin/addons/chatassistant/it/po/ChatBubbleElement.java similarity index 93% rename from src/test/java/com/flowingcode/vaadin/addons/chatbot/it/po/ChatBubbleElement.java rename to src/test/java/com/flowingcode/vaadin/addons/chatassistant/it/po/ChatBubbleElement.java index 789fd86..134fab4 100644 --- a/src/test/java/com/flowingcode/vaadin/addons/chatbot/it/po/ChatBubbleElement.java +++ b/src/test/java/com/flowingcode/vaadin/addons/chatassistant/it/po/ChatBubbleElement.java @@ -17,7 +17,7 @@ * limitations under the License. * #L% */ -package com.flowingcode.vaadin.addons.chatbot.it.po; +package com.flowingcode.vaadin.addons.chatassistant.it.po; import com.vaadin.testbench.TestBenchElement; import com.vaadin.testbench.elementsbase.Element; diff --git a/src/test/java/com/flowingcode/vaadin/addons/chatbot/test/SerializationTest.java b/src/test/java/com/flowingcode/vaadin/addons/chatassistant/test/SerializationTest.java similarity index 96% rename from src/test/java/com/flowingcode/vaadin/addons/chatbot/test/SerializationTest.java rename to src/test/java/com/flowingcode/vaadin/addons/chatassistant/test/SerializationTest.java index 3e695ac..48f73d6 100644 --- a/src/test/java/com/flowingcode/vaadin/addons/chatbot/test/SerializationTest.java +++ b/src/test/java/com/flowingcode/vaadin/addons/chatassistant/test/SerializationTest.java @@ -17,7 +17,7 @@ * limitations under the License. * #L% */ -package com.flowingcode.vaadin.addons.chatbot.test; +package com.flowingcode.vaadin.addons.chatassistant.test; import com.flowingcode.vaadin.addons.chatassistant.ChatAssistant; import java.io.ByteArrayInputStream; From a7d287ca252e1507da6cb20758789a8076cfde2f Mon Sep 17 00:00:00 2001 From: Martin Lopez Date: Tue, 22 Aug 2023 15:05:00 -0300 Subject: [PATCH 05/16] docs: remove unnecesary period --- .../flowingcode/vaadin/addons/chatassistant/ChatAssistant.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/flowingcode/vaadin/addons/chatassistant/ChatAssistant.java b/src/main/java/com/flowingcode/vaadin/addons/chatassistant/ChatAssistant.java index 40fc36f..fd76ad3 100644 --- a/src/main/java/com/flowingcode/vaadin/addons/chatassistant/ChatAssistant.java +++ b/src/main/java/com/flowingcode/vaadin/addons/chatassistant/ChatAssistant.java @@ -101,7 +101,7 @@ public void sendMessage(Message message) { * message is sent by the user or programmatically. * * @param listener - * @return Registration object to allow removing the listener. + * @return Registration object to allow removing the listener */ public Registration addChatSentListener(ComponentEventListener listener) { return addListener(ChatSentEvent.class, listener); From 84ddedcb1ce74d0a9e79bf5b8723685e660bafbb Mon Sep 17 00:00:00 2001 From: Martin Lopez Date: Wed, 23 Aug 2023 18:17:44 -0300 Subject: [PATCH 06/16] docs: correct addon name --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ca09152..12415aa 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,7 @@ Then, follow these steps for creating a contibution: This add-on is distributed under Apache License 2.0. For license terms, see LICENSE.txt. -Chat Assistant is written by Flowing Code S.A. +Chat Assistant Add-on is written by Flowing Code S.A. # Developer Guide From 0b956a402bc576c364e7ace81a008bbcad03d99f Mon Sep 17 00:00:00 2001 From: Martin Lopez Date: Wed, 23 Aug 2023 18:28:27 -0300 Subject: [PATCH 07/16] ci: update webdrivermanager to 5.4.1 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 3e0ae9e..0e1597a 100644 --- a/pom.xml +++ b/pom.xml @@ -154,7 +154,7 @@ io.github.bonigarcia webdrivermanager - 5.1.1 + 5.4.1 test From a4bc7913b3e201c8685cdc0ce7270152512e0bc5 Mon Sep 17 00:00:00 2001 From: Martin Lopez Date: Wed, 23 Aug 2023 18:29:14 -0300 Subject: [PATCH 08/16] test: separate test into two independent tests --- .../vaadin/addons/chatassistant/it/BasicIT.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/test/java/com/flowingcode/vaadin/addons/chatassistant/it/BasicIT.java b/src/test/java/com/flowingcode/vaadin/addons/chatassistant/it/BasicIT.java index 1984bf6..8d6c452 100644 --- a/src/test/java/com/flowingcode/vaadin/addons/chatassistant/it/BasicIT.java +++ b/src/test/java/com/flowingcode/vaadin/addons/chatassistant/it/BasicIT.java @@ -33,7 +33,7 @@ public class BasicIT extends AbstractViewTest { @Test - public void sendMessageTest() { + public void sendMessageFromUser() { ChatAssistantElement element = $(ChatAssistantElement.class).first(); TestBenchElement input = element.$(TestBenchElement.class).id("msg-input"); input.sendKeys("hello"); @@ -41,12 +41,16 @@ public void sendMessageTest() { button.click(); String notificationMessage = $(NotificationElement.class).waitForFirst().getText(); Assert.assertEquals("hello", notificationMessage); - + } + + @Test + public void sendMessageFromAssistant() { + ChatAssistantElement element = $(ChatAssistantElement.class).first(); TextAreaElement ta = $(TextAreaElement.class).first(); ta.setValue("What can I do for you?"); ButtonElement chatButton = $(ButtonElement.class).first(); chatButton.click(); - ChatBubbleElement cb = element.$(ChatBubbleElement.class).get(2); + ChatBubbleElement cb = element.$(ChatBubbleElement.class).get(1); String chat = cb.$(ParagraphElement.class).first().getText(); Assert.assertEquals("What can I do for you?", chat); } From 2c199dcc1f8b2203ff36d9fd9fd46ce5540f95d0 Mon Sep 17 00:00:00 2001 From: Martin Lopez Date: Wed, 23 Aug 2023 18:31:39 -0300 Subject: [PATCH 09/16] fix: replace with primitive boolean Replace with primitive boolean because null state is not supported --- .../vaadin/addons/chatassistant/ChatAssistant.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/flowingcode/vaadin/addons/chatassistant/ChatAssistant.java b/src/main/java/com/flowingcode/vaadin/addons/chatassistant/ChatAssistant.java index fd76ad3..8f80761 100644 --- a/src/main/java/com/flowingcode/vaadin/addons/chatassistant/ChatAssistant.java +++ b/src/main/java/com/flowingcode/vaadin/addons/chatassistant/ChatAssistant.java @@ -115,13 +115,13 @@ public Registration addChatSentListener(ComponentEventListener li @DomEvent("sent") public static class ChatSentEvent extends ComponentEvent { private final String message; - private Boolean right; + private boolean right; public ChatSentEvent( ChatAssistant source, boolean fromClient, @EventData("event.detail.message.message") String message, - @EventData("event.detail.message.right") Boolean right) { + @EventData("event.detail.message.right") boolean right) { super(source, fromClient); this.message = message.replaceAll("^<[^>]+>|<[^>]+>$", ""); this.right = right; @@ -131,7 +131,7 @@ public String getMessage() { return message; } - public Boolean isRight() { + public boolean isRight() { return right; } From de1930a74883f4503159c8a0a2cc93b4fb6a36eb Mon Sep 17 00:00:00 2001 From: Martin Lopez Date: Wed, 23 Aug 2023 18:33:39 -0300 Subject: [PATCH 10/16] remove: remove method that is not needed --- .../vaadin/addons/chatassistant/ChatAssistant.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/main/java/com/flowingcode/vaadin/addons/chatassistant/ChatAssistant.java b/src/main/java/com/flowingcode/vaadin/addons/chatassistant/ChatAssistant.java index 8f80761..2e70292 100644 --- a/src/main/java/com/flowingcode/vaadin/addons/chatassistant/ChatAssistant.java +++ b/src/main/java/com/flowingcode/vaadin/addons/chatassistant/ChatAssistant.java @@ -134,9 +134,5 @@ public String getMessage() { public boolean isRight() { return right; } - - public ChatAssistant getChatBot() { - return (ChatAssistant) source; - } } } From 0ee70ff1dbb9d11db45c5ed6a82865f657ea0a20 Mon Sep 17 00:00:00 2001 From: Martin Lopez Date: Wed, 23 Aug 2023 18:34:38 -0300 Subject: [PATCH 11/16] fix: use correct types in constructor --- .../flowingcode/vaadin/addons/chatassistant/Message.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/flowingcode/vaadin/addons/chatassistant/Message.java b/src/main/java/com/flowingcode/vaadin/addons/chatassistant/Message.java index 274e7ad..0269953 100644 --- a/src/main/java/com/flowingcode/vaadin/addons/chatassistant/Message.java +++ b/src/main/java/com/flowingcode/vaadin/addons/chatassistant/Message.java @@ -54,10 +54,10 @@ public Message(String content) { public Message( String content, - Boolean continued, - Boolean right, + boolean continued, + boolean right, Integer delay, - Boolean loading, + boolean loading, Sender sender) { super(); this.content = content; From 6fd8d79047b04f94d0f297397a1e4391af918dcf Mon Sep 17 00:00:00 2001 From: Martin Lopez Date: Wed, 23 Aug 2023 18:36:21 -0300 Subject: [PATCH 12/16] refactor: remove unnecesary semicolon --- .../META-INF/frontend/styles/chat-assistant-styles.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/META-INF/frontend/styles/chat-assistant-styles.css b/src/main/resources/META-INF/frontend/styles/chat-assistant-styles.css index 4738758..5d85bc4 100644 --- a/src/main/resources/META-INF/frontend/styles/chat-assistant-styles.css +++ b/src/main/resources/META-INF/frontend/styles/chat-assistant-styles.css @@ -29,7 +29,7 @@ chat-bot::part(chat-bubble) { --chat-bubble-color: var(--lumo-success-color); --chat-bubble-right-color: white; - --chat-bubble-font-color: white;; + --chat-bubble-font-color: white; --chat-bubble-font-right-color: var(--lumo-contrast-90pct); --chat-bubble-avatar-color: var(--lumo-secondary-color); --chat-bubble-delay: 0.2s; From 170dd3e2788793a402e14ab284bf2191b49f8dcf Mon Sep 17 00:00:00 2001 From: Martin Lopez Date: Thu, 24 Aug 2023 17:33:57 -0300 Subject: [PATCH 13/16] build: add lombok dependency --- pom.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pom.xml b/pom.xml index 0e1597a..0e5141b 100644 --- a/pom.xml +++ b/pom.xml @@ -123,6 +123,12 @@ com.vaadin vaadin-core + + org.projectlombok + lombok + provided + 1.18.28 + org.slf4j slf4j-simple From 381dd0620b5868f12eb1673e55d161adec7d55cd Mon Sep 17 00:00:00 2001 From: Martin Lopez Date: Thu, 24 Aug 2023 20:06:17 -0300 Subject: [PATCH 14/16] refactor: use lombok to implement builder pattern --- .../addons/chatassistant/ChatAssistant.java | 2 +- .../vaadin/addons/chatassistant/Message.java | 84 +++---------------- .../vaadin/addons/chatassistant/Sender.java | 43 +++------- 3 files changed, 24 insertions(+), 105 deletions(-) diff --git a/src/main/java/com/flowingcode/vaadin/addons/chatassistant/ChatAssistant.java b/src/main/java/com/flowingcode/vaadin/addons/chatassistant/ChatAssistant.java index 2e70292..6062365 100644 --- a/src/main/java/com/flowingcode/vaadin/addons/chatassistant/ChatAssistant.java +++ b/src/main/java/com/flowingcode/vaadin/addons/chatassistant/ChatAssistant.java @@ -51,7 +51,7 @@ public class ChatAssistant extends Div { * @param message */ public void sendMessage(String message) { - sendMessage(new Message(message)); + sendMessage(Message.builder().content(message).build()); } /** Shows or hides the chat window */ diff --git a/src/main/java/com/flowingcode/vaadin/addons/chatassistant/Message.java b/src/main/java/com/flowingcode/vaadin/addons/chatassistant/Message.java index 0269953..398a15a 100644 --- a/src/main/java/com/flowingcode/vaadin/addons/chatassistant/Message.java +++ b/src/main/java/com/flowingcode/vaadin/addons/chatassistant/Message.java @@ -19,6 +19,13 @@ */ package com.flowingcode.vaadin.addons.chatassistant; +import java.util.Optional; +import elemental.json.Json; +import elemental.json.JsonObject; +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + /** * Class that represents a chat message. It contains several configurations to control the * appearance of the message, such as: @@ -33,86 +40,17 @@ * * @author mmlopez */ +@Getter +@Setter +@Builder public class Message { private String content; private boolean continued; private boolean right; + @Builder.Default private Integer delay = 0; private boolean loading; private Sender sender; - public Message(String content) { - this( - content, - false, - true, - 0, - false, - new Sender("Guest", "2", "https://ui-avatars.com/api/?name=Guest")); - } - - public Message( - String content, - boolean continued, - boolean right, - Integer delay, - boolean loading, - Sender sender) { - super(); - this.content = content; - this.continued = continued; - this.right = right; - this.delay = delay; - this.loading = loading; - this.sender = sender; - } - - public String getContent() { - return content; - } - - public void setContent(String content) { - this.content = content; - } - - public boolean isContinued() { - return continued; - } - - public void setContinued(boolean continued) { - this.continued = continued; - } - - public boolean isRight() { - return right; - } - - public void setRight(boolean right) { - this.right = right; - } - - public Integer getDelay() { - return delay; - } - - public void setDelay(Integer delay) { - this.delay = delay; - } - - public boolean isLoading() { - return loading; - } - - public void setLoading(boolean loading) { - this.loading = loading; - } - - public Sender getSender() { - return sender; - } - - public void setSender(Sender sender) { - this.sender = sender; - } } diff --git a/src/main/java/com/flowingcode/vaadin/addons/chatassistant/Sender.java b/src/main/java/com/flowingcode/vaadin/addons/chatassistant/Sender.java index 7c32dbe..6582177 100644 --- a/src/main/java/com/flowingcode/vaadin/addons/chatassistant/Sender.java +++ b/src/main/java/com/flowingcode/vaadin/addons/chatassistant/Sender.java @@ -19,6 +19,14 @@ */ package com.flowingcode.vaadin.addons.chatassistant; +import java.util.Optional; +import elemental.json.Json; +import elemental.json.JsonObject; +import elemental.json.JsonValue; +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + /** * Class that represents a chat message sender: * @@ -30,40 +38,13 @@ * * @author mmlopez */ +@Getter +@Setter +@Builder public class Sender { private String name; private String id; private String avatar; - - public Sender(String name, String id, String avatar) { - super(); - this.name = name; - this.id = id; - this.avatar = avatar; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getAvatar() { - return avatar; - } - - public void setAvatar(String avatar) { - this.avatar = avatar; - } + } From 0cc6bb3683dd99101dfeaca9567fe09cb3163a33 Mon Sep 17 00:00:00 2001 From: Martin Lopez Date: Thu, 24 Aug 2023 20:07:52 -0300 Subject: [PATCH 15/16] fix: fix string manipulation issues by using JsonObject --- .../addons/chatassistant/ChatAssistant.java | 28 +------------------ .../vaadin/addons/chatassistant/Message.java | 11 ++++++++ .../vaadin/addons/chatassistant/Sender.java | 8 ++++++ 3 files changed, 20 insertions(+), 27 deletions(-) diff --git a/src/main/java/com/flowingcode/vaadin/addons/chatassistant/ChatAssistant.java b/src/main/java/com/flowingcode/vaadin/addons/chatassistant/ChatAssistant.java index 6062365..6ab0457 100644 --- a/src/main/java/com/flowingcode/vaadin/addons/chatassistant/ChatAssistant.java +++ b/src/main/java/com/flowingcode/vaadin/addons/chatassistant/ChatAssistant.java @@ -67,33 +67,7 @@ public void toggle() { public void sendMessage(Message message) { getElement() .executeJs( - "setTimeout(() => { this.sendMessage('" - + message.getContent() - + "', {\n" - + " continued: " - + message.isContinued() - + ",\n" - + " right: " - + message.isRight() - + ",\n" - + " delay: " - + message.getDelay() - + ",\n" - + " loading: " - + message.isLoading() - + ",\n" - + " sender: {\n" - + " name: '" - + message.getSender().getName() - + "',\n" - + " id: '" - + message.getSender().getId() - + "',\n" - + " avatar: '" - + message.getSender().getAvatar() - + "'\n" - + " }\n" - + "}) });"); + "setTimeout(() => {debugger;this.sendMessage(null, JSON.parse($0));})", message.getJsonObject().toJson()); } /** diff --git a/src/main/java/com/flowingcode/vaadin/addons/chatassistant/Message.java b/src/main/java/com/flowingcode/vaadin/addons/chatassistant/Message.java index 398a15a..d632a74 100644 --- a/src/main/java/com/flowingcode/vaadin/addons/chatassistant/Message.java +++ b/src/main/java/com/flowingcode/vaadin/addons/chatassistant/Message.java @@ -52,5 +52,16 @@ public class Message { private Integer delay = 0; private boolean loading; private Sender sender; + + public JsonObject getJsonObject() { + JsonObject result = Json.createObject(); + result.put("message", content); + result.put("continued", continued); + result.put("right", right); + Optional.ofNullable(delay).ifPresent(value->result.put("delay", delay)); + result.put("loading", loading); + Optional.ofNullable(sender).ifPresent(value->result.put("sender", sender.getJsonObject())); + return result; + } } diff --git a/src/main/java/com/flowingcode/vaadin/addons/chatassistant/Sender.java b/src/main/java/com/flowingcode/vaadin/addons/chatassistant/Sender.java index 6582177..bd206c2 100644 --- a/src/main/java/com/flowingcode/vaadin/addons/chatassistant/Sender.java +++ b/src/main/java/com/flowingcode/vaadin/addons/chatassistant/Sender.java @@ -47,4 +47,12 @@ public class Sender { private String id; private String avatar; + public JsonValue getJsonObject() { + JsonObject result = Json.createObject(); + Optional.ofNullable(name).ifPresent(value->result.put("name", name)); + Optional.ofNullable(id).ifPresent(value->result.put("id", id)); + Optional.ofNullable(avatar).ifPresent(value->result.put("avatar", avatar)); + return result; + } + } From 1696b70c3a4d177dbf356f826ac30dc77ff8e5c1 Mon Sep 17 00:00:00 2001 From: Martin Lopez Date: Thu, 24 Aug 2023 20:08:34 -0300 Subject: [PATCH 16/16] test: fix failing test by obtaining inner text from correct place --- .../com/flowingcode/vaadin/addons/chatassistant/it/BasicIT.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/com/flowingcode/vaadin/addons/chatassistant/it/BasicIT.java b/src/test/java/com/flowingcode/vaadin/addons/chatassistant/it/BasicIT.java index 8d6c452..70a3ea4 100644 --- a/src/test/java/com/flowingcode/vaadin/addons/chatassistant/it/BasicIT.java +++ b/src/test/java/com/flowingcode/vaadin/addons/chatassistant/it/BasicIT.java @@ -51,7 +51,7 @@ public void sendMessageFromAssistant() { ButtonElement chatButton = $(ButtonElement.class).first(); chatButton.click(); ChatBubbleElement cb = element.$(ChatBubbleElement.class).get(1); - String chat = cb.$(ParagraphElement.class).first().getText(); + String chat = cb.getText(); Assert.assertEquals("What can I do for you?", chat); } }