├── .editorconfig ├── .gitattributes ├── .gitignore ├── .prettierignore ├── .prettierrc.json ├── LICENSE ├── README.md ├── bot.html └── static ├── img ├── bot.jpg ├── demo.png └── guy.jpg ├── main.css └── main.js /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | charset = utf-8 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | indent_style = tab 11 | indent_size = 4 12 | max_line_length = 120 13 | 14 | [*.md] 15 | trim_trailing_whitespace = false 16 | max_line_length = 0 17 | 18 | [{**.min.**, **/vendors/**}] 19 | charset = unset 20 | end_of_line = unset 21 | insert_final_newline = unset 22 | trim_trailing_whitespace = unset 23 | indent_style = unset 24 | indent_size = unset 25 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | MANIFEST 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | .pytest_cache/ 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | local_settings.py 57 | db.sqlite3 58 | 59 | # Flask stuff: 60 | instance/ 61 | .webassets-cache 62 | 63 | # Scrapy stuff: 64 | .scrapy 65 | 66 | # Sphinx documentation 67 | docs/_build/ 68 | 69 | # PyBuilder 70 | target/ 71 | 72 | # Jupyter Notebook 73 | .ipynb_checkpoints 74 | 75 | # pyenv 76 | .python-version 77 | 78 | # celery beat schedule file 79 | celerybeat-schedule 80 | 81 | # SageMath parsed files 82 | *.sage.py 83 | 84 | # Environments 85 | .env 86 | .venv 87 | env/ 88 | venv/ 89 | ENV/ 90 | env.bak/ 91 | venv.bak/ 92 | 93 | # Spyder project settings 94 | .spyderproject 95 | .spyproject 96 | 97 | # Rope project settings 98 | .ropeproject 99 | 100 | # mkdocs documentation 101 | /site 102 | 103 | # mypy 104 | .mypy_cache/ 105 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | **/vendors/** 2 | **.min.** 3 | *.py 4 | *.md 5 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "tabWidth": 4, 3 | "useTabs": true, 4 | "semi": true, 5 | "singleQuote": true, 6 | "trailingComma": "all", 7 | "bracketSpacing": true, 8 | "jsxBracketSameLine": false, 9 | "insertPragma": false 10 | } 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Thomas Ashish Cherian 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Chatbot Frontend 2 | A simple chatbot frontend for plugging in my bots. 3 | 4 | To add a user message to the chat window 5 | run javascript function - 6 | 7 | showUserMessage("Message",getCurrentTimestamp()); 8 | 9 | To add a bot message to the chat window 10 | run javascript function - 11 | 12 | showBotMessage("Message",getCurrentTimestamp()); 13 | 14 | ## Screenshot 15 | ![enter image description here](./static/img/demo.png) 16 | 17 | PR's are welcome :) 18 | -------------------------------------------------------------------------------- /bot.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Chatbot Frontend 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 |
29 | 30 | 31 |
32 | 33 |
34 | 35 |
36 |
ChatBot - Jarvis
37 |
38 | 39 | 40 |
    41 | 42 | 43 |
    44 | 45 |
    Send
    46 |
    47 | 48 |
    49 | 50 |
    51 | 52 | 53 |
    54 |
    55 | 56 |
    57 |
    Help
    58 |
    59 | 60 | 61 |
    62 | 63 | 64 |
    65 |
    66 |

    67 | Lorem ipsum 69 |

    70 |
    71 |
    72 |
    73 | Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt 74 | mollit anim id est laborum 75 |
    76 |
    77 |
    78 | 79 |
    80 | 81 |
    82 |
    83 | 84 |
    85 | 86 |
    87 | 88 | 89 | 90 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /static/img/bot.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PandaWhoCodes/chatbot-frontend/1b1ebb51cd7b4bbeaee5d3fefadb5c533b1abb18/static/img/bot.jpg -------------------------------------------------------------------------------- /static/img/demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PandaWhoCodes/chatbot-frontend/1b1ebb51cd7b4bbeaee5d3fefadb5c533b1abb18/static/img/demo.png -------------------------------------------------------------------------------- /static/img/guy.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PandaWhoCodes/chatbot-frontend/1b1ebb51cd7b4bbeaee5d3fefadb5c533b1abb18/static/img/guy.jpg -------------------------------------------------------------------------------- /static/main.css: -------------------------------------------------------------------------------- 1 | * { 2 | box-sizing: border-box; 3 | } 4 | 5 | body { 6 | background-color: #edeff2; 7 | font-family: 'Calibri', 'Roboto', sans-serif; 8 | } 9 | 10 | .row.padded_row, 11 | .row.padded_row > div { 12 | padding-top: 20px; 13 | padding-bottom: 20px; 14 | } 15 | 16 | /* layout and common global classes */ 17 | /* ---------------------------------------------------------------------- */ 18 | 19 | .chat_window { 20 | border-radius: 10px; 21 | box-shadow: 0 10px 20px rgba(0, 0, 0, 0.15); 22 | background-color: #f8f8f8; 23 | overflow: hidden; 24 | } 25 | 26 | .top_menu { 27 | background-color: #fff; 28 | padding: 13px 0px; 29 | box-shadow: 0 1px 30px rgba(0, 0, 0, 0.1); 30 | } 31 | 32 | .top_menu .title { 33 | text-align: center; 34 | color: #337ab7; 35 | font-size: 20px; 36 | } 37 | 38 | /* messages inside the chatbox */ 39 | /* ---------------------------------------------------------------------- */ 40 | 41 | .messages { 42 | position: relative; 43 | list-style: none; 44 | padding: 20px 10px 0 10px; 45 | margin: 0; 46 | height: 500px; 47 | overflow: scroll; 48 | } 49 | 50 | .messages .message { 51 | clear: both; 52 | overflow: hidden; 53 | margin-bottom: 20px; 54 | transition: all 0.5s linear; 55 | opacity: 0; 56 | } 57 | 58 | .messages .message .avatar { 59 | height: 40px; 60 | width: 40px; 61 | background-size: cover !important; 62 | border-radius: 50%; 63 | display: inline-block; 64 | } 65 | 66 | .messages .message .timestamp { 67 | font-size: 10px; 68 | font-weight: 300; 69 | text-align: right; 70 | margin-top: 5px; 71 | } 72 | 73 | .messages .message.appeared { 74 | opacity: 1; 75 | } 76 | 77 | .messages .message .text_wrapper { 78 | display: inline-block; 79 | padding: 20px; 80 | border-radius: 6px; 81 | min-width: 150px; 82 | position: relative; 83 | } 84 | 85 | .messages .message .text_wrapper::after, 86 | .messages .message .text_wrapper:before { 87 | top: 18px; 88 | border: solid transparent; 89 | content: ' '; 90 | height: 0; 91 | width: 0; 92 | position: absolute; 93 | pointer-events: none; 94 | } 95 | 96 | .messages .message .text_wrapper::after { 97 | border-width: 13px; 98 | margin-top: 0px; 99 | } 100 | 101 | .messages .message .text_wrapper::before { 102 | border-width: 15px; 103 | margin-top: -2px; 104 | } 105 | 106 | /* bot message */ 107 | 108 | .messages .message.left .avatar { 109 | float: left; 110 | background: url('./img/bot.jpg'); 111 | } 112 | 113 | .messages .message.left .text_wrapper { 114 | background-color: #f3eeca; 115 | margin-left: 20px; 116 | } 117 | 118 | .messages .message.left .text_wrapper::after, 119 | .messages .message.left .text_wrapper::before { 120 | right: 100%; 121 | border-right-color: #f3eeca; 122 | } 123 | 124 | .messages .message.left .timestamp { 125 | color: #b0742f; 126 | } 127 | 128 | /* user message */ 129 | 130 | .messages .message.right .avatar { 131 | float: right; 132 | background: url('./img/guy.jpg'); 133 | } 134 | 135 | .messages .message.right .text_wrapper { 136 | background-color: #b0d4f3; 137 | margin-right: 20px; 138 | float: right; 139 | } 140 | 141 | .messages .message.right .text_wrapper::after, 142 | .messages .message.right .text_wrapper::before { 143 | left: 100%; 144 | border-left-color: #b0d4f3; 145 | } 146 | 147 | .messages .message.right .timestamp { 148 | color: #1a5770; 149 | } 150 | 151 | /* text inpur from user */ 152 | 153 | .bottom_wrapper { 154 | background-color: #fff; 155 | padding: 20px; 156 | bottom: 0; 157 | display: flex; 158 | } 159 | 160 | .bottom_wrapper #msg_input { 161 | flex-grow: 1; 162 | outline-width: 0; 163 | padding: 12px; 164 | border: 1px solid #bcbdc0; 165 | border-radius: 50px; 166 | margin-right: 15px; 167 | } 168 | 169 | .app_button_1 { 170 | width: 140px; 171 | background-color: #a3d063; 172 | border-radius: 50px; 173 | cursor: pointer; 174 | padding: 12px; 175 | 176 | color: #fff; 177 | font-size: 18px; 178 | font-weight: 300; 179 | text-align: center; 180 | } 181 | 182 | /* faq section | right side */ 183 | /* ---------------------------------------------------------------------- */ 184 | 185 | .panel-group { 186 | margin: 20px; 187 | } 188 | 189 | .panel-heading [data-toggle='collapse']:after { 190 | font-family: 'FontAwesome'; 191 | content: '\f054'; 192 | float: right; 193 | font-size: 18px; 194 | line-height: 22px; 195 | transition: all 0.2s linear; 196 | 197 | -webkit-transform: rotate(-90deg); 198 | -moz-transform: rotate(-90deg); 199 | -ms-transform: rotate(-90deg); 200 | -o-transform: rotate(-90deg); 201 | transform: rotate(-90deg); 202 | } 203 | 204 | .panel-heading [data-toggle='collapse'].collapsed:after { 205 | -webkit-transform: rotate(90deg); 206 | -moz-transform: rotate(90deg); 207 | -ms-transform: rotate(90deg); 208 | -o-transform: rotate(90deg); 209 | transform: rotate(90deg); 210 | } 211 | -------------------------------------------------------------------------------- /static/main.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Returns the current datetime for the message creation. 3 | */ 4 | function getCurrentTimestamp() { 5 | return new Date(); 6 | } 7 | 8 | /** 9 | * Renders a message on the chat screen based on the given arguments. 10 | * This is called from the `showUserMessage` and `showBotMessage`. 11 | */ 12 | function renderMessageToScreen(args) { 13 | // local variables 14 | let displayDate = (args.time || getCurrentTimestamp()).toLocaleString('en-IN', { 15 | month: 'short', 16 | day: 'numeric', 17 | hour: 'numeric', 18 | minute: 'numeric', 19 | }); 20 | let messagesContainer = $('.messages'); 21 | 22 | // init element 23 | let message = $(` 24 |
  • 25 |
    26 |
    27 |
    ${args.text}
    28 |
    ${displayDate}
    29 |
    30 |
  • 31 | `); 32 | 33 | // add to parent 34 | messagesContainer.append(message); 35 | 36 | // animations 37 | setTimeout(function () { 38 | message.addClass('appeared'); 39 | }, 0); 40 | messagesContainer.animate({ scrollTop: messagesContainer.prop('scrollHeight') }, 300); 41 | } 42 | 43 | /* Sends a message when the 'Enter' key is pressed. 44 | */ 45 | $(document).ready(function() { 46 | $('#msg_input').keydown(function(e) { 47 | // Check for 'Enter' key 48 | if (e.key === 'Enter') { 49 | // Prevent default behaviour of enter key 50 | e.preventDefault(); 51 | // Trigger send button click event 52 | $('#send_button').click(); 53 | } 54 | }); 55 | }); 56 | 57 | /** 58 | * Displays the user message on the chat screen. This is the right side message. 59 | */ 60 | function showUserMessage(message, datetime) { 61 | renderMessageToScreen({ 62 | text: message, 63 | time: datetime, 64 | message_side: 'right', 65 | }); 66 | } 67 | 68 | /** 69 | * Displays the chatbot message on the chat screen. This is the left side message. 70 | */ 71 | function showBotMessage(message, datetime) { 72 | renderMessageToScreen({ 73 | text: message, 74 | time: datetime, 75 | message_side: 'left', 76 | }); 77 | } 78 | 79 | /** 80 | * Get input from user and show it on screen on button click. 81 | */ 82 | $('#send_button').on('click', function (e) { 83 | // get and show message and reset input 84 | showUserMessage($('#msg_input').val()); 85 | $('#msg_input').val(''); 86 | 87 | // show bot message 88 | setTimeout(function () { 89 | showBotMessage(randomstring()); 90 | }, 300); 91 | }); 92 | 93 | /** 94 | * Returns a random string. Just to specify bot message to the user. 95 | */ 96 | function randomstring(length = 20) { 97 | let output = ''; 98 | 99 | // magic function 100 | var randomchar = function () { 101 | var n = Math.floor(Math.random() * 62); 102 | if (n < 10) return n; 103 | if (n < 36) return String.fromCharCode(n + 55); 104 | return String.fromCharCode(n + 61); 105 | }; 106 | 107 | while (output.length < length) output += randomchar(); 108 | return output; 109 | } 110 | 111 | /** 112 | * Set initial bot message to the screen for the user. 113 | */ 114 | $(window).on('load', function () { 115 | showBotMessage('Hello there! Type in a message.'); 116 | }); --------------------------------------------------------------------------------