diff --git a/OSS_LICENSES.txt b/OSS_LICENSES.txt index 19171c5b..64507d44 100644 --- a/OSS_LICENSES.txt +++ b/OSS_LICENSES.txt @@ -1,4 +1,4 @@ -Created on 07-08-2024 at 16:11:49 +Created on 29-08-2024 at 11:10:23 { "@babel/code-frame@7.24.2": { @@ -63,19 +63,19 @@ Created on 07-08-2024 at 16:11:49 "licenseFile": "node_modules/@braintree/sanitize-url/LICENSE", "copyright": "Copyright (c) 2017 Braintree" }, - "@cognigy/chat-components@0.29.0": { + "@cognigy/chat-components@0.33.1": { "licenses": "MIT*", "licenseFile": "node_modules/@cognigy/chat-components/LICENSE", "copyright": "Copyright (c) 2024 Cognigy GmbH" }, - "@cognigy/socket-client@5.0.0-beta.17": { + "@cognigy/socket-client@5.0.0-beta.20": { "licenses": "MIT*", "publisher": "Robin Schuster", "email": "r.schuster@cognigy.com", "licenseFile": "node_modules/@cognigy/socket-client/LICENSE", "copyright": "Copyright (c) 2019 Cognigy GmbH" }, - "@cognigy/webchat@3.0.0": { + "@cognigy/webchat@3.3.0": { "licenses": "MIT*", "publisher": "Cognigy GmbH", "email": "info@cognigy.com", @@ -213,6 +213,27 @@ Created on 07-08-2024 at 16:11:49 "licenseFile": "node_modules/@emotion/react/node_modules/@emotion/weak-memoize/LICENSE", "copyright": "Copyright (c) Emotion team and other contributors" }, + "@floating-ui/core@1.6.7": { + "licenses": "MIT", + "repository": "https://github.com/floating-ui/floating-ui", + "publisher": "atomiks", + "licenseFile": "node_modules/@floating-ui/core/LICENSE", + "copyright": "Copyright (c) 2021-present Floating UI contributors" + }, + "@floating-ui/dom@1.6.10": { + "licenses": "MIT", + "repository": "https://github.com/floating-ui/floating-ui", + "publisher": "atomiks", + "licenseFile": "node_modules/@floating-ui/dom/LICENSE", + "copyright": "Copyright (c) 2021-present Floating UI contributors" + }, + "@floating-ui/utils@0.2.7": { + "licenses": "MIT", + "repository": "https://github.com/floating-ui/floating-ui", + "publisher": "atomiks", + "licenseFile": "node_modules/@floating-ui/utils/LICENSE", + "copyright": "Copyright (c) 2021-present Floating UI contributors" + }, "@fontsource/figtree@5.0.19": { "licenses": "OFL-1.1", "repository": "https://github.com/fontsource/font-files", @@ -228,7 +249,7 @@ Created on 07-08-2024 at 16:11:49 "licenseFile": "node_modules/@reduxjs/toolkit/LICENSE", "copyright": "Copyright (c) 2018 Mark Erikson" }, - "@socket.io/component-emitter@3.1.0": { + "@socket.io/component-emitter@3.1.2": { "licenses": "MIT", "repository": "https://github.com/socketio/emitter", "licenseFile": "node_modules/@socket.io/component-emitter/LICENSE", @@ -457,7 +478,7 @@ Created on 07-08-2024 at 16:11:49 "licenseFile": "node_modules/aws4/LICENSE", "copyright": "Copyright 2013 Michael Hart (michael.hart.au@gmail.com)" }, - "axios@1.6.4": { + "axios@1.7.4": { "licenses": "MIT", "repository": "https://github.com/axios/axios", "publisher": "Matt Zabriskie", @@ -906,17 +927,17 @@ Created on 07-08-2024 at 16:11:49 "licenseFile": "node_modules/end-of-stream/LICENSE", "copyright": "Copyright (c) 2014 Mathias Buus" }, - "engine.io-client@6.5.3": { + "engine.io-client@6.5.4": { "licenses": "MIT", "repository": "https://github.com/socketio/engine.io-client", "licenseFile": "node_modules/engine.io-client/LICENSE", "copyright": "Copyright (c) 2014-2015 Automattic " }, - "engine.io-parser@5.2.2": { + "engine.io-parser@5.2.3": { "licenses": "MIT", - "repository": "https://github.com/socketio/engine.io-parser", + "repository": "https://github.com/socketio/socket.io", "licenseFile": "node_modules/engine.io-parser/LICENSE", - "copyright": "Copyright (c) 2016 Guillermo Rauch (@rauchg)" + "copyright": "Copyright (c) 2014-present Guillermo Rauch and Socket.IO contributors" }, "enquirer@2.4.1": { "licenses": "MIT", @@ -1927,7 +1948,7 @@ Created on 07-08-2024 at 16:11:49 "licenseFile": "node_modules/qs/LICENSE.md", "copyright": "Copyright (c) 2014, Nathan LaFreniere and other [contributors](https://github.com/ljharb/qs/graphs/contributors). All rights reserved." }, - "qs@6.12.0": { + "qs@6.13.0": { "licenses": "BSD-3-Clause", "repository": "https://github.com/ljharb/qs", "licenseFile": "node_modules/url/node_modules/qs/LICENSE.md", @@ -2014,6 +2035,13 @@ Created on 07-08-2024 at 16:11:49 "licenseFile": "node_modules/react-textarea-autosize/LICENSE", "copyright": "Copyright (c) 2013 Andrey Popp" }, + "react-tooltip@5.28.0": { + "licenses": "MIT", + "repository": "https://github.com/ReactTooltip/react-tooltip", + "publisher": "ReactTooltip", + "licenseFile": "node_modules/react-tooltip/LICENSE", + "copyright": "Copyright (c) 2022 ReactTooltip Team Github" + }, "react-transition-group@4.4.5": { "licenses": "BSD-3-Clause", "repository": "https://github.com/reactjs/react-transition-group", @@ -2260,7 +2288,7 @@ Created on 07-08-2024 at 16:11:49 "licenseFile": "node_modules/slide/LICENSE", "copyright": "Copyright (c) Isaac Z. Schlueter" }, - "socket.io-client@4.7.2": { + "socket.io-client@4.7.5": { "licenses": "MIT", "repository": "https://github.com/socketio/socket.io-client", "licenseFile": "node_modules/socket.io-client/LICENSE", @@ -2656,14 +2684,14 @@ Created on 07-08-2024 at 16:11:49 "licenseFile": "node_modules/wrappy/LICENSE", "copyright": "Copyright (c) Isaac Z. Schlueter and Contributors" }, - "ws@8.11.0": { + "ws@8.17.1": { "licenses": "MIT", "repository": "https://github.com/websockets/ws", "publisher": "Einar Otto Stangvik", "email": "einaros@gmail.com", "url": "http://2x.io", "licenseFile": "node_modules/ws/LICENSE", - "copyright": "Copyright (c) 2011 Einar Otto Stangvik " + "copyright": "Copyright (c) 2011 Einar Otto Stangvik . Copyright (c) 2013 Arnout Kazemier and contributors. Copyright (c) 2016 Luigi Pinca and contributors" }, "xmlhttprequest-ssl@2.0.0": { "licenses": "MIT", diff --git a/README.md b/README.md index 380277be..4528dd41 100644 --- a/README.md +++ b/README.md @@ -17,10 +17,6 @@ You need an installed version of `Node.js` to build your Webchat. Clone this rep For development purposes, you can utilize `npm run dev`. This command spawns an HTTP server on port 8080, showcasing the current form of the webchat directly from the source code. It automatically reloads upon updating source files, simplifying the development process. It automatically reloads when you make changes, streamlining the development process. -## Compatibility Builds - -The `npm run bundle` command generates bundle files for the Webchat itself and basic Webchat plugins. Additionally, it produces a second version of each bundle ending in `.legacy.js`. These builds maintain the same feature set as the regular ones but are converted into an older JavaScript standard, enhancing compatibility for older browsers that lack support for modern JavaScript features, such as Internet Explorer 11. When you run the command `npm run bundle`, it creates bundle files for the Webchat along with some basic Webchat plugins. This command also produces a second version of each bundle, which has `.legacy.js` at the end of its name. These builds have the same features as the regular ones but are converted into an older JavaScript standard. This enhances compatibility for older browsers that don't support modern JavaScript features, such as Internet Explorer 11. - ## Migration Guide If you are already using Webchat 2 and want to migrate to Webchat v3, please follow the [migration guide](https://docs.cognigy.com/webchat/migration/) here. diff --git a/cypress/e2e/engagement.cy.ts b/cypress/e2e/engagement.cy.ts index c2cb1aea..bb1e61e6 100644 --- a/cypress/e2e/engagement.cy.ts +++ b/cypress/e2e/engagement.cy.ts @@ -79,6 +79,9 @@ describe("Engagement Message", () => { unreadMessages: { enablePreview: false, }, + homeScreen: { + enabled: false, + } }, }); cy.get("[data-cognigy-webchat-toggle]").click().click(); @@ -137,6 +140,9 @@ describe("Engagement Message", () => { unreadMessages: { enablePreview: false, }, + homeScreen: { + enabled: false, + } }, }); cy.wait(500); diff --git a/cypress/e2e/homeScreen.cy.ts b/cypress/e2e/homeScreen.cy.ts index bf0942d7..ec63bd64 100644 --- a/cypress/e2e/homeScreen.cy.ts +++ b/cypress/e2e/homeScreen.cy.ts @@ -255,6 +255,7 @@ describe('Home Screen', () => { { type: "phone_number", title: "Phone number starter", + payload: "123456789" }, ] } @@ -263,8 +264,8 @@ describe('Home Screen', () => { }); cy.openWebchat(); cy.get('button').contains('Postback starter'); - cy.get('button').contains('Web URL starter'); - cy.get('button').contains('Phone number starter'); + cy.get('a').contains('Web URL starter'); + cy.get('a').contains('Phone number starter'); }); it('has postback buttons that starts a conversation when clicked', () => { @@ -291,7 +292,7 @@ describe('Home Screen', () => { cy.get('.webchat-message-row.user .chat-bubble', { timeout: 100 }).contains('Postback starter'); }); - it('has web url button with correct role when configured', () => { + it('has web url button with correct aria-label when configured', () => { cy.initMockWebchat({ settings: { homeScreen: { @@ -311,7 +312,6 @@ describe('Home Screen', () => { } }); cy.openWebchat(); - cy.get('.webchat-homescreen-button').should('have.attr', 'role', 'link'); cy.get('.webchat-homescreen-button').should('have.attr', 'aria-label', 'Web URL starter. Opens in new tab'); }); diff --git a/cypress/e2e/messages/audio.cy.ts b/cypress/e2e/messages/audio.cy.ts index 5a7548d5..aa3839e4 100644 --- a/cypress/e2e/messages/audio.cy.ts +++ b/cypress/e2e/messages/audio.cy.ts @@ -27,15 +27,5 @@ describe("Message with Audio", () => { cy.withMessageFixture('audio', () => { cy.get(".webchat-message-row .webchat-media-template-audio"); }) - }) - - it("should have sr-only default alternate text for audio", () => { - cy.withMessageFixture('audio', () => { - cy - .get(".webchat-message-row .webchat-media-template-audio span") - .contains("Attachment Audio") - .should("not.be.visible"); - }) }) - }) \ No newline at end of file diff --git a/cypress/e2e/messages/downloadableImage.cy.ts b/cypress/e2e/messages/downloadableImage.cy.ts index 05a00a10..118074f3 100644 --- a/cypress/e2e/messages/downloadableImage.cy.ts +++ b/cypress/e2e/messages/downloadableImage.cy.ts @@ -20,7 +20,7 @@ describe("Message with Downloadable Image", () => { it("should render download button", () => { cy.withMessageFixture('downloadableImage', () => { cy - .get("button").contains("Download"); + .get(".webchat-message-row a").contains("Download"); }) }); }) \ No newline at end of file diff --git a/cypress/e2e/messages/image.cy.ts b/cypress/e2e/messages/image.cy.ts index 6306bb42..851a55d0 100644 --- a/cypress/e2e/messages/image.cy.ts +++ b/cypress/e2e/messages/image.cy.ts @@ -8,7 +8,7 @@ describe("Message with Image", { retries: 3 }, () => { it("should render image", () => { cy.withMessageFixture("image", () => { - cy.get(".webchat-message-row > div > img").should("be.visible"); + cy.get(".webchat-message-row img").should("be.visible"); }); }); @@ -20,15 +20,14 @@ describe("Message with Image", { retries: 3 }, () => { it("should have alt attibute", () => { cy.withMessageFixture("image", () => { - cy.get(".webchat-message-row > div > img") - .should("have.attr", "alt") - .and("match", /Attachment Image/); + cy.get(".webchat-media-template-image img") + .should("have.attr", "alt", "Attachment Image") }); }); it("should render the image in a fixed aspect ratio", () => { cy.withMessageFixture("image", () => { - cy.get(".webchat-media-template-image > img") + cy.get(".webchat-media-template-image img") .should("be.visible") .then(element => { const imageRatio = (element.innerWidth() / element.innerHeight()).toFixed(1); @@ -51,7 +50,7 @@ describe("Message with Image", { retries: 3 }, () => { cy.startConversation(); cy.withMessageFixture("image", () => { - cy.get(".webchat-media-template-image > img") + cy.get(".webchat-media-template-image img") .should("be.visible") .then(element => { expect(element.innerHeight().toFixed()).to.equal( diff --git a/cypress/e2e/messages/video.cy.ts b/cypress/e2e/messages/video.cy.ts index 532d6d5e..b9c27d64 100644 --- a/cypress/e2e/messages/video.cy.ts +++ b/cypress/e2e/messages/video.cy.ts @@ -32,12 +32,4 @@ describe("Message with Video", () => { cy.get(".webchat-message-row .webchat-media-template-video"); }) }) - - it("should have sr-only default alternate text for video", () => { - cy.withMessageFixture('video', () => { - cy.get(".webchat-message-row .webchat-media-template-video .sr-only") - .contains("Attachment Video") - .should("not.be.visible"); - }) - }) }) \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 77a19b0b..6e282d79 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,27 +1,27 @@ { "name": "@cognigy/webchat", - "version": "3.0.0", + "version": "3.3.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@cognigy/webchat", - "version": "3.0.0", + "version": "3.3.0", "license": "SEE LICENSE IN LICENSE", "dependencies": { "@braintree/sanitize-url": "^6.0.0", - "@cognigy/chat-components": "0.29.0", - "@cognigy/socket-client": "5.0.0-beta.17", + "@cognigy/chat-components": "0.33.1", + "@cognigy/socket-client": "5.0.0-beta.20", "@emotion/cache": "^10.0.29", "@emotion/react": "^11.7.1", "@emotion/serialize": "1.1.3", - "@emotion/styled": "^11.6.0", + "@emotion/styled": "^11.12.0", "@reduxjs/toolkit": "^2.2.6", "@types/react-transition-group": "4.4.10", - "axios": "1.6.4", - "classnames": "2.3.2", + "axios": "1.7.4", + "classnames": "^2.5.1", "cypress-real-events": "^1.7.0", - "dompurify": "2.4.9", + "dompurify": "^2.5.6", "license-checker": "25.0.1", "lodash": "^4.17.21", "moment": "^2.29.4", @@ -828,9 +828,9 @@ } }, "node_modules/@cognigy/chat-components": { - "version": "0.29.0", - "resolved": "https://registry.npmjs.org/@cognigy/chat-components/-/chat-components-0.29.0.tgz", - "integrity": "sha512-ImEV1duNy2/OZASu0XT4FY5c+GyJU2iD65+YphxnzHBPomOtzUHFu1H/nzWu3s9CEKBaf6L/tRjNHBIs8tHBfA==", + "version": "0.33.1", + "resolved": "https://registry.npmjs.org/@cognigy/chat-components/-/chat-components-0.33.1.tgz", + "integrity": "sha512-J5sJjTrvv/dZ6RKgxOxRowbPDYFp7B2G3j9jPytYKzAxlhzDRA3mA2DVOMflXFPASR82tkp6RqZmygQSppaRrw==", "dependencies": { "@braintree/sanitize-url": "^6.0.4", "@fontsource/figtree": "5.0.19", @@ -840,6 +840,7 @@ "moment": "^2.30.1", "react-flatpickr": "^3.10.13", "react-player": "2.16.0", + "react-tooltip": "5.28.0", "remarkable": "^2.0.1", "swiper": "^11.1.1" }, @@ -854,12 +855,12 @@ "integrity": "sha512-cTOAhc36AalkjtBpfG6O8JimdTMWNXjiePT2xQH/ppBGi/4uIpmj8eKyIkMJErXWARyINV/sB38yf8JCLF5pbQ==" }, "node_modules/@cognigy/socket-client": { - "version": "5.0.0-beta.17", - "resolved": "https://registry.npmjs.org/@cognigy/socket-client/-/socket-client-5.0.0-beta.17.tgz", - "integrity": "sha512-iKRigOlEYlRiH5/1oGVN4TrTGZ6+NyEs3qfefDvt2EXc5IKxXxYbqyYj1ngci3WCW1uVsX80Dy2IdXRInZG3mw==", + "version": "5.0.0-beta.20", + "resolved": "https://registry.npmjs.org/@cognigy/socket-client/-/socket-client-5.0.0-beta.20.tgz", + "integrity": "sha512-IPuUKcHe+7CA5gVdzXGUaVuDG0GQhN83aMmyiEACPFiSU9iP7/b0rxiijXAgMIfTDp0obrLlPaAg5kMlgIAeBw==", "dependencies": { "detect-browser": "^4.8.0", - "socket.io-client": "4.7.2", + "socket.io-client": "4.7.5", "url": "0.11.3", "uuid": "9.0.1" } @@ -960,15 +961,16 @@ } }, "node_modules/@emotion/babel-plugin": { - "version": "11.11.0", - "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz", - "integrity": "sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==", + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.12.0.tgz", + "integrity": "sha512-y2WQb+oP8Jqvvclh8Q55gLUyb7UFvgv7eJfsj7td5TToBrIUtPay2kMrZi4xjq9qw2vD0ZR5fSho0yqoFgX7Rw==", + "license": "MIT", "dependencies": { "@babel/helper-module-imports": "^7.16.7", "@babel/runtime": "^7.18.3", - "@emotion/hash": "^0.9.1", - "@emotion/memoize": "^0.8.1", - "@emotion/serialize": "^1.1.2", + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/serialize": "^1.2.0", "babel-plugin-macros": "^3.1.0", "convert-source-map": "^1.5.0", "escape-string-regexp": "^4.0.0", @@ -977,6 +979,37 @@ "stylis": "4.2.0" } }, + "node_modules/@emotion/babel-plugin/node_modules/@emotion/memoize": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz", + "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==", + "license": "MIT" + }, + "node_modules/@emotion/babel-plugin/node_modules/@emotion/serialize": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.0.tgz", + "integrity": "sha512-jACuBa9SlYajnpIVXB+XOXnfJHyckDfe6fOpORIM6yhBDlqGuExvDdZYHDQGoDf3bZXGv7tNr+LpLjJqiEQ6EA==", + "license": "MIT", + "dependencies": { + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/unitless": "^0.9.0", + "@emotion/utils": "^1.4.0", + "csstype": "^3.0.2" + } + }, + "node_modules/@emotion/babel-plugin/node_modules/@emotion/unitless": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.9.0.tgz", + "integrity": "sha512-TP6GgNZtmtFaFcsOgExdnfxLLpRDla4Q66tnenA9CktvVSdNKDvMVuUah4QvWPIpNjrWsGg3qeGo9a43QooGZQ==", + "license": "MIT" + }, + "node_modules/@emotion/babel-plugin/node_modules/@emotion/utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.0.tgz", + "integrity": "sha512-spEnrA1b6hDR/C68lC2M7m6ALPUHZC0lIY7jAS/B/9DuuO1ZP04eov8SMv/6fwRd8pzmsn2AuJEznRREWlQrlQ==", + "license": "MIT" + }, "node_modules/@emotion/babel-plugin/node_modules/convert-source-map": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", @@ -999,18 +1032,26 @@ } }, "node_modules/@emotion/hash": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz", - "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==" + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz", + "integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==", + "license": "MIT" }, "node_modules/@emotion/is-prop-valid": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.2.tgz", - "integrity": "sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.3.0.tgz", + "integrity": "sha512-SHetuSLvJDzuNbOdtPVbq6yMMMlLoW5Q94uDqJZqy50gcmAjxFkVqmzqSGEFq9gT2iMuIeKV1PXVWmvUhuZLlQ==", + "license": "MIT", "dependencies": { - "@emotion/memoize": "^0.8.1" + "@emotion/memoize": "^0.9.0" } }, + "node_modules/@emotion/is-prop-valid/node_modules/@emotion/memoize": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz", + "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==", + "license": "MIT" + }, "node_modules/@emotion/memoize": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", @@ -1094,16 +1135,17 @@ "integrity": "sha512-zM9PFmgVSqBw4zL101Q0HrBVTGmpAxFZH/pYx/cjJT5advXguvcgjHFTCaIO3enL/xr89vK2bh0Mfyj9aa0ANA==" }, "node_modules/@emotion/styled": { - "version": "11.11.0", - "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.11.0.tgz", - "integrity": "sha512-hM5Nnvu9P3midq5aaXj4I+lnSfNi7Pmd4EWk1fOZ3pxookaQTNew6bp4JaCBYM4HVFZF9g7UjJmsUmC2JlxOng==", + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.12.0.tgz", + "integrity": "sha512-2l60kuKm8OKbyFYlVutpwFGoeIoftJAHX4udQwpaO4HNoGyvxFLXiEU56/UGCyrwxr76C93eOdVnGewZeC7AEw==", + "license": "MIT", "dependencies": { "@babel/runtime": "^7.18.3", - "@emotion/babel-plugin": "^11.11.0", - "@emotion/is-prop-valid": "^1.2.1", - "@emotion/serialize": "^1.1.2", + "@emotion/babel-plugin": "^11.12.0", + "@emotion/is-prop-valid": "^1.3.0", + "@emotion/serialize": "^1.2.0", "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1", - "@emotion/utils": "^1.2.1" + "@emotion/utils": "^1.3.0" }, "peerDependencies": { "@emotion/react": "^11.0.0-rc.0", @@ -1115,10 +1157,36 @@ } } }, + "node_modules/@emotion/styled/node_modules/@emotion/memoize": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz", + "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==", + "license": "MIT" + }, + "node_modules/@emotion/styled/node_modules/@emotion/serialize": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.0.tgz", + "integrity": "sha512-jACuBa9SlYajnpIVXB+XOXnfJHyckDfe6fOpORIM6yhBDlqGuExvDdZYHDQGoDf3bZXGv7tNr+LpLjJqiEQ6EA==", + "license": "MIT", + "dependencies": { + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/unitless": "^0.9.0", + "@emotion/utils": "^1.4.0", + "csstype": "^3.0.2" + } + }, + "node_modules/@emotion/styled/node_modules/@emotion/unitless": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.9.0.tgz", + "integrity": "sha512-TP6GgNZtmtFaFcsOgExdnfxLLpRDla4Q66tnenA9CktvVSdNKDvMVuUah4QvWPIpNjrWsGg3qeGo9a43QooGZQ==", + "license": "MIT" + }, "node_modules/@emotion/styled/node_modules/@emotion/utils": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.1.tgz", - "integrity": "sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg==" + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.0.tgz", + "integrity": "sha512-spEnrA1b6hDR/C68lC2M7m6ALPUHZC0lIY7jAS/B/9DuuO1ZP04eov8SMv/6fwRd8pzmsn2AuJEznRREWlQrlQ==", + "license": "MIT" }, "node_modules/@emotion/stylis": { "version": "0.8.5", @@ -1231,6 +1299,28 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/@floating-ui/core": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.7.tgz", + "integrity": "sha512-yDzVT/Lm101nQ5TCVeK65LtdN7Tj4Qpr9RTXJ2vPFLqtLxwOrpoxAHAJI8J3yYWUc40J0BDBheaitK5SJmno2g==", + "dependencies": { + "@floating-ui/utils": "^0.2.7" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.6.10", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.10.tgz", + "integrity": "sha512-fskgCFv8J8OamCmyun8MfjB1Olfn+uZKjOKZ0vhYF3gRmEUXcGOjxWL8bBr7i4kIuPZ2KD2S3EUIOxnjC8kl2A==", + "dependencies": { + "@floating-ui/core": "^1.6.0", + "@floating-ui/utils": "^0.2.7" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.7.tgz", + "integrity": "sha512-X8R8Oj771YRl/w+c1HqAC1szL8zWQRwFvgDwT129k9ACdBoud/+/rX9V0qiMl6LWUdP9voC2nDVZYPMQQsb6eA==" + }, "node_modules/@fontsource/figtree": { "version": "5.0.19", "resolved": "https://registry.npmjs.org/@fontsource/figtree/-/figtree-5.0.19.tgz", @@ -1509,9 +1599,9 @@ } }, "node_modules/@socket.io/component-emitter": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", - "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==" + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", + "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==" }, "node_modules/@types/body-parser": { "version": "1.19.5", @@ -2877,11 +2967,11 @@ "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==" }, "node_modules/axios": { - "version": "1.6.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.4.tgz", - "integrity": "sha512-heJnIs6N4aa1eSthhN9M5ioILu8Wi8vmQW9iHQ9NUvfkJb0lEEDUiIdQNAuBtfUt3FxReaKdpQA5DbmMOqzF/A==", + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.4.tgz", + "integrity": "sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw==", "dependencies": { - "follow-redirects": "^1.15.4", + "follow-redirects": "^1.15.6", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } @@ -3341,9 +3431,10 @@ } }, "node_modules/classnames": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz", - "integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==" + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz", + "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==", + "license": "MIT" }, "node_modules/clean-stack": { "version": "2.2.0", @@ -4393,9 +4484,10 @@ } }, "node_modules/dompurify": { - "version": "2.4.9", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.4.9.tgz", - "integrity": "sha512-iHtnxYMotKgOTvxIqq677JsKHvCOkAFqj9x8Mek2zdeHW1XjuFKwjpmZeMaXQRQ8AbJZDbcRz/+r1QhwvFtmQg==" + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.5.6.tgz", + "integrity": "sha512-zUTaUBO8pY4+iJMPE1B9XlO2tXVYIcEA4SNGtvDELzTSCQO7RzH+j7S180BmhmJId78lqGU2z19vgVx2Sxs/PQ==", + "license": "(MPL-2.0 OR Apache-2.0)" }, "node_modules/eastasianwidth": { "version": "0.2.0", @@ -4462,21 +4554,21 @@ } }, "node_modules/engine.io-client": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.5.3.tgz", - "integrity": "sha512-9Z0qLB0NIisTRt1DZ/8U2k12RJn8yls/nXMZLn+/N8hANT3TcYjKFKcwbw5zFQiN4NTde3TSY9zb79e1ij6j9Q==", + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.5.4.tgz", + "integrity": "sha512-GeZeeRjpD2qf49cZQ0Wvh/8NJNfeXkXXcoGh+F77oEAgo9gUHwT1fCRxSNU+YEEaysOJTnsFHmM5oAcPy4ntvQ==", "dependencies": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.3.1", "engine.io-parser": "~5.2.1", - "ws": "~8.11.0", + "ws": "~8.17.1", "xmlhttprequest-ssl": "~2.0.0" } }, "node_modules/engine.io-parser": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.2.tgz", - "integrity": "sha512-RcyUFKA93/CXH20l4SoVvzZfrSDMOTUS3bWVpTt2FuFP+XYrL8i8oonHP7WInRyVHXh0n/ORtoeiE1os+8qkSw==", + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", + "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==", "engines": { "node": ">=10.0.0" } @@ -9182,6 +9274,19 @@ "react": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, + "node_modules/react-tooltip": { + "version": "5.28.0", + "resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-5.28.0.tgz", + "integrity": "sha512-R5cO3JPPXk6FRbBHMO0rI9nkUG/JKfalBSQfZedZYzmqaZQgq7GLzF8vcCWx6IhUCKg0yPqJhXIzmIO5ff15xg==", + "dependencies": { + "@floating-ui/dom": "^1.6.1", + "classnames": "^2.3.0" + }, + "peerDependencies": { + "react": ">=16.14.0", + "react-dom": ">=16.14.0" + } + }, "node_modules/react-transition-group": { "version": "4.4.5", "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", @@ -10061,9 +10166,9 @@ } }, "node_modules/socket.io-client": { - "version": "4.7.2", - "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.2.tgz", - "integrity": "sha512-vtA0uD4ibrYD793SOIAwlo8cj6haOeMHrGvwPxJsxH7CeIksqJ+3Zc06RvWTIFgiSqx4A3sOnTXpfAEE2Zyz6w==", + "version": "4.7.5", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.5.tgz", + "integrity": "sha512-sJ/tqHOCe7Z50JCBCXrsY3I2k03iOiUe+tj1OmKeD2lXPiGH/RUCdTZFoqVyN7l1MnpIzPrGtLcijffmeouNlQ==", "dependencies": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.3.2", @@ -11286,9 +11391,9 @@ "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==" }, "node_modules/url/node_modules/qs": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.12.0.tgz", - "integrity": "sha512-trVZiI6RMOkO476zLGaBIzszOdFPnCCXHPG9kn0yuS1uz6xdVxPfZdB3vUig9pxPFDM9BRAgz/YUIVQ1/vuiUg==", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", "dependencies": { "side-channel": "^1.0.6" }, @@ -11780,27 +11885,6 @@ "url": "https://opencollective.com/webpack" } }, - "node_modules/webpack-dev-server/node_modules/ws": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", - "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", - "dev": true, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, "node_modules/webpack-merge": { "version": "5.10.0", "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", @@ -12131,15 +12215,15 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, "node_modules/ws": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", - "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", "engines": { "node": ">=10.0.0" }, "peerDependencies": { "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" + "utf-8-validate": ">=5.0.2" }, "peerDependenciesMeta": { "bufferutil": { diff --git a/package.json b/package.json index b3db1089..b0a91548 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@cognigy/webchat", - "version": "3.0.0", + "version": "3.3.0", "description": "Webchat Widget for Cognigy.AI", "author": "Cognigy GmbH ", "contributors": [ @@ -29,18 +29,18 @@ }, "dependencies": { "@braintree/sanitize-url": "^6.0.0", - "@cognigy/chat-components": "0.29.0", - "@cognigy/socket-client": "5.0.0-beta.17", + "@cognigy/chat-components": "0.33.1", + "@cognigy/socket-client": "5.0.0-beta.20", "@emotion/cache": "^10.0.29", "@emotion/react": "^11.7.1", "@emotion/serialize": "1.1.3", - "@emotion/styled": "^11.6.0", + "@emotion/styled": "^11.12.0", "@reduxjs/toolkit": "^2.2.6", "@types/react-transition-group": "4.4.10", - "axios": "1.6.4", - "classnames": "2.3.2", + "axios": "1.7.4", + "classnames": "2.5.1", "cypress-real-events": "^1.7.0", - "dompurify": "2.4.9", + "dompurify": "2.5.6", "license-checker": "25.0.1", "lodash": "^4.17.21", "moment": "^2.29.4", diff --git a/src/common/interfaces/message.ts b/src/common/interfaces/message.ts index bab095ad..96d97e3c 100644 --- a/src/common/interfaces/message.ts +++ b/src/common/interfaces/message.ts @@ -6,7 +6,7 @@ export interface IBaseMessage { prevMessage?: IMessage; source: string; text?: string; - timestamp: number; + timestamp?: number; } export interface IUserMessage extends IBaseMessage { diff --git a/src/webchat-embed/embedded-webchat-styles.css b/src/webchat-embed/embedded-webchat-styles.css index 7819f99f..cb52a0e6 100644 --- a/src/webchat-embed/embedded-webchat-styles.css +++ b/src/webchat-embed/embedded-webchat-styles.css @@ -75,7 +75,6 @@ @media screen and (min-width: 576px) and (max-height: 870px) { [data-cognigy-webchat-root] [data-cognigy-webchat] { height: calc(100% - 90px); - min-height: 558px; } } diff --git a/src/webchat-ui/components/WebchatUI.tsx b/src/webchat-ui/components/WebchatUI.tsx index af105575..d10fbe62 100644 --- a/src/webchat-ui/components/WebchatUI.tsx +++ b/src/webchat-ui/components/WebchatUI.tsx @@ -67,7 +67,7 @@ import XAppOverlay from "./functional/xapp-overlay/XAppOverlay"; import { getSourceBackgroundColor } from "../utils/sourceMapping"; import type { Options } from "@cognigy/socket-client/lib/interfaces/options"; import speechOutput from "./plugins/speech-output"; -import getMessagesListWithoutPrivacyMessage from "../utils/filter-out-privacy-message"; +import getMessagesListWithoutControlCommands from "../utils/filter-out-control-commands"; export interface WebchatUIProps { currentSession: string; @@ -128,6 +128,7 @@ export interface WebchatUIProps { fileUploadError: boolean; onSetFileUploadError: (hasError: boolean) => void; + onShowChatScreen: () => void; showPrevConversations: boolean; onSetShowPrevConversations: (show: boolean) => void; prevConversations: PrevConversationsState; @@ -201,6 +202,7 @@ const RegularLayoutContentWrapper = styled.div(({ theme }) => ({ display: "flex", flexDirection: "column", backgroundColor: theme.white, + overflow: "auto", "&.slide-in-enter": { transform: "translateX(100%)", @@ -740,31 +742,63 @@ export class WebchatUI extends React.PureComponent< options, }); } else { + this.props.onSwitchSession(); this.props.onSendMessage(text, data, options); } }; - handleStartConversation = () => { - if (!this.props.config.settings.privacyNotice.enabled || this.props.hasAcceptedTerms) { - const { initialSessionId } = this.props.config; - if (!initialSessionId) { - this.props.onSwitchSession(); - } - if (initialSessionId && initialSessionId !== this.props.currentSession) { - this.props.onSwitchSession(initialSessionId); - } + handleSendActionButtonMessageFromTeaser = ( + text?: string, + data?: any, + options?: Partial, + ) => { + this.props.onSetShowHomeScreen(false); + this.props.onSetShowChatOptionsScreen(false); + + if (this.props.config.settings.privacyNotice.enabled && !this.props.hasAcceptedTerms) { + this.props.onSetStoredMessage({ + text, + data, + options, + }); + } else { + this.props.onShowChatScreen(); + this.props.onSendMessage(text, data, options); } + }; - if (!this.props.open) this.props.onToggle(); + handleStartConversation = () => { this.props.onSetShowHomeScreen(false); this.props.onSetShowChatOptionsScreen(false); + + const showPrivacyScreen = this.props.config.settings.privacyNotice.enabled && !this.props.hasAcceptedTerms; + if (!showPrivacyScreen) { + this.props.onShowChatScreen(); + } }; + handleFabClick = () => { + this.props.onToggle(); + + const homeScreenEnabled = this.props.config.settings.homeScreen.enabled === true; + if (homeScreenEnabled) { + this.setState({ lastUnseenMessageText: "" }); + } else { + this.handleStartConversation(); + } + } + openConversationFromTeaser = () => { - // in this case we always open to current session this.props.onToggle(); this.props.onSetShowHomeScreen(false); this.props.onSetShowChatOptionsScreen(false); + + const showPrivacyScreen = this.props.config.settings.privacyNotice.enabled && !this.props.hasAcceptedTerms; + if (showPrivacyScreen) { + this.setState({ lastUnseenMessageText: "" }); + } else { + this.props.onShowChatScreen(); + } }; render() { @@ -800,6 +834,7 @@ export class WebchatUI extends React.PureComponent< onSetHasGivenRating, onSetShowPrevConversations, onSetShowChatOptionsScreen, + onShowChatScreen, onSwitchSession, requestRatingScreenTitle, customRatingTitle, @@ -946,7 +981,7 @@ export class WebchatUI extends React.PureComponent< config={config} onEmitAnalytics={onEmitAnalytics} onSendActionButtonMessage={ - this.handleSendActionButtonMessage + this.handleSendActionButtonMessageFromTeaser } onHideTeaserMessage={onHideTeaserMessage} wasOpen={wasOpen} @@ -974,7 +1009,7 @@ export class WebchatUI extends React.PureComponent< ) : ( { - onSwitchSession(); onSetShowHomeScreen(true); onClose(); // Restore focus to chat toggle button this.chatToggleButtonRef?.current?.focus?.(); } - // TODO implement proper navigation solution const handleOnGoBack = () => { if (!showChatOptionsScreen && !showRatingScreen) { onSetShowPrevConversations(false); @@ -1100,13 +1134,13 @@ export class WebchatUI extends React.PureComponent< const handleAcceptTerms = () => { onAcceptTerms(this.props?.options?.userId || ""); + onShowChatScreen(); const data = { _cognigy: { controlCommands: [{ type: "acceptPrivacyPolicy" }], }, }; - this.props.onSendMessage("", data); }; @@ -1141,6 +1175,7 @@ export class WebchatUI extends React.PureComponent< onSetShowPrevConversations={onSetShowPrevConversations} onSwitchSession={onSwitchSession} config={config} + currentSession={currentSession} /> ); @@ -1347,7 +1382,7 @@ export class WebchatUI extends React.PureComponent< // Find privacy message and remove it from the messages list (these message types are not displayed in the chat log). // If we do not remove, it will cause the collatation of the first user message. - const messagesExcludingPrivacyMessage = getMessagesListWithoutPrivacyMessage(messages); + const messagesExcludingPrivacyMessage = getMessagesListWithoutControlCommands(messages, ["acceptPrivacyPolicy"]); return ( <> @@ -1356,9 +1391,13 @@ export class WebchatUI extends React.PureComponent< {messagesExcludingPrivacyMessage.map((message, index) => { // Lookahead if there is a user reply - const hasReply = messages + const hasReply = messagesExcludingPrivacyMessage .slice(index + 1) - .some(message => message.source === "user"); + .some( + message => + message.source === "user" && + !(message?.data?._cognigy as any)?.controlCommands, + ); return ( this.props.onSetFullscreenMessage(message)} openXAppOverlay={openXAppOverlay} plugins={messagePlugins} - prevMessage={messages?.[index - 1]} + prevMessage={messagesExcludingPrivacyMessage?.[index - 1]} theme={this.state.theme} /> ); diff --git a/src/webchat-ui/components/presentational/HomeScreen.tsx b/src/webchat-ui/components/presentational/HomeScreen.tsx index 29bc94b5..25bace12 100644 --- a/src/webchat-ui/components/presentational/HomeScreen.tsx +++ b/src/webchat-ui/components/presentational/HomeScreen.tsx @@ -210,8 +210,12 @@ export const HomeScreen: React.FC = props => { }, [showHomeScreen]); return ( - -

Home Screen

+ +

Home Screen

{config?.settings?.layout?.logoUrl ? ( @@ -244,18 +248,20 @@ export const HomeScreen: React.FC = props => { > {homeScreen.welcomeText || "Welcome to the Cognigy Webchat"} - - - + {homeScreen?.conversationStarters?.enabled && ( + + + + )} ({ justifyContent: "space-between", alignItems: "center", padding: 20, + overflowY: "auto", })); const PrivacyMessage = styled.div(() => ({ diff --git a/src/webchat-ui/components/presentational/TeaserMessage.tsx b/src/webchat-ui/components/presentational/TeaserMessage.tsx index e2428372..d9ddd2dd 100644 --- a/src/webchat-ui/components/presentational/TeaserMessage.tsx +++ b/src/webchat-ui/components/presentational/TeaserMessage.tsx @@ -88,7 +88,9 @@ export const TeaserMessage = (props: ITeaserMessageProps) => { wasOpen, } = props; - const buttons: IWebchatButton[] = config.settings.teaserMessage.conversationStarters.starters; + const { teaserMessage } = config.settings; + + const buttons: IWebchatButton[] = teaserMessage.conversationStarters.starters; const isDesktopMedia = useMediaQuery({ query: "(min-width: 576px)" }); @@ -155,7 +157,7 @@ export const TeaserMessage = (props: ITeaserMessageProps) => { {messageText} - {!wasOpen && ( + {!wasOpen && teaserMessage?.conversationStarters?.enabled && ( ({ display: "flex", padding: "0 20px", flexDirection: "column", + overflowY: "auto", })); const DividerWrapper = styled.div(() => ({ diff --git a/src/webchat-ui/components/presentational/previous-conversations/ConversationsList.tsx b/src/webchat-ui/components/presentational/previous-conversations/ConversationsList.tsx index 7f2a6e42..13d809c4 100644 --- a/src/webchat-ui/components/presentational/previous-conversations/ConversationsList.tsx +++ b/src/webchat-ui/components/presentational/previous-conversations/ConversationsList.tsx @@ -55,13 +55,14 @@ const StartButton = styled(PrimaryButton)(() => ({ interface IPrevConversationsListProps { config: IWebchatConfig; + currentSession?: string; conversations: PrevConversationsState; onSetShowPrevConversations: (show: boolean) => void; onSwitchSession: (sessionId?: string, conversation?: PrevConversationsState[string]) => void; } export const PrevConversationsList = (props: IPrevConversationsListProps) => { - const { conversations, config, onSetShowPrevConversations, onSwitchSession } = props; + const { conversations, config, onSetShowPrevConversations, onSwitchSession, currentSession } = props; // we sort the conversation based on last message timestamp // result: the last updated conversation goes on top @@ -91,7 +92,9 @@ export const PrevConversationsList = (props: IPrevConversationsListProps) => { const switchSession = useCallback( (sessionId?: string, conversation?: PrevConversationsState[string]) => { - onSwitchSession(sessionId, conversation); + if (sessionId && sessionId !== currentSession) { + onSwitchSession(sessionId, conversation); + } onSetShowPrevConversations(false); }, [], diff --git a/src/webchat-ui/components/presentational/previous-conversations/ConversationsListItem.tsx b/src/webchat-ui/components/presentational/previous-conversations/ConversationsListItem.tsx index 21b270e6..d5950610 100644 --- a/src/webchat-ui/components/presentational/previous-conversations/ConversationsListItem.tsx +++ b/src/webchat-ui/components/presentational/previous-conversations/ConversationsListItem.tsx @@ -7,6 +7,7 @@ import { getAvatars, getLastMessagePreview, getParticipants, getRelativeTime } f import { IWebchatConfig } from "../../../../common/interfaces/webchat-config"; import { PrevConversationsState } from "../../../../webchat/store/previous-conversations/previous-conversations-reducer"; import { Typography } from "@cognigy/chat-components"; +import { IMessage } from "../../../../common/interfaces/message"; const ListItem = styled.div(({ theme }) => ({ display: "flex", @@ -101,7 +102,9 @@ interface IConversationsListItemProps { export const ConversationsListItem = (props: IConversationsListItemProps) => { const { sessionId, conversation, config, index, switchSession } = props; - const avatars = getAvatars(conversation.messages); + const messages = conversation.messages as IMessage[] + + const avatars = getAvatars(messages); const handleClick = () => { switchSession(sessionId, conversation); @@ -136,12 +139,12 @@ export const ConversationsListItem = (props: IConversationsListItemProps) => {
- {getLastMessagePreview(conversation.messages)} + {getLastMessagePreview(messages)} - {getParticipants(conversation.messages, config)} + {getParticipants(messages, config)} - {getRelativeTime(conversation.messages)} + {getRelativeTime(messages)}
diff --git a/src/webchat-ui/utils/filter-out-control-commands.ts b/src/webchat-ui/utils/filter-out-control-commands.ts new file mode 100644 index 00000000..2166bcb9 --- /dev/null +++ b/src/webchat-ui/utils/filter-out-control-commands.ts @@ -0,0 +1,20 @@ +import { IMessageEvent } from "../../common/interfaces/event"; +import { IMessage } from "../../common/interfaces/message"; + +const EXCLUDE_CC_TYPES = ["acceptPrivacyPolicy", "setRating"]; + +const getMessagesListWithoutControlCommands = ( + messages: (IMessage | IMessageEvent)[], + types: string[] = EXCLUDE_CC_TYPES, +) => { + return messages.filter(message => { + if (message.data?._cognigy && (message.data._cognigy as any).controlCommands) { + return !(message.data._cognigy as any).controlCommands.some((controlCommand: any) => + types.includes(controlCommand.type), + ); + } + return true; + }); +}; + +export default getMessagesListWithoutControlCommands; diff --git a/src/webchat-ui/utils/filter-out-privacy-message.ts b/src/webchat-ui/utils/filter-out-privacy-message.ts deleted file mode 100644 index f8e7957d..00000000 --- a/src/webchat-ui/utils/filter-out-privacy-message.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { IMessage } from "../../common/interfaces/message"; - -const getMessagesListWithoutPrivacyMessage = (messages: IMessage[]) => { - return messages.filter(message => { - if (message.data?._cognigy && (message.data._cognigy as any).controlCommands) { - return !(message.data._cognigy as any).controlCommands.some((controlCommand: any) => controlCommand.type === 'acceptPrivacyPolicy'); - } - return true; - }); -} - -export default getMessagesListWithoutPrivacyMessage; \ No newline at end of file diff --git a/src/webchat/components/ConnectedWebchatUI.tsx b/src/webchat/components/ConnectedWebchatUI.tsx index 42a2ca67..e0295a29 100644 --- a/src/webchat/components/ConnectedWebchatUI.tsx +++ b/src/webchat/components/ConnectedWebchatUI.tsx @@ -2,7 +2,7 @@ import { WebchatUI, WebchatUIProps } from "../../webchat-ui"; import { connect } from "react-redux"; import { StoreState } from "../store/store"; import { sendMessage, triggerEngagementMessage } from '../store/messages/message-middleware'; -import { setInputMode, setFullscreenMessage, setOpen, toggleOpen, setScrollToPosition, setLastScrolledPosition, setShowHomeScreen, setShowPrevConversations, setShowChatOptionsScreen, setHasAcceptedTerms, UIState, setStoredMessage } from '../store/ui/ui-reducer'; +import { setInputMode, setFullscreenMessage, setOpen, toggleOpen, setScrollToPosition, setLastScrolledPosition, setShowHomeScreen, showChatScreen, setShowPrevConversations, setShowChatOptionsScreen, setHasAcceptedTerms, UIState, setStoredMessage } from '../store/ui/ui-reducer'; import { getPluginsForMessage, isFullscreenPlugin } from '../../plugins/helper'; import { connect as doConnect } from "../store/connection/connection-middleware"; import { setHasGivenRating, showRatingScreen } from "../store/rating/rating-reducer"; @@ -79,6 +79,7 @@ export const ConnectedWebchatUI = connect dispatch(setShowHomeScreen(show)), onSetShowPrevConversations: (show: boolean) => dispatch(setShowPrevConversations(show)), onSetShowChatOptionsScreen: (show: boolean) => dispatch(setShowChatOptionsScreen(show)), + onShowChatScreen: () => dispatch(showChatScreen()), onSwitchSession: (sessionId?: string, conversation?: PrevConversationsState[string]) => dispatch(switchSession(sessionId, conversation)), onAcceptTerms: (userId: string) => dispatch(setHasAcceptedTerms(userId)), onSetStoredMessage: (message: UIState['storedMessage']) => dispatch(setStoredMessage(message)), diff --git a/src/webchat/components/Webchat.tsx b/src/webchat/components/Webchat.tsx index df3448ec..79872be1 100644 --- a/src/webchat/components/Webchat.tsx +++ b/src/webchat/components/Webchat.tsx @@ -6,7 +6,7 @@ import { ConnectedWebchatUI, FromProps } from './ConnectedWebchatUI'; import { MessagePlugin } from '../../common/interfaces/message-plugin'; import { sendMessage } from '../store/messages/message-middleware'; import { MessageSender } from '../../webchat-ui/interfaces'; -import { setHasAcceptedTerms, setOpen, setShowHomeScreen, toggleOpen } from '../store/ui/ui-reducer'; +import { setHasAcceptedTerms, setOpen, setShowHomeScreen, showChatScreen, toggleOpen } from '../store/ui/ui-reducer'; import { loadConfig } from '../store/config/config-middleware'; import { connect } from '../store/connection/connection-middleware'; import { EventEmitter } from 'events'; @@ -22,6 +22,7 @@ import { isDisabledDueToConnectivity } from '../helper/connectivity'; import { createNotification } from '../../webchat-ui/components/presentational/Notifications'; import { getStorage } from '../helper/storage'; import { hasAcceptedTermsInStorage } from '../helper/privacyPolicy'; +import { setUserId } from '../store/options/options-reducer'; export interface WebchatProps extends FromProps { url: string; @@ -73,6 +74,9 @@ export class Webchat extends React.PureComponent { if (this.props.options?.sessionId) { this.store.dispatch(setInitialSessionId(this.props.options.sessionId)); } + if (this.props.options?.userId) { + this.store.dispatch(setUserId(this.props.options?.userId)); + } } componentWillUnmount() { @@ -135,7 +139,8 @@ export class Webchat extends React.PureComponent { } startConversation = () => { - this.store.dispatch(setShowHomeScreen(false)); + this.store.dispatch(setShowHomeScreen(false)); + this.store.dispatch(showChatScreen()); } on = (event, handler) => { diff --git a/src/webchat/helper/storage.ts b/src/webchat/helper/storage.ts index c455d1bd..4b752884 100644 --- a/src/webchat/helper/storage.ts +++ b/src/webchat/helper/storage.ts @@ -25,8 +25,8 @@ export const getAllConversations = ( currentURLtoken?: string, ) => { return Object.keys(storage).reduce((acc, item) => { - // skip missing userId or sessionId - if (!currentSessionId || !currentUserId || !currentURLtoken) return acc; + // skip missing userId or URLtoken + if (!currentUserId || !currentURLtoken) return acc; const data = storage.getItem(item) || ""; diff --git a/src/webchat/store/autoinject/autoinject-middleware.ts b/src/webchat/store/autoinject/autoinject-middleware.ts index 8b3fc747..aa08d6a5 100644 --- a/src/webchat/store/autoinject/autoinject-middleware.ts +++ b/src/webchat/store/autoinject/autoinject-middleware.ts @@ -3,24 +3,24 @@ import { StoreState } from "../store"; import { autoInjectHandled, TAutoInjectAction, triggerAutoInject } from './autoinject-reducer'; import { Webchat } from "../../components/Webchat"; import { IWebchatConfig } from "../../../common/interfaces/webchat-config"; -import getMessagesListWithoutPrivacyMessage from "../../../webchat-ui/utils/filter-out-privacy-message"; +import getMessagesListWithoutControlCommands from "../../../webchat-ui/utils/filter-out-control-commands"; export const createAutoInjectMiddleware = (webchat: Webchat): Middleware => api => next => (action: TAutoInjectAction) => { switch (action.type) { case 'SET_CONFIG': case 'SET_CONNECTED': - case 'SET_OPEN': + case 'SHOW_CHAT_SCREEN': case 'SET_OPTIONS': { const nextActionResult = next(action); (() => { const state = api.getState(); - const { isAutoInjectHandled: isAutoInjectTriggered, isConfiguredOnce, isConnectedOnce, isOpenedOnce, isSessionRestoredOnce } = state.autoInject; + const { isAutoInjectHandled: isAutoInjectTriggered, isConfiguredOnce, isConnectedOnce, isChatOpenedOnce, isSessionRestoredOnce } = state.autoInject; if (isAutoInjectTriggered) return; - if (!isConfiguredOnce || !isConnectedOnce || !isOpenedOnce || !isSessionRestoredOnce) + if (!isConfiguredOnce || !isConnectedOnce || !isChatOpenedOnce || !isSessionRestoredOnce) return; api.dispatch(triggerAutoInject()); @@ -50,11 +50,11 @@ export const createAutoInjectMiddleware = (webchat: Webchat): Middleware message.source !== 'engagement'); - // Exclude privacy policy accepted message type from filtered message list - const messagesExcludingEngagementAndPrivacyMessage = getMessagesListWithoutPrivacyMessage(messagesExcludingEngagementMessages); - const isEmptyExceptEngagementAndPrivacyMessage = messagesExcludingEngagementAndPrivacyMessage.length === 0; + // Exclude controlCommands messages from filtered message list + const messagesExcludingControlCommands = getMessagesListWithoutControlCommands(messagesExcludingEngagementMessages); + const isEmptyExceptEngagementAndControlCommands = messagesExcludingControlCommands.length === 0; - if (!isEmptyExceptEngagementAndPrivacyMessage) { + if (!isEmptyExceptEngagementAndControlCommands) { break; } } diff --git a/src/webchat/store/autoinject/autoinject-reducer.ts b/src/webchat/store/autoinject/autoinject-reducer.ts index 46371700..d0250df9 100644 --- a/src/webchat/store/autoinject/autoinject-reducer.ts +++ b/src/webchat/store/autoinject/autoinject-reducer.ts @@ -2,10 +2,10 @@ import { Reducer } from "redux"; import { SetConfigAction } from '../config/config-reducer'; import { SetConnectedAction } from '../connection/connection-reducer'; import { SetOptionsAction } from "../options/options-reducer"; -import { SetOpenAction } from '../ui/ui-reducer'; +import { ShowChatScreenAction } from '../ui/ui-reducer'; const getInitialState = () => ({ - isOpenedOnce: false, + isChatOpenedOnce: false, isConnectedOnce: false, isConfiguredOnce: false, isSessionRestoredOnce: false, @@ -34,7 +34,7 @@ export type TAutoInjectResetAction = ReturnType; export type TAutoInjectAction = | SetConnectedAction - | SetOpenAction + | ShowChatScreenAction | SetOptionsAction | SetConfigAction | TTriggerAutoInjectAction @@ -59,11 +59,11 @@ export const autoInject: Reducer = (state = break; } - case 'SET_OPEN': { - if (action.open && !state.isOpenedOnce) { + case 'SHOW_CHAT_SCREEN': { + if (!state.isChatOpenedOnce) { return { ...state, - isOpenedOnce: true + isChatOpenedOnce: true } } diff --git a/src/webchat/store/connection/connection-middleware.ts b/src/webchat/store/connection/connection-middleware.ts index 99db8838..8749cce8 100644 --- a/src/webchat/store/connection/connection-middleware.ts +++ b/src/webchat/store/connection/connection-middleware.ts @@ -1,6 +1,6 @@ import { Middleware } from "redux"; import { StoreState } from "../store"; -import { SetHasAcceptedTermsAction, SetOpenAction, SetPageVisibleAction, ToggleOpenAction, setStoredMessage } from "../ui/ui-reducer"; +import { SetHasAcceptedTermsAction, SetPageVisibleAction, ShowChatScreenAction, ToggleOpenAction, setStoredMessage } from "../ui/ui-reducer"; import { SendMessageAction, sendMessage } from "../messages/message-middleware"; import { setOptions } from "../options/options-reducer"; import { SocketClient } from "@cognigy/socket-client"; @@ -13,9 +13,8 @@ export interface ISendMessageOptions { } const CONNECT = 'CONNECT' -export const connect = (termsAccepted?: boolean) => ({ - type: CONNECT as 'CONNECT', - termsAccepted +export const connect = () => ({ + type: CONNECT as 'CONNECT' }); export type ConnectAction = ReturnType; @@ -25,57 +24,54 @@ type announceNetworkOnAction = ReturnType; // forwards messages to the socket -export const createConnectionMiddleware = (client: SocketClient): Middleware => store => next => (action: SetOpenAction | ToggleOpenAction | ConnectAction | SetHasAcceptedTermsAction | SendMessageAction | SetPageVisibleAction | announceNetworkOnAction) => { +export const createConnectionMiddleware = (client: SocketClient): Middleware => store => next => (action: ToggleOpenAction | ConnectAction | SetHasAcceptedTermsAction | SendMessageAction | ShowChatScreenAction | SetPageVisibleAction | announceNetworkOnAction) => { switch (action.type) { - case 'CONNECT': { - const { hasAcceptedTerms, storedMessage } = store.getState().ui; + case "CONNECT": { + const { storedMessage } = store.getState().ui; - if (!client.connected && !store.getState().connection.connecting && (!store.getState().config.settings.privacyNotice.enabled || hasAcceptedTerms || action.termsAccepted)) { + if (!client.connected && !store.getState().connection.connecting) { store.dispatch(setConnecting(true)); - - client.connect() - .then(() => { - // set options - store.dispatch(setConnecting(false)); - store.dispatch(setReconnectionLimit(false)) - store.dispatch(setOptions(client.socketOptions)); - - if (storedMessage) { - store.dispatch(sendMessage({ text: storedMessage.text, data: storedMessage.data }, storedMessage.options)); - store.dispatch(setStoredMessage(null)); - } - }).catch(error => { + + client + .connect() + .then(() => { + // set options store.dispatch(setConnecting(false)); + store.dispatch(setReconnectionLimit(false)); + store.dispatch(setOptions(client.socketOptions)); + + if (storedMessage) { + store.dispatch( + sendMessage( + { text: storedMessage.text, data: storedMessage.data }, + storedMessage.options, + ), + ); + store.dispatch(setStoredMessage(null)); + } }) + .catch(() => { + store.dispatch(setConnecting(false)); + }); } break; } - case 'SET_OPEN': { - if (action.open) { - if (!client.connected) { - store.dispatch(connect()) - } - } - - break; - } - - case 'SET_HAS_ACCEPTED_TERMS': { + case "SHOW_CHAT_SCREEN": { if (!client.connected) { - store.dispatch(connect(true)) + store.dispatch(connect()); } break; } - case 'SEND_MESSAGE': { - store.dispatch(connect()) + case "SEND_MESSAGE": { + store.dispatch(connect()); break; } - case 'SET_PAGE_VISIBLE': { + case "SET_PAGE_VISIBLE": { if (action.visible && shouldReestablishConnection(store.getState())) { store.dispatch(connect()); } @@ -83,7 +79,7 @@ export const createConnectionMiddleware = (client: SocketClient): Middleware = store => next => (action: Actions) => { const key = getOptionsKey(store.getState().options, store.getState().config); const { active } = store.getState().config; // Actual settings are loaded const { disableLocalStorage, disablePersistentHistory, useSessionStorage } = store.getState().config.settings.embeddingConfiguration; - const { userId } = store.getState().options; + const { userId, sessionId } = store.getState().options; const browserStorage = getStorage({ useSessionStorage, disableLocalStorage }); switch (action.type) { @@ -46,6 +47,20 @@ export const optionsMiddleware: Middleware = store => next = } break; } + case "SET_SHOW_PREV_CONVERSATIONS": { + // we set prevConversations here in case user visit the list without socket session + if (action.showPrevConversations && browserStorage && userId && !sessionId) { + const prevConversations = getAllConversations( + browserStorage, + userId, + undefined, + store.getState().config?.URLToken + ); + store.dispatch(setConversations(prevConversations)); + } + + break; + } case "SEND_MESSAGE": case "RECEIVE_MESSAGE": case "TRIGGER_ENGAGEMENT_MESSAGE": @@ -53,7 +68,7 @@ export const optionsMiddleware: Middleware = store => next = case "SET_HAS_GIVEN_RATING": case "SET_CUSTOM_RATING_TITLE": case "SET_CUSTOM_RATING_COMMENT_TEXT": { - if (browserStorage && active && userId && !disablePersistentHistory) { + if (browserStorage && active && userId && sessionId && !disablePersistentHistory) { const { messages, rating } = store.getState(); browserStorage.setItem( key, diff --git a/src/webchat/store/options/options-reducer.ts b/src/webchat/store/options/options-reducer.ts index 8558a56a..d70a2d7f 100644 --- a/src/webchat/store/options/options-reducer.ts +++ b/src/webchat/store/options/options-reducer.ts @@ -16,13 +16,27 @@ export const setOptions = (options: Options) => ({ }); export type SetOptionsAction = ReturnType; -export const options: Reducer = (state = getInitialState(), action) => { +const SET_USER_ID = 'SET_USER_ID'; +export const setUserId = (userId: string) => ({ + type: SET_USER_ID as 'SET_USER_ID', + userId +}); +export type SetUserIdAction = ReturnType; + +export const options: Reducer = (state = getInitialState(), action) => { switch (action.type) { case 'SET_OPTIONS': { return action.options; - }; + } + + case 'SET_USER_ID': { + return { + ...state, + userId: action.userId, + }; + } default: return state; - }; + } }; diff --git a/src/webchat/store/previous-conversations/previous-conversations-middleware.ts b/src/webchat/store/previous-conversations/previous-conversations-middleware.ts index 06bd3845..1fa3e289 100644 --- a/src/webchat/store/previous-conversations/previous-conversations-middleware.ts +++ b/src/webchat/store/previous-conversations/previous-conversations-middleware.ts @@ -8,6 +8,7 @@ import { SetPrevStateAction, setPrevState } from "../reducer"; import { SocketClient } from "@cognigy/socket-client"; import { autoInjectHandledReset, triggerAutoInject } from "../autoinject/autoinject-reducer"; import { setConnecting } from "../connection/connection-reducer"; +import { setOptions } from "../options/options-reducer"; const SWITCH_SESSION = "SWITCH_SESSION"; export const switchSession = ( @@ -51,6 +52,7 @@ export const createPrevConversationsMiddleware = .switchSession(targetSession) .then(() => { store.dispatch(setConnecting(false)); + store.dispatch(setOptions(client.socketOptions)); store.dispatch(autoInjectHandledReset()); store.dispatch(triggerAutoInject()); }) diff --git a/src/webchat/store/ui/ui-middleware.ts b/src/webchat/store/ui/ui-middleware.ts index c97cc3a9..1b105824 100644 --- a/src/webchat/store/ui/ui-middleware.ts +++ b/src/webchat/store/ui/ui-middleware.ts @@ -4,7 +4,7 @@ import { clearUnseenMessages } from "../unseen-messages/unseen-message-reducer"; import { setOpen, ToggleOpenAction, - SetOpenAction, + ShowChatScreenAction, SetPageVisibleAction, SetHasAcceptedTermsAction, } from "./ui-reducer"; @@ -15,7 +15,7 @@ export const uiMiddleware: Middleware = store => next => ( - action: ToggleOpenAction | SetOpenAction | SetPageVisibleAction | SetHasAcceptedTermsAction, + action: ToggleOpenAction | ShowChatScreenAction | SetPageVisibleAction | SetHasAcceptedTermsAction, ) => { const { disableLocalStorage, useSessionStorage } = store.getState().config.settings.embeddingConfiguration; @@ -30,9 +30,9 @@ export const uiMiddleware: Middleware = break; } - // if the webchat is opened while the page is active, reset unread messages - case "SET_OPEN": { - if (action.open && store.getState().ui.isPageVisible) { + // if the chat screen is opened while the page is active, reset unread messages + case "SHOW_CHAT_SCREEN": { + if (store.getState().ui.isPageVisible) { store.dispatch(clearUnseenMessages()); } diff --git a/src/webchat/store/ui/ui-reducer.ts b/src/webchat/store/ui/ui-reducer.ts index 31726354..5aa9595b 100644 --- a/src/webchat/store/ui/ui-reducer.ts +++ b/src/webchat/store/ui/ui-reducer.ts @@ -58,6 +58,12 @@ export const setShowHomeScreen = (showHomeScreen: boolean) => ({ }); export type SetShowHomeScreenAction = ReturnType; +export const SHOW_CHAT_SCREEN = 'SHOW_CHAT_SCREEN'; +export const showChatScreen = () => ({ + type: SHOW_CHAT_SCREEN as 'SHOW_CHAT_SCREEN' +}); +export type ShowChatScreenAction = ReturnType; + export const SET_SHOW_PREV_CONVERSATIONS = 'SET_SHOW_PREV_CONVERSATIONS'; export const setShowPrevConversations = (showPrevConversations: boolean) => ({ type: SET_SHOW_PREV_CONVERSATIONS as 'SET_SHOW_PREV_CONVERSATIONS', diff --git a/webpack.production.js b/webpack.production.js index d54deb07..11052a9c 100644 --- a/webpack.production.js +++ b/webpack.production.js @@ -10,7 +10,7 @@ const CompressionPlugin = require("compression-webpack-plugin"); config.mode = "production"; config.plugins.push( new webpack.BannerPlugin({ - banner: `[file] v${version}\nhttps://github.com/Cognigy/WebchatWidget/tree/v${version}\nhttps://github.com/Cognigy/WebchatWidget/tree/v${version}/OSS_LICENSES.txt`, + banner: `[file] v${version}\nhttps://github.com/Cognigy/Webchat/tree/v${version}\nhttps://github.com/Cognigy/Webchat/tree/v${version}/OSS_LICENSES.txt`, }), );