├── .dockerignore
├── .github
└── ISSUE_TEMPLATE
│ └── bug_report.md
├── .gitignore
├── Dockerfile
├── README.md
├── contributing.md
├── docker-compose.yml
├── license
├── package-lock.json
├── package.json
├── server
├── data
│ ├── .gitignore
│ └── models
│ │ └── .gitignore
├── db
│ ├── actions.js
│ ├── bots.js
│ ├── conversations.js
│ ├── db.js
│ ├── entities.js
│ ├── expressions.js
│ ├── intents.js
│ ├── logs.js
│ ├── models.js
│ ├── parameters.js
│ ├── regex.js
│ ├── responses.js
│ ├── settings.js
│ ├── stories.js
│ ├── synonyms.js
│ └── variants.js
├── routes
│ ├── auth.js
│ ├── index.js
│ └── rasa_router.js
├── server.js
├── test
│ ├── common.js
│ ├── db
│ │ └── test_db.sqlite3
│ ├── test.js
│ └── tests
│ │ ├── actions.test.js
│ │ ├── bots.test.js
│ │ ├── conversations.test.js
│ │ ├── entities.test.js
│ │ ├── expressions.test.js
│ │ ├── intents.test.js
│ │ ├── models.test.js
│ │ ├── parameters.test.js
│ │ ├── regex.test.js
│ │ ├── responses.test.js
│ │ ├── settings.test.js
│ │ ├── stories.test.js
│ │ ├── synonyms.test.js
│ │ └── variants.test.js
└── util
│ └── logger.js
└── web
└── src
├── app
├── app.js
├── components
│ ├── bots
│ │ ├── add_bot.html
│ │ ├── add_bot.js
│ │ ├── bots.html
│ │ ├── bots.js
│ │ ├── edit_bot.html
│ │ ├── edit_bot.js
│ │ ├── import_bot.html
│ │ └── import_bot.js
│ ├── chat
│ │ ├── chat.html
│ │ └── chat.js
│ ├── dashboard
│ │ ├── dashboard.html
│ │ ├── dashboard.js
│ │ └── widgets.js
│ ├── entities
│ │ ├── add_entity.html
│ │ ├── add_entity.js
│ │ ├── edit_entity.html
│ │ └── edit_entity.js
│ ├── insights
│ │ ├── insights.html
│ │ └── insights.js
│ ├── intents
│ │ ├── add_intent.html
│ │ ├── add_intent.js
│ │ ├── edit_intent.html
│ │ └── edit_intent.js
│ ├── logs
│ │ ├── logs.html
│ │ └── logs.js
│ ├── models
│ │ ├── add_model.html
│ │ ├── add_model.js
│ │ ├── models.html
│ │ └── models.js
│ ├── rasaconfig
│ │ ├── rasa_config.html
│ │ └── rasa_config.js
│ ├── regex
│ │ ├── add_regex.html
│ │ ├── add_regex.js
│ │ ├── edit_regex.html
│ │ └── edit_regex.js
│ ├── responses
│ │ ├── add_action.html
│ │ ├── add_action.js
│ │ ├── responses.html
│ │ └── responses.js
│ ├── settings
│ │ ├── settings.html
│ │ └── settings.js
│ ├── stories
│ │ ├── stories.html
│ │ └── stories.js
│ ├── synonyms
│ │ ├── add_synonym.html
│ │ ├── add_synonym.js
│ │ ├── edit_synonym.html
│ │ └── edit_synonym.js
│ └── training
│ │ ├── training.html
│ │ └── training.js
├── config
│ └── app.config.js
├── directives.js
├── router.js
├── services
│ ├── api.js
│ ├── log.js
│ └── rasa_api.js
└── shared
│ ├── aside
│ ├── aside.html
│ └── aside.js
│ ├── navbar
│ ├── navbar.html
│ └── navbar.js
│ └── sidebar
│ ├── sidebar.html
│ └── sidebar.js
├── assets
├── css
│ ├── fonts
│ │ ├── FontAwesome.otf
│ │ ├── fontawesome-webfont.eot
│ │ ├── fontawesome-webfont.svg
│ │ ├── fontawesome-webfont.ttf
│ │ ├── fontawesome-webfont.woff
│ │ └── fontawesome-webfont.woff2
│ ├── style.css
│ └── vendor
│ │ └── core-ui.css
└── img
│ ├── favicon.png
│ ├── logo.png
│ ├── screenshot1.png
│ ├── screenshot1_small.png
│ ├── screenshot2.png
│ └── screenshot2_small.png
└── index.html
/.dockerignore:
--------------------------------------------------------------------------------
1 | .git
2 | node_modules
3 | npm-debug.log
4 | .*
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **Installation Type (please complete the following information):**
27 | - Docker Hub, Docker Compose, Source Code Install
28 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | npm-debug.log
3 | node_modules
4 | server/data/db.sqlite3
5 |
6 | # editors
7 | .idea
8 | *.swp
9 | *.iml
10 |
11 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM mhart/alpine-node:10 as builder
2 |
3 | RUN apk add --no-cache make gcc g++ python
4 | COPY ./package*.json ./
5 | RUN npm install --production
6 |
7 | FROM mhart/alpine-node:10
8 |
9 | RUN apk add --no-cache make gcc g++ python
10 |
11 | ENV http_port=5001
12 | ENV rasa_endpoint "http://localhost:5005"
13 | ENV jwtsecret "mysecret"
14 | ENV loglevel "info"
15 | ENV admin_username "admin"
16 | ENV admin_password "admin"
17 | ENV db_schema "3.0.1"
18 |
19 | WORKDIR /opt/rasaui
20 |
21 | COPY --from=builder /node_modules ./node_modules
22 |
23 | COPY ./package*.json ./
24 | COPY ./server ./server
25 | COPY ./web ./web
26 |
27 | EXPOSE ${http_port}
28 |
29 | ENTRYPOINT sh -c "hostname -i; npm start"
30 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://hub.docker.com/r/paschmann/rasa-ui/)
2 |
3 | # Rasa UI
4 |
5 | Rasa UI is a web application built on top of, and for [Rasa](https://github.com/RasaHQ/rasa). Rasa UI provides a web application to quickly and easily be able to create and manage bots, NLU components (Regex, Examples, Entities, Intents, etc.) and Core components (Stories, Actions, Responses, etc.) through a web interface. It also provides some convenience features for Rasa, like training and loading your models, monitoring usage or viewing logs.
6 |
7 | ## Features
8 |
9 | - UI for creating and managing training data - Examples, Intents, Entities, Synonyms, Regex, Stories, Actions, Responses
10 | - Manage multiple bots from a single UI/instance of Rasa UI
11 | - Create, manage and load different versions of your models for testing and optimizing
12 | - Log requests for usage tracking, history and improvements to your models
13 | - Easily execute intent parsing using different models
14 | - Data is stored in a SQLite DB for backing up/sharing
15 | - Can be used with or without a Rasa backend to manage your training data
16 |
17 |
18 |
19 |
20 | ## Getting Started
21 |
22 | Rasa UI can run on your Rasa instance, or on a separate machine. Technically Rasa is not required, you could just use the UI for managing training data.
23 |
24 | ### Prerequisites
25 |
26 | [Node.js/npm](https://nodejs.org/en/) - Serves Rasa UI - Required
27 |
28 | [Rasa](https://github.com/RasaHQ/rasa) - Developed against Version 1.2+ - Optional
29 |
30 | ### Installing
31 |
32 | 1. Clone/download the Rasa UI repository or a [release](https://www.github.com/paschmann/rasa-ui)
33 | 2. Install npm packages.
34 | 3. Set Rasa Server variable in package.json
35 |
36 | ```
37 | git clone https://github.com/paschmann/rasa-ui.git
38 | cd rasa-ui
39 | npm install
40 | ```
41 |
42 | ## Running
43 |
44 | Run npm start from the server folder (rasa-ui)
45 |
46 | ```
47 | npm start
48 | ```
49 | Your web application should be available on http://localhost:5001
50 |
51 | ## Running from Docker
52 |
53 | If you **already** have a Rasa instance setup and running, you can run Rasa UI from docker hub using [paschmann/rasa-ui](https://hub.docker.com/r/paschmann/rasa-ui/). You will need to edit the environment variables, specifically the **rasa_endpoint**.
54 |
55 | If you **dont** have a Rasa instance setup, you can run both Rasa and Rasa UI using the [docker-compose file](https://github.com/paschmann/rasa-ui/blob/master/docker-compose.yml), copy the file to a local directory and run the command below:
56 |
57 | ```
58 | docker-compose up
59 | ```
60 |
61 | The docker-compose up command will use the docker-compose.yml file to create both the Rasa container and Rasa UI container, and create a networked connection between both.
62 |
63 | ## Upgrading
64 |
65 | Because Rasa UI uses a Database to store training data, and other content, in the event the database schema changes, you will need to modify your database when upgrading to newer versions of Rasa UI. Please review the server/db migration folder for upgrade scripts from and to newer versions if you have existing data and want to maintain it. If you are upgrading from Rasa UI prior to v.3.0.0 there is no data migration path as previously postgres was used, and now sqlite is being used.
66 |
67 | ## Logging
68 |
69 | Since Rasa UI can be used to log events/intent parsing/training etc. we would suggest changing your endpoints for your API calls to "pass through" Rasa UI. All API requests are simply logged, forwarded to Rasa and then returned.
70 |
71 | e.g. Instead of POST'ing to your Rasa instance which is normally something like http://localhost:5005/model/parse?q=hello you can POST to Rasa UI (e.g. http://localhost:5001/api/v2/rasa/model/parse?q=hello)
72 |
73 | ## Contributing
74 |
75 | Please read [contributing.md](contributing.md) for details on our code of conduct, and the process for submitting pull requests to us.
76 |
77 | ## Contributers
78 |
79 | Rasa UI is possible thanks to all the awesome contributers, thank you!
80 |
81 | * **Pradeep Mamillapalli**
82 | * **elvay1**
83 | * **huberrom**
84 | * **ClaasBrueggemann**
85 | * **btran10**
86 | * **btotharye**
87 | * **beevelop**
88 |
89 | ## License
90 |
91 | This project is licensed under the MIT License - see the [license](license) file for details
92 |
--------------------------------------------------------------------------------
/contributing.md:
--------------------------------------------------------------------------------
1 | # RASA-UI Contribution guide
2 | When contributing to this repository, please first discuss the change you wish to make via issue, with the owners of this repository before making a change.
3 |
4 | ## Pull Request Process
5 | 1. Fork this project.
6 | 2. Implement the change, follow the agreed path from the discussion (see above opening sentence.)
7 | 3. Update the README.md with details of changes to the interface, this includes new environment variables, exposed ports, useful file locations and any other information related to running the application.
8 | 3. Increase the version numbers in any examples files and the README.md to the new version that this Pull Request would represent. The versioning scheme we use is [SemVer](semver.org).
9 | 4. File a PR against paschmann/rasa-ui
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3.0'
2 |
3 | services:
4 | rasa:
5 | image: rasa/rasa:latest-full
6 | container_name: rasa
7 | networks: ['rasa-network']
8 | ports:
9 | - "5005:5005"
10 | volumes:
11 | - "./rasa-app-data/models:/app/models"
12 | - "./rasa-app-data/logs:/app/logs"
13 | command: "run --enable-api --debug"
14 |
15 | rasa_ui:
16 | image: paschmann/rasa-ui:latest
17 | container_name: rasa_ui
18 | networks: ['rasa-network']
19 | ports:
20 | - "5001:5001"
21 | depends_on:
22 | - "rasa"
23 | environment:
24 | rasa_endpoint: "http://rasa:5005"
25 |
26 | networks: {rasa-network: {}}
--------------------------------------------------------------------------------
/license:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Paul Aschmann
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 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "RasaUI",
3 | "version": "3.0.1",
4 | "description": "Rasa UI is a web application built on top of, and for, Rasa.",
5 | "dependencies": {
6 | "angular": "1.7.2",
7 | "angular-chart.js": "^1.1.1",
8 | "angular-cookies": "1.7.2",
9 | "angular-modal-service": "^0.15.1",
10 | "angular-resource": "1.7.2",
11 | "angular-route": "1.7.2",
12 | "angular-sanitize": "1.7.2",
13 | "angular-utils-pagination": "^0.11.1",
14 | "body-parser": "^1.18.3",
15 | "bootstrap": "latest",
16 | "chart.js": "^2.7.3",
17 | "cors": "^2.8.5",
18 | "express": "^4.16.4",
19 | "http-proxy-middleware": "^0.19.1",
20 | "jquery": "3.4.0",
21 | "jsonformatter": "^0.6.0",
22 | "jsonwebtoken": "^8.4.0",
23 | "ng-file-upload": "^12.2.13",
24 | "ng-tags-input": "^3.2.0",
25 | "ngstorage": "^0.3.11",
26 | "popper.js": "^1.15.0",
27 | "request": "^2.88.0",
28 | "simple-line-icons": "^2.4.1",
29 | "sqlite3": "^4.1.0",
30 | "winston": "^3.2.1"
31 | },
32 | "config": {
33 | "rasa_endpoint": "http://localhost:5005",
34 | "loglevel": "info",
35 | "jwtsecret": "mysecret",
36 | "admin_username": "admin",
37 | "admin_password": "admin",
38 | "db_schema": "3.0.1",
39 | "db_autoupdate": "true"
40 | },
41 | "scripts": {
42 | "test:server": "mocha server/test/test.js --delay true --exit",
43 | "start": "node server/server.js",
44 | "dev": "nodemon server/server.js --ignore 'server/data/'"
45 | },
46 | "author": "Paul Aschmann",
47 | "url": "https://github.com/paschmann/rasa-ui",
48 | "copyright": "Copyright 2017",
49 | "license": "SEE LICENSE IN https://github.com/paschmann/rasa-ui/blob/master/license",
50 | "repository": {
51 | "type": "git",
52 | "url": "https://github.com/paschmann/rasa-ui.git"
53 | },
54 | "devDependencies": {
55 | "chai": "^4.2.0",
56 | "chai-http": "^4.3.0",
57 | "mocha": "^6.2.0"
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/server/data/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | */
3 | !.gitignore
--------------------------------------------------------------------------------
/server/data/models/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | */
3 | !.gitignore
--------------------------------------------------------------------------------
/server/db/actions.js:
--------------------------------------------------------------------------------
1 | const db = require('./db');
2 | const logger = require('../util/logger');
3 |
4 | function getBotActionsAndResponses(req, res, next) {
5 | logger.winston.info('actions.getBotActionsAndResponses');
6 | db.all('select * from actions where bot_id = ? order by action_id desc', req.query.bot_id, function(err, actions) {
7 | if (err) {
8 | logger.winston.error(err);
9 | } else {
10 | var actionIds = [];
11 | for (var i = 0; i < actions.length; i++) {
12 | actionIds.push(actions[i].action_id);
13 | }
14 | if (actionIds.length > 0) {
15 | db.all('select * from responses where action_id in (' + actionIds.splice(",") + ') order by action_id desc', function(err, responses) {
16 | if (err) {
17 | logger.winston.error(err);
18 | } else {
19 | res.status(200).json([{actions: actions, responses: responses}]);
20 | }
21 | });
22 | } else {
23 | res.status(200).json([{actions: actions, responses: []}]);
24 | }
25 | }
26 | });
27 | }
28 |
29 | function createAction(req, res, next) {
30 | logger.winston.info('actions.createAction');
31 | db.run('insert into actions (action_name, bot_id)' + 'values (?,?)', [req.body.action_name, req.body.bot_id], function(err) {
32 | if (err) {
33 | logger.winston.error("Error inserting a new record");
34 | } else {
35 | res.status(200).json({ status: 'success', message: 'Inserted' });
36 | }
37 | });
38 | }
39 |
40 |
41 | function removeAction(req, res, next) {
42 | logger.winston.info('actions.removeAction');
43 | db.run('delete from actions where action_id = ?', req.query.action_id, function(err) {
44 | if (err) {
45 | logger.winston.error("Error removing the record");
46 | } else {
47 | db.run('delete from responses where action_id = ?', req.query.action_id);
48 | res.status(200).json({ status: 'success', message: 'Removed' });
49 | }
50 | });
51 | }
52 |
53 |
54 | function updateAction(req, res, next) {
55 | logger.winston.info('actions.updateAction');
56 | db.run('update actions set action_name = ? where action_id = ?', [req.body.action_name, req.body.bot_id], function(err) {
57 | if (err) {
58 | logger.winston.error("Error updating the record");
59 | } else {
60 | res.status(200).json({ status: 'success', message: 'Updated' });
61 | }
62 | });
63 | }
64 |
65 | module.exports = {
66 | getBotActionsAndResponses,
67 | createAction,
68 | updateAction,
69 | removeAction
70 | };
71 |
--------------------------------------------------------------------------------
/server/db/conversations.js:
--------------------------------------------------------------------------------
1 | const db = require('./db');
2 | const logger = require('../util/logger');
3 |
4 | module.exports = {
5 | getConversations,
6 | createConversation,
7 | removeConversation
8 | };
9 |
10 | function getConversations(req, res, next) {
11 | logger.winston.info('Conversations.getConversations');
12 | db.all('select * from conversations where bot_id = ? order by timestamp desc', req.params.bot_id, function(err, data) {
13 | if (err) {
14 | logger.winston.error(err);
15 | } else {
16 | res.status(200).json(data);
17 | }
18 | });
19 | }
20 |
21 | function createConversation(req, res, next) {
22 | logger.winston.info('Conversations.createConversation');
23 | db.run('insert into conversations(bot_id)' + 'values (?)', [req.body.bot_id], function(err) {
24 | if (err) {
25 | logger.winston.error("Error inserting a new record");
26 | } else {
27 | res.status(200).json({ status: 'success', message: 'Inserted' });
28 | }
29 | });
30 | }
31 |
32 | function removeConversation(req, res, next) {
33 | logger.winston.info('Conversations.removeConversation');
34 | db.run('delete from conversations where conversation_id = ?', req.query.conversation_id, function(err) {
35 | if (err) {
36 | logger.winston.error("Error removing the record");
37 | } else {
38 | res.status(200).json({ status: 'success', message: 'Removed' });
39 | }
40 | });
41 | }
--------------------------------------------------------------------------------
/server/db/db.js:
--------------------------------------------------------------------------------
1 | const sqlite3 = require('sqlite3').verbose();
2 | const logger = require('../util/logger');
3 |
4 | var db_file_path = "";
5 |
6 | if (process.env.npm_lifecycle_event == 'test:server') {
7 | db_file_path = "server/test/db/test_db.sqlite3";
8 | try {
9 | fs.unlinkSync(db_file_path);
10 | //file removed
11 | } catch(err) {
12 | //console.error(err)
13 | }
14 | } else {
15 | db_file_path = "server/data/db.sqlite3";
16 | }
17 |
18 | let db = new sqlite3.Database(db_file_path, (err) => {
19 | if (err) {
20 | logger.winston.error('Error when connecting to the Database.', err)
21 | } else {
22 | logger.winston.info('Database connected!');
23 | checkDBSchema();
24 | }
25 | })
26 |
27 | function checkDBSchema() {
28 | //Get version of DB Schema from version table, if != to version, suggest upgrade
29 | db.all("SELECT * from version", function(err, rows) {
30 | if (err && err.errno == 1) {
31 | createDBSchema();
32 | } else {
33 | if (rows.length > 0 && rows[0].version == global.db_schema) {
34 | logger.winston.info("Schema version v" + rows[0].version + " matches package.json schema version v" + global.db_schema);
35 | } else {
36 | var current_version = "?";
37 | if (rows.length > 0) {
38 | current_version = rows[0].version;
39 | }
40 | logger.winston.warn("Schema version v" + current_version + " DOES NOT match package.json schema version v" + global.db_schema);
41 | if (global.db_autoupdate == "true") {
42 | createDBSchema();
43 | } else {
44 | logger.winston.error("Please upgrade your schema");
45 | }
46 | }
47 | }
48 | });
49 | }
50 |
51 | async function createDBSchema() {
52 | try {
53 | logger.winston.info("------------------------- Starting to create/update DB schema -------------------------");
54 | await Promise.all([
55 | db.run("CREATE TABLE bots (bot_id INTEGER PRIMARY KEY AUTOINCREMENT, bot_name TEXT, bot_config TEXT, output_folder TEXT)", function(error) { sqlOutput(error, "bots"); }),
56 | db.run("CREATE TABLE intents (intent_id INTEGER PRIMARY KEY AUTOINCREMENT, intent_name TEXT, bot_id INTEGER)", function(error) { sqlOutput(error, "intents"); }),
57 | db.run("CREATE TABLE synonyms (synonym_id INTEGER PRIMARY KEY AUTOINCREMENT, synonym_reference TEXT, regex_pattern TEXT, bot_id INTEGER)", function(error) { sqlOutput(error, "synonyms"); }),
58 | db.run("CREATE TABLE entities (entity_id INTEGER PRIMARY KEY AUTOINCREMENT, entity_name TEXT, slot_data_type TEXT, bot_id INTEGER)", function(error) { sqlOutput(error, "entities"); }),
59 | db.run("CREATE TABLE expressions (expression_id INTEGER PRIMARY KEY AUTOINCREMENT, expression_text TEXT, intent_id INTEGER)", function(error) { sqlOutput(error, "expressions"); }),
60 | db.run("CREATE TABLE expression_parameters (parameter_id INTEGER PRIMARY KEY AUTOINCREMENT, parameter_start INTEGER, parameter_end INTEGER, parameter_value TEXT, expression_id INTEGER, intent_id INTEGER, entity_id INTEGER)", function(error) { sqlOutput(error, "expression_parameters"); }),
61 | db.run("CREATE TABLE regex (regex_id INTEGER PRIMARY KEY AUTOINCREMENT, regex_name TEXT, regex_pattern TEXT, bot_id INTEGER)", function(error) { sqlOutput(error, "regex"); }),
62 | db.run("CREATE TABLE responses (response_id INTEGER PRIMARY KEY AUTOINCREMENT, response_text TEXT, response_type TEXT, action_id INTEGER)", function(error) { sqlOutput(error, "responses"); }),
63 | db.run("CREATE TABLE synonym_variants (synonym_variant_id INTEGER PRIMARY KEY AUTOINCREMENT, synonym_value TEXT, synonym_id INTEGER)", function(error) { sqlOutput(error, "synonym_variants"); }),
64 | db.run("CREATE TABLE nlu_log (log_id INTEGER PRIMARY KEY AUTOINCREMENT, ip_address TEXT, query TEXT, event_type TEXT, event_data TEXT, timestamp DATETIME DEFAULT CURRENT_TIMESTAMP)", function(error) { sqlOutput(error, "nlu_log"); }),
65 | db.run("CREATE TABLE models (model_id INTEGER PRIMARY KEY AUTOINCREMENT, model_name TEXT, timestamp DATETIME DEFAULT CURRENT_TIMESTAMP, comment TEXT, bot_id INTEGER, local_path TEXT, server_path TEXT, server_response TEXT)", function(error) { sqlOutput(error, "models"); }),
66 | db.run("CREATE TABLE actions (action_id INTEGER PRIMARY KEY AUTOINCREMENT, action_name TEXT, bot_id INTEGER)", function(error) { sqlOutput(error, "actions"); }),
67 | db.run("CREATE TABLE stories (story_id INTEGER PRIMARY KEY AUTOINCREMENT, story_name TEXT, story TEXT, bot_id INTEGER, timestamp DATETIME DEFAULT CURRENT_TIMESTAMP)", function(error) { sqlOutput(error, "stories"); }),
68 |
69 | db.run("CREATE TABLE settings (setting_name TEXT, setting_value TEXT)", function(error) {
70 | sqlOutput(error, "settings");
71 | db.run("INSERT into settings (setting_name, setting_value) values ('refresh_time', '60000')");
72 | }),
73 |
74 | //New table part of Version 3.0.1
75 | db.run("CREATE TABLE conversations (conversation_id INTEGER PRIMARY KEY AUTOINCREMENT, ip_address TEXT, conversation TEXT, story TEXT, bot_id INTEGER, timestamp DATETIME DEFAULT CURRENT_TIMESTAMP)", function(error) { sqlOutput(error, "conversations"); }),
76 |
77 | db.run("CREATE TABLE version(version)", function(error) { setDBSchemaVersion(error); })
78 | ]);
79 | } catch (err) {
80 | logger.winston.error(err);
81 | }
82 | }
83 |
84 | function sqlOutput(error, table_name) {
85 | if (!error) {
86 | logger.winston.info("Table: " + table_name + " created");
87 | }
88 | }
89 |
90 | function setDBSchemaVersion(error) {
91 | if (error) {
92 | db.run("UPDATE version set version = ?", global.db_schema);
93 | logger.winston.info("Database Schema updated to v" + global.db_schema + " ");
94 | } else {
95 | db.run("INSERT into version (version) values (?)", global.db_schema);
96 | logger.winston.info("Database Schema v" + global.db_schema + " created");
97 | }
98 | }
99 |
100 | module.exports = db;
--------------------------------------------------------------------------------
/server/db/entities.js:
--------------------------------------------------------------------------------
1 | const db = require('./db');
2 | const logger = require('../util/logger');
3 |
4 | function getAllEntities(req, res, next) {
5 | logger.winston.info('Entities.getAllEntities');
6 | db.all('select * from entities', function(err, data) {
7 | if (err) {
8 | logger.winston.error(err);
9 | } else {
10 | res.status(200).json(data);
11 | }
12 | });
13 | }
14 |
15 | function getAllEntitiesForBot(req, res, next) {
16 | logger.winston.info('Entities.getAllEntitiesForBot');
17 | db.all('select * from entities where bot_id = ? order by entity_id desc', req.params.bot_id, function(err, data) {
18 | if (err) {
19 | logger.winston.error(err);
20 | } else {
21 | res.status(200).json(data);
22 | }
23 | });
24 | }
25 |
26 | function getSingleEntity(req, res, next) {
27 | logger.winston.info('Entities.getSingleEntity');
28 | db.get('select * from entities where entity_id = ?', req.params.entity_id, function(err, data) {
29 | if (err) {
30 | logger.winston.error(err);
31 | } else {
32 | res.status(200).json(data);
33 | }
34 | });
35 | }
36 |
37 | function createEntity(req, res, next) {
38 | logger.winston.info('Entities.createEntity');
39 |
40 | db.run('insert into entities(bot_id, entity_name, slot_data_type)' + 'values (?,?,?)', [req.body.bot_id, req.body.entity_name, req.body.slot_data_type], function(err) {
41 | if (err) {
42 | logger.winston.error("Error inserting a new record");
43 | } else {
44 | res.status(200).json({ status: 'success', message: 'Inserted' });
45 | }
46 | });
47 | }
48 |
49 | function updateEntity(req, res, next) {
50 | logger.winston.info('entities.updateEntity');
51 |
52 | db.run('update entities set entity_name = ?, slot_data_type = ? where entity_id = ?', [req.body.entity_name, req.body.slot_data_type, req.params.entity_id], function(err) {
53 | if (err) {
54 | logger.winston.error("Error updating the record");
55 | } else {
56 | res.status(200).json({ status: 'success', message: 'Updated' });
57 | }
58 | });
59 | }
60 |
61 | function removeEntity(req, res, next) {
62 | logger.winston.info('entities.updateEntity');
63 | db.run('delete from entities where entity_id = ?', req.params.entity_id, function(err) {
64 | if (err) {
65 | logger.winston.error("Error removing the record");
66 | } else {
67 | res.status(200).json({ status: 'success', message: 'Removed' });
68 | }
69 | });
70 | }
71 |
72 | module.exports = {
73 | getAllEntities,
74 | getAllEntitiesForBot,
75 | getSingleEntity,
76 | createEntity,
77 | updateEntity,
78 | removeEntity
79 | };
80 |
--------------------------------------------------------------------------------
/server/db/expressions.js:
--------------------------------------------------------------------------------
1 | const db = require('./db');
2 | const logger = require('../util/logger');
3 |
4 | function getSingleExpression(req, res, next) {
5 | logger.winston.info('expression.getSingleExpression');
6 |
7 | db.get('select * from expressions where expression_id = ?', req.params.expression_id, function(err, data) {
8 | if (err) {
9 | logger.winston.error(err);
10 | } else {
11 | res.status(200).json(data);
12 | }
13 | });
14 | }
15 |
16 | function getIntentExpressions(req, res, next) {
17 | logger.winston.info('expression.getIntentExpressions');
18 | db.all('select * from expressions where intent_id = ? order by expression_id desc', req.params.intent_id, function(err, data) {
19 | if (err) {
20 | logger.winston.error(err);
21 | } else {
22 | res.status(200).json(data);
23 | }
24 | });
25 | }
26 |
27 | function getIntentExpressionQuery(req, res, next) {
28 | logger.winston.info('expression.getIntentExpressionQuery');
29 | var array_intentIds = req.query.intent_ids.split(","); //Very hacky due to the node-sqlite not supporting IN from an array
30 | db.all('select * from expressions where intent_id in (' + array_intentIds + ') order by expression_id desc', function(err, data) {
31 | if (err) {
32 | logger.winston.error(err);
33 | } else {
34 | res.status(200).json(data);
35 | }
36 | });
37 | }
38 |
39 | function createIntentExpression(req, res, next) {
40 | logger.winston.info('expressions.createIntentExpression');
41 | db.run('insert into expressions(intent_id, expression_text)' + 'values (?,?)', [req.body.intent_id, req.body.expression_text], function(err) {
42 | if (err) {
43 | logger.winston.error("Error inserting a new record");
44 | } else {
45 | res.status(200).json({ status: 'success', message: 'Inserted' });
46 | }
47 | });
48 | }
49 |
50 | function removeExpression(req, res, next) {
51 | logger.winston.info('expressions.removeExpression');
52 | db.run('delete from expressions where expression_id = ?', req.params.expression_id, function(err) {
53 | if (err) {
54 | logger.winston.error("Error removing the record");
55 | } else {
56 | res.status(200).json({ status: 'success', message: 'Removed' });
57 | }
58 | });
59 | }
60 |
61 | function updateExpression(req, res, next) {
62 | logger.winston.info('expressions.updateExpressionEndpoint');
63 | db.run('update expressions set expression_text = ? where expression_id = ?', [req.body.expression_text, req.body.expression_id], function(err) {
64 | if (err) {
65 | logger.winston.error("Error updating the record");
66 | } else {
67 | res.status(200).json({ status: 'success', message: 'Updated' });
68 | }
69 | });
70 | }
71 |
72 | module.exports = {
73 | getSingleExpression,
74 | getIntentExpressions,
75 | createIntentExpression,
76 | removeExpression,
77 | getIntentExpressionQuery,
78 | updateExpression};
79 |
--------------------------------------------------------------------------------
/server/db/intents.js:
--------------------------------------------------------------------------------
1 | const db = require('./db');
2 | const logger = require('../util/logger');
3 |
4 | function getSingleIntent(req, res, next) {
5 | logger.winston.info('intents.getSingleIntents');
6 | db.get('select * from intents where intent_id = ?', req.params.intent_id, function(err, data) {
7 | if (err) {
8 | logger.winston.error(err);
9 | } else {
10 | res.status(200).json(data);
11 | }
12 | });
13 | }
14 |
15 | function getBotIntents(req, res, next) {
16 | logger.winston.info('intents.getBotIntents');
17 | db.all('select * from intents where bot_id = ? order by intent_id desc', req.params.bot_id, function(err, data) {
18 | if (err) {
19 | logger.winston.error(err);;
20 | } else {
21 | res.status(200).json(data);
22 | }
23 | });
24 | }
25 |
26 | function createBotIntent(req, res, next) {
27 | logger.winston.info('intents.createBotIntent');
28 | db.run('insert into intents (bot_id, intent_name)' + 'values (?,?)', [req.body.bot_id, req.body.intent_name], function(err) {
29 | if (err) {
30 | logger.winston.error("Error inserting a new record");
31 | } else {
32 | res.status(200).json({ status: 'success', message: 'Inserted' });
33 | }
34 | });
35 | }
36 |
37 | function updateIntent(req, res, next) {
38 | logger.winston.info('intents.updateIntent');
39 |
40 | db.run('update intents set intent_name = ? where intent_id = ?', [req.body.intent_name, req.params.intent_id], function(err) {
41 | if (err) {
42 | logger.winston.error("Error updating the record");
43 | } else {
44 | res.status(200).json({ status: 'success', message: 'Updated' });
45 | }
46 | });
47 | }
48 |
49 | function removeIntent(req, res, next) {
50 | //Remove all sub components of intent
51 | logger.winston.info('intents.removeIntent');
52 |
53 | db.run('delete from intents where intent_id = ?', req.params.intent_id, function(err) {
54 | if (err) {
55 | logger.winston.error("Error removing the record");
56 | } else {
57 | res.status(200).json({ status: 'success', message: 'Removed' });
58 | }
59 | });
60 | }
61 |
62 | module.exports = {
63 | getBotIntents,
64 | createBotIntent,
65 | getSingleIntent,
66 | updateIntent,
67 | removeIntent
68 | };
69 |
--------------------------------------------------------------------------------
/server/db/logs.js:
--------------------------------------------------------------------------------
1 | const db = require('./db');
2 | const logger = require('../util/logger');
3 |
4 | module.exports = {
5 | getLogs,
6 | getRequestUsageTotal,
7 | getIntentUsageTotal,
8 | getIntentUsageByDay,
9 | getAvgIntentUsageByDay,
10 | getNluParseLogByBot,
11 | getBotsByIntentConfidencePct,
12 | getIntentsMostUsed,
13 | getAvgNluResponseTimesLast30Days,
14 | getAvgUserResponseTimesLast30Days,
15 | getActiveUserCountLast12Months,
16 | getActiveUserCountLast30Days,
17 | getTotalLogEntries,
18 | logRequest
19 | };
20 |
21 | function logRequest(req, type, data) {
22 | try {
23 | const obj = {};
24 | obj.ip_address = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
25 | obj.query = req.originalUrl;
26 | obj.event_type = type;
27 | obj.event_data = JSON.stringify(data);
28 |
29 | db.run('insert into nlu_log (ip_address, query, event_type, event_data)' + 'values (?,?,?,?)', [obj.ip_address, obj.query, obj.event_type, obj.event_data], function(err) {
30 | if (err) {
31 | logger.winston.error("Error inserting a new record");
32 | }
33 | });
34 | } catch (err) {
35 | logger.winston.info('Error: ' + err);
36 | }
37 | }
38 |
39 | function getLogs(req, res, next) {
40 | db.all('select * from nlu_log where event_type = ? order by timestamp desc', req.params.query, function(err, data) {
41 | if (err) {
42 | logger.winston.error(err);
43 | } else {
44 | res.status(200).json(data);
45 | }
46 | });
47 | }
48 |
49 | function getRequestUsageTotal(req, res, next) {
50 | db.get("select count(*) from nlu_log where event_type = 'parse'", req.params.query, function(err, data) {
51 | if (err) {
52 | logger.winston.error(err);
53 | } else {
54 | res.status(200).json({total_request_usage: data['count(*)']});
55 | }
56 | });
57 | }
58 |
59 | function getTotalLogEntries(req, res, next) {
60 | db.get("select count(*) from nlu_log", req.params.query, function(err, data) {
61 | if (err) {
62 | logger.winston.error(err);
63 | } else {
64 | res.status(200).json({total_log_entries: data['count(*)']});
65 | }
66 | });
67 | }
68 |
69 | function getIntentUsageByDay(req, res, next) {
70 | db.all("select strftime('%m/%d', timestamp) as day, count(*) as cnt from nlu_log group by strftime('%m/%d', timestamp)", req.params.query, function(err, data) {
71 | if (err) {
72 | logger.winston.error(err);
73 | } else {
74 | res.status(200).json(data);
75 | }
76 | });
77 | }
78 |
79 |
80 | /* Not used yet */
81 |
82 | function getIntentUsageTotal(req, res, next) {
83 | const data = db.get('nlu_log')
84 | .filter({ event_type: 'parse' })
85 | .size()
86 | .value()
87 | res.status(200).json({intent_usage: data});
88 | }
89 |
90 | function getActiveUserCountLast30Days(req, res, next) {
91 | db.any('select * from active_user_count_30_days')
92 | .then(function (data) {
93 | res.status(200)
94 | .json(data);
95 | })
96 | .catch(function (err) {
97 | return next(err);
98 | });
99 | }
100 |
101 | function getActiveUserCountLast12Months(req, res, next) {
102 | db.any('select * from active_user_count_12_months')
103 | .then(function (data) {
104 | res.status(200)
105 | .json(data);
106 | })
107 | .catch(function (err) {
108 | return next(err);
109 | });
110 | }
111 |
112 | function getAvgUserResponseTimesLast30Days(req, res, next) {
113 | db.any('select * from avg_user_response_times_30_days')
114 | .then(function (data) {
115 | res.status(200)
116 | .json(data);
117 | })
118 | .catch(function (err) {
119 | return next(err);
120 | });
121 | }
122 |
123 | function getAvgNluResponseTimesLast30Days(req, res, next) {
124 | db.any('select * from avg_nlu_response_times_30_days')
125 | .then(function (data) {
126 | res.status(200)
127 | .json(data);
128 | })
129 | .catch(function (err) {
130 | return next(err);
131 | });
132 | }
133 |
134 | function getIntentsMostUsed(req, res, next) {
135 | const bot_id = req.params.bot_id;
136 | db.any('select * from intents_most_used where bot_id=$1', bot_id)
137 | .then(function (data) {
138 | res.status(200)
139 | .json(data);
140 | })
141 | .catch(function (err) {
142 | return next(err);
143 | });
144 | }
145 |
146 | function getBotsByIntentConfidencePct(req, res, next) {
147 | const bot_id = req.params.bot_id;
148 | db.any('select count(*),intent_confidence_pct, bots.bot_id, bots.bot_name from nlu_parse_log, bots, messages '
149 | + ' where messages.bot_id = bots.bot_id and messages.messages_id=nlu_parse_log.messages_id '
150 | + ' and bots.bot_id=$1 group by intent_confidence_pct, bots.bot_id, bots.bot_name ', bot_id)
151 | .then(function (data) {
152 | res.status(200)
153 | .json(data);
154 | })
155 | .catch(function (err) {
156 | return next(err);
157 | });
158 | }
159 |
160 | function getNluParseLogByBot(req, res, next) {
161 | const bot_id = req.params.bot_id;
162 | db.any('select * from nlu_parse_log where bot_id = $1 order by timestamp desc', bot_id)
163 | .then(function (data) {
164 | res.status(200)
165 | .json(data);
166 | })
167 | .catch(function (err) {
168 | return next(err);
169 | });
170 | }
171 |
172 | function getAvgIntentUsageByDay(req, res, next) {
173 | db.any('select round(avg(count)) as avg from intent_usage_by_day')
174 | .then(function (data) {
175 | res.status(200)
176 | .json(data);
177 | })
178 | .catch(function (err) {
179 | return next(err);
180 | });
181 | }
182 |
183 |
184 |
--------------------------------------------------------------------------------
/server/db/models.js:
--------------------------------------------------------------------------------
1 | const db = require('./db');
2 | const logger = require('../util/logger');
3 | const fs = require('fs');
4 |
5 | function getBotModels(req, res, next) {
6 | logger.winston.info('Model.getBotModels');
7 | db.all('select * from models where bot_id = ? order by model_id desc', req.params.bot_id, function(err, data) {
8 | if (err) {
9 | logger.winston.error(err);
10 | } else {
11 | res.status(200).json(data);
12 | }
13 | });
14 | }
15 |
16 | function createModel(req, res, next) {
17 | logger.winston.info('Bot.createModel');
18 | db.run('insert into models(model_name, comment, bot_id, server_path, local_path)' + 'values (?,?,?,?,?)', [req.body.file_name, req.body.comment, req.body.bot_id, req.body.server_path, 'Manually added'], function (err) {
19 | if (err) {
20 | logger.winston.error("Error inserting a new record: " + err);
21 | } else {
22 | logger.winston.info("Model saved to models table");
23 | res.status(200).json({ status: 'success', message: 'Inserted' });
24 | }
25 | });
26 | }
27 |
28 | function removeModel(req, res, next) {
29 | logger.winston.info('Model.removeModel');
30 | db.run('delete from models where model_id = ?', req.query.model_id, function(err) {
31 | if (err) {
32 | logger.winston.error("Error removing the record");
33 | } else {
34 | if (req.query.local_path && req.query.local_path != "Manually Added") {
35 | fs.unlink(req.query.local_path, (err) => {
36 | if (err) {
37 | logger.winston.info(err)
38 | return
39 | }
40 | })
41 | }
42 | res.status(200).json({ status: 'success', message: 'Removed' });
43 | }
44 | });
45 | }
46 |
47 | module.exports = {
48 | getBotModels,
49 | removeModel,
50 | createModel
51 | };
--------------------------------------------------------------------------------
/server/db/parameters.js:
--------------------------------------------------------------------------------
1 | const db = require('./db');
2 | const logger = require('../util/logger');
3 |
4 | function getExpressionParametersQuery(req, res, next) {
5 | logger.winston.info('parameters.getExpressionParametersQuery');
6 | const expressionIds = req.query.expression_ids;
7 | var array_expressionIds = expressionIds.split(","); //Very hacky due to the node-sqlite not supporting IN from an array
8 | db.all("select * from expression_parameters inner join entities on expression_parameters.entity_id = entities.entity_id where expression_id in (" + array_expressionIds + ")", function(err, data) {
9 | if (err) {
10 | logger.winston.error(err);
11 | } else {
12 | res.status(200).json(data);
13 | }
14 | });
15 |
16 | }
17 |
18 | function getIntentParameters(req, res, next) {
19 | logger.winston.info('parameters.getIntentParameters');
20 | db.all('select * from expression_parameters where intent_id = ?', req.params.intent_id, function(err, data) {
21 | if (err) {
22 | logger.winston.error(err);
23 | } else {
24 | res.status(200).json(data);
25 | }
26 | });
27 | }
28 |
29 | function getExpressionParameters(req, res, next) {
30 | logger.winston.info('parameters.getExpressionParameters');
31 | db.all('select * from expression_parameters where expression_id = ?', req.params.expression_id, function(err, data) {
32 | if (err) {
33 | logger.winston.error(err);
34 | } else {
35 | res.status(200).json(data);
36 | }
37 | });
38 | }
39 |
40 | function createExpressionParameter(req, res, next) {
41 | logger.winston.info('parameters.createExpressionParameter');
42 | db.run('insert into expression_parameters(expression_id, parameter_start, parameter_end, parameter_value, intent_id)' + 'values (?,?,?,?,?)', [req.body.expression_id, req.body.parameter_start, req.body.parameter_end, req.body.parameter_value, req.body.intent_id], function(err) {
43 | if (err) {
44 | logger.winston.error("Error inserting a new record");
45 | } else {
46 | res.status(200).json({ status: 'success', message: 'Inserted' });
47 | }
48 | });
49 | }
50 |
51 | function updateParameter(req, res, next) {
52 | //Sets the entity once a new parameter has been created
53 | logger.winston.info('parameters.updateParameter');
54 | db.run('update expression_parameters set entity_id = ? where parameter_id = ?', [req.body.entity_id, req.body.parameter_id], function(err) {
55 | if (err) {
56 | logger.winston.error("Error updating the record");
57 | } else {
58 | res.status(200).json({ status: 'success', message: 'Updated' });
59 | }
60 | });
61 | }
62 |
63 | function removeExpressionParameter(req, res, next) {
64 | db.run('delete from expression_parameters where parameter_id = ?', req.params.parameter_id, function(err) {
65 | if (err) {
66 | logger.winston.error("Error removing the record");
67 | } else {
68 | res.status(200).json({ status: 'success', message: 'Removed' });
69 | }
70 | });
71 | }
72 |
73 | module.exports = {
74 | getExpressionParameters,
75 | getIntentParameters,
76 | createExpressionParameter,
77 | removeExpressionParameter,
78 | updateParameter,
79 | getExpressionParametersQuery
80 | };
81 |
--------------------------------------------------------------------------------
/server/db/regex.js:
--------------------------------------------------------------------------------
1 | const db = require('./db');
2 | const logger = require('../util/logger');
3 |
4 | function getBotRegex(req, res, next) {
5 | logger.winston.info('regex.getBotRegex');
6 | db.all('select * from regex where bot_id = ? order by regex_id desc', req.params.bot_id, function(err, data) {
7 | if (err) {
8 | logger.winston.error(err);
9 | } else {
10 | res.status(200).json(data);
11 | }
12 | });
13 | }
14 |
15 | function getSingleRegex(req, res, next) {
16 | logger.winston.info('regex.getSingleRegex');
17 | db.get('select * from regex where regex_id = ?', req.params.regex_id, function(err, data) {
18 | if (err) {
19 | logger.winston.error(err);
20 | } else {
21 | res.status(200).json(data);
22 | }
23 | });
24 | }
25 |
26 | function createRegex(req, res, next) {
27 | logger.winston.info('regex.createRegex');
28 | db.run('insert into regex(bot_id, regex_name, regex_pattern)' + 'values (?,?,?)', [req.body.bot_id, req.body.regex_name, req.body.regex_pattern], function(err) {
29 | if (err) {
30 | logger.winston.error("Error inserting a new record");
31 | } else {
32 | res.status(200).json({ status: 'success', message: 'Inserted' });
33 | }
34 | });
35 | }
36 |
37 | function updateRegex(req, res, next) {
38 | logger.winston.info('regex.updateRegex');
39 | db.run('update regex set regex_name = ?, regex_pattern = ? where regex_id = ?', [req.body.regex_name, req.body.regex_pattern, req.body.regex_id], function(err) {
40 | if (err) {
41 | logger.winston.error("Error updating the record");
42 | } else {
43 | res.status(200).json({ status: 'success', message: 'Updated' });
44 | }
45 | });
46 | }
47 |
48 | function removeRegex(req, res, next) {
49 | logger.winston.info('regex.removeRegex');
50 | db.run('delete from regex where regex_id = ?', req.params.regex_id, function(err) {
51 | if (err) {
52 | logger.winston.error("Error removing the record");
53 | } else {
54 | res.status(200).json({ status: 'success', message: 'Removed' });
55 | }
56 | });
57 | }
58 |
59 | module.exports = {
60 | getBotRegex,
61 | getSingleRegex,
62 | createRegex,
63 | updateRegex,
64 | removeRegex};
65 |
--------------------------------------------------------------------------------
/server/db/responses.js:
--------------------------------------------------------------------------------
1 | const db = require('./db');
2 | const logger = require('../util/logger');
3 |
4 | function createResponse(req, res, next) {
5 | logger.winston.info('responses.createResponse');
6 | db.run('insert into responses (response_text, action_id, response_type)' + 'values (?,?,?)', [req.body.response_text, req.body.action_id, req.body.response_type], function(err) {
7 | if (err) {
8 | logger.winston.error("Error inserting a new record");
9 | } else {
10 | res.status(200).json({ status: 'success', message: 'Inserted' });
11 | }
12 | });
13 | }
14 |
15 | function updateResponse(req, res, next) {
16 | logger.winston.info('responses.updateResponse');
17 | db.run('update responses set response_text = ?, response_type = ? where response_id = ?', [req.body.response_text, req.body.response_type, req.body.response_id], function(err) {
18 | if (err) {
19 | logger.winston.error("Error updating the record");
20 | } else {
21 | res.status(200).json({ status: 'success', message: 'Updated' });
22 | }
23 | });
24 | }
25 |
26 | function deleteResponse(req, res, next) {
27 | logger.winston.info('responses.removeResponse');
28 | db.run('delete from responses where response_id = ?', req.query.response_id, function(err) {
29 | if (err) {
30 | logger.winston.error("Error removing the record");
31 | } else {
32 | res.status(200).json({ status: 'success', message: 'Removed' });
33 | }
34 | });
35 | }
36 |
37 | module.exports = {
38 | createResponse,
39 | deleteResponse,
40 | updateResponse
41 | };
--------------------------------------------------------------------------------
/server/db/settings.js:
--------------------------------------------------------------------------------
1 | const db = require('./db');
2 | const logger = require('../util/logger');
3 |
4 | function getSingleSetting(req, res, next) {
5 | logger.winston.info('settings.getSingleSetting');
6 | const settingName = req.params.setting_name;
7 |
8 | db.get('select * from settings where setting_name = ?', settingName, function(err, data) {
9 | if (err) {
10 | logger.winston.error(err);
11 | } else {
12 | res.status(200).json(data);
13 | }
14 | });
15 | }
16 |
17 | function getSettings(req, res, next) {
18 | logger.winston.info('settings.getSettings');
19 | db.all('select * from settings', function(err, settings) {
20 | if (err) {
21 | logger.winston.error(err);
22 | } else {
23 | db.all('select * from version', function(err, version) {
24 | settings.push({ 'ui_version': version[0].version });
25 | res.status(200).json(settings);
26 | });
27 | }
28 | });
29 | }
30 |
31 | function updateSetting(req, res, next) {
32 | logger.winston.info('settings.updateSetting');
33 | db.run('update settings set setting_value = ? where setting_name = ?', [req.body.setting_value, req.body.setting_name], function(err) {
34 | if (err) {
35 | logger.winston.error("Error updating the record");
36 | } else {
37 | res.status(200).json({ status: 'success', message: 'Updated' });
38 | }
39 | });
40 | }
41 |
42 | module.exports = {
43 | getSingleSetting,
44 | getSettings,
45 | updateSetting};
46 |
--------------------------------------------------------------------------------
/server/db/stories.js:
--------------------------------------------------------------------------------
1 | const db = require('./db');
2 | const logger = require('../util/logger');
3 |
4 | function getAllBotStories(req, res, next) {
5 | logger.winston.info('Stories.getAllStories');
6 | db.all('select * from stories where bot_id = ? order by story_id desc', req.params.bot_id, function(err, data) {
7 | if (err) {
8 | logger.winston.error(err);
9 | } else {
10 | res.status(200).json(data);
11 | }
12 | });
13 | }
14 |
15 | function createStory(req, res, next) {
16 | logger.winston.info('Stories.createStory');
17 | db.run('insert into stories(story_name, story, bot_id)' + 'values (?,?,?)', [req.body.story_name, req.body.story, req.body.bot_id], function(err) {
18 | if (err) {
19 | logger.winston.error("Error inserting a new record");
20 | } else {
21 | res.status(200).json({ status: 'success', message: 'Inserted' });
22 | }
23 | });
24 | }
25 |
26 | function updateStory(req, res, next) {
27 | logger.winston.info('Stories.updateStory');
28 | db.run('update stories set story = ? where story_id = ?', [req.body.story, req.body.story_id], function(err) {
29 | if (err) {
30 | logger.winston.error("Error updating the record");
31 | } else {
32 | res.status(200).json({ status: 'success', message: 'Updated' });
33 | }
34 | });
35 | }
36 |
37 | function removeStory(req, res) {
38 | logger.winston.info('Stories.updateStory');
39 | db.run('delete from stories where story_id = ?', req.query.story_id, function(err) {
40 | if (err) {
41 | logger.winston.error("Error removing the record");
42 | } else {
43 | res.status(200).json({ status: 'success', message: 'Removed' });
44 | }
45 | });
46 | }
47 |
48 | function searchStoryAttributes(req, res, next) {
49 | logger.winston.info('Stories.searchStoryAttributes');
50 | var search_string = "%" + req.query.search_text + "%";
51 | db.all("select * from intents where intent_name like ? and bot_id = ?", [search_string, req.params.bot_id], function(err, intents) {
52 | if (err) {
53 | logger.winston.error(err);
54 | } else {
55 | db.all("select * from entities where entity_name like ? and bot_id = ?", [search_string, req.params.bot_id], function(err, entities) {
56 | if (err) {
57 | logger.winston.error(err);
58 | } else {
59 | db.all("select * from actions where action_name like ? and bot_id = ?", [search_string, req.params.bot_id], function(err, actions) {
60 | if (err) {
61 | logger.winston.error(err);
62 | } else {
63 | var data = [];
64 | try {
65 | for (action of actions) {
66 | data.push({text: action.action_name, type: "action"});
67 | }
68 | } catch (err) {
69 | logger.winston.error(err);
70 | }
71 | try {
72 | for (entity of entities) {
73 | data.push({text: entity.entity_name, type: "entity"});
74 | }
75 | } catch (err) {
76 | logger.winston.error(err);
77 | }
78 | try {
79 | for (intent of intents) {
80 | data.push({text: intent.intent_name, type: "intent"});
81 | }
82 | } catch (err) {
83 | logger.winston.error(err);
84 | }
85 | res.status(200).json(data);
86 | }
87 | });
88 | }
89 | });
90 | }
91 | });
92 | }
93 |
94 | module.exports = {
95 | searchStoryAttributes,
96 | getAllBotStories,
97 | createStory,
98 | updateStory,
99 | removeStory
100 | };
--------------------------------------------------------------------------------
/server/db/synonyms.js:
--------------------------------------------------------------------------------
1 | const db = require('./db');
2 | const logger = require('../util/logger');
3 |
4 | function getSingleSynonym(req, res, next) {
5 | logger.winston.info('synonym.getSingleSynonym');
6 | db.get('select * from synonyms where synonym_id = ?', req.params.synonym_id, function(err, data) {
7 | if (err) {
8 | logger.winston.error(err);
9 | } else {
10 | res.status(200).json(data);
11 | }
12 | });
13 | }
14 |
15 | function getBotSynonyms(req, res, next) {
16 | logger.winston.info('synonym.getBotSynonyms');
17 |
18 | db.all('select * from synonyms where bot_id = ? order by synonym_id desc', req.params.bot_id, function(err, data) {
19 | if (err) {
20 | logger.winston.error(err);
21 | } else {
22 | res.status(200).json(data);
23 | }
24 | });
25 | }
26 |
27 | function createBotSynonym(req, res, next) {
28 | logger.winston.info('synonym.createBotSynonym');
29 | db.run('insert into synonyms(bot_id, synonym_reference, regex_pattern)' + 'values (?,?,?)', [req.body.bot_id, req.body.synonym_reference, req.body.regex_pattern], function(err) {
30 | if (err) {
31 | logger.winston.error("Error inserting a new record");
32 | } else {
33 | db.get('SELECT last_insert_rowid()', function(err, data) {
34 | if (err) {
35 | res.status(500).json({ status: 'error', message: '' });
36 | } else {
37 | res.status(200).json({ status: 'success', message: 'Inserted', synonym_id: data['last_insert_rowid()'] });
38 | }
39 | });
40 | }
41 | });
42 | }
43 |
44 | function removeSynonym(req, res, next) {
45 | logger.winston.info('synonym.removeExpression');
46 | db.run("delete from synonym_variants where synonym_id = ?", req.params.synonym_id);
47 | db.run('delete from synonyms where synonym_id = ?', req.params.synonym_id, function(err) {
48 | if (err) {
49 | logger.winston.error("Error removing the record");
50 | } else {
51 | res.status(200).json({ status: 'success', message: 'Removed' });
52 | }
53 | });
54 | }
55 |
56 | module.exports = {
57 | getSingleSynonym,
58 | getBotSynonyms,
59 | createBotSynonym,
60 | removeSynonym};
61 |
--------------------------------------------------------------------------------
/server/db/variants.js:
--------------------------------------------------------------------------------
1 | const db = require('./db');
2 | const logger = require('../util/logger');
3 |
4 | function getSingleVariant(req, res, next) {
5 | logger.winston.info('variants.getSingleVariant');
6 | db.get('select * from synonym_variants where synonym_variant_id = ?', req.params.synonym_variant_id, function(err, data) {
7 | if (err) {
8 | logger.winston.error(err);
9 | } else {
10 | res.status(200).json(data);
11 | }
12 | });
13 | }
14 |
15 | function getSynonymVariants(req, res, next) {
16 | logger.winston.info('variants.getSynonymVariants');
17 | db.all('select * from synonym_variants where synonym_id = ? order by synonym_variant_id desc', req.params.synonym_id, function(err, data) {
18 | if (err) {
19 | logger.winston.error(err);
20 | } else {
21 | res.status(200).json(data);
22 | }
23 | });
24 | }
25 |
26 | function getSynonymsVariants(req, res, next) {
27 | logger.winston.info('variants.getSynonymVariants');
28 | const synonymsId = req.params.synonyms_id;
29 | var array_synonymIds = synonymsId.split(","); //Very hacky due to the node-sqlite not supporting IN from an array
30 | db.all('select * from synonym_variants where synonym_id in (' + array_synonymIds + ')', function(err, data) {
31 | if (err) {
32 | logger.winston.error(err);
33 | } else {
34 | res.status(200).json(data);
35 | }
36 | });
37 | }
38 |
39 | function createVariant(req, res, next) {
40 | logger.winston.info('variants.createVariant');
41 | db.run('insert into synonym_variants (synonym_id, synonym_value)' + 'values (?, ?)', [req.body.synonym_id, req.body.synonym_value], function(err) {
42 | if (err) {
43 | logger.winston.error("Error inserting a new record");
44 | } else {
45 | db.get('SELECT last_insert_rowid()', function(err, data) {
46 | if (err) {
47 | res.status(500).json({ status: 'error', message: '' });
48 | } else {
49 | res.status(200).json({ status: 'success', message: 'Inserted', synonym_variant_id: data['last_insert_rowid()'] });
50 | }
51 | });
52 | }
53 | });
54 | }
55 |
56 | function removeVariant(req, res, next) {
57 | logger.winston.info('variants.removeVariant');
58 | db.run('delete from synonym_variants where synonym_variant_id = ?', req.params.synonym_variant_id, function(err) {
59 | if (err) {
60 | logger.winston.error("Error removing the record");
61 | } else {
62 | res.status(200).json({ status: 'success', message: 'Removed' });
63 | }
64 | });
65 | }
66 |
67 | function removeSynonymVariants(req, res, next) {
68 | logger.winston.info('variants.removeSynonymVariants');
69 | db.run('delete from synonym_variants where synonym_id = ?', req.params.synonym_id, function(err) {
70 | if (err) {
71 | logger.winston.error("Error removing the record");
72 | } else {
73 | res.status(200).json({ status: 'success', message: 'Removed' });
74 | }
75 | });
76 | }
77 |
78 | module.exports = {
79 | getSingleVariant,
80 | getSynonymVariants,
81 | createVariant,
82 | removeVariant,
83 | removeSynonymVariants,
84 | getSynonymsVariants
85 | };
86 |
--------------------------------------------------------------------------------
/server/routes/auth.js:
--------------------------------------------------------------------------------
1 | const jwt = require('jsonwebtoken');
2 | const db = require('../db/db');
3 | const logger = require('../util/logger');
4 |
5 | function authenticateUser(req, res, next) {
6 | //authenticate user
7 | logger.winston.info('Authenticate User');
8 | if (req.body.username === global.admin_username && req.body.password === global.admin_password) {
9 | //create token and send it back
10 | const tokenData = { username: 'admin', name: 'Portal Administrator' };
11 | // if user is found and password is right
12 | // create a token]
13 | var token = ""
14 | try {
15 | token = jwt.sign(tokenData, global.jwtsecret);
16 | } catch (err) {
17 | logger.winston.error(err);
18 | };
19 | // return the information including token as JSON
20 | res.json({ username: 'admin', token: token });
21 | } else {
22 | logger.winston.error('Information didnt match or not provided.');
23 | return res.status(401).send({
24 | success: false,
25 | message: 'Username and password didnt match.'});
26 | }
27 | }
28 |
29 | function authenticateClient(req, res, next) {
30 | //authenticate client based on client secret key
31 | //username,user_fullname,bot_name,client_secret_key should all be present in the body
32 | logger.winston.info('Authenticate Client');
33 | db.one(
34 | 'select * from bots where bot_name = $1 and client_secret_key=$2',
35 | [req.body.bot_name, req.body.client_secret_key]
36 | )
37 | .then(function(data) {
38 | const tokenData = {
39 | username: req.body.username,
40 | name: req.body.user_fullname};
41 | // if user is found and password is right
42 | // create a token
43 | try {
44 | const token = jwt.sign(tokenData, global.jwtsecret);
45 | } catch (err) {
46 | logger.winston.error(err);
47 | };
48 | // return the information including token as JSON
49 | res.status(200).json({ username: req.body.username, token: token });
50 | })
51 | .catch(function(err) {
52 | logger.winston.error('Client Authentication error: ' + err);
53 | return res.status(401).send({
54 | success: false,
55 | message: 'Client Authentication failed.'});
56 | });
57 | }
58 |
59 | module.exports = {
60 | authenticateUser: authenticateUser,
61 | authenticateClient: authenticateClient
62 | };
63 |
--------------------------------------------------------------------------------
/server/server.js:
--------------------------------------------------------------------------------
1 | // Global Variables
2 | global.rasa_endpoint = process.env.rasa_endpoint || process.env.npm_package_config_rasa_endpoint;
3 | global.jwtsecret = process.env.jwtsecret || process.env.npm_package_config_jwtsecret;
4 | global.loglevel = process.env.loglevel || process.env.npm_package_config_loglevel;
5 | global.admin_username = process.env.admin_username || process.env.npm_package_config_admin_username;
6 | global.admin_password = process.env.admin_password || process.env.npm_package_config_admin_password;
7 | global.db_schema = process.env.db_schema || process.env.npm_package_config_db_schema;
8 | global.db_autoupdate = process.env.db_autoupdate || process.env.npm_package_config_db_autoupdate;
9 |
10 | const express = require('express');
11 | const proxy = require('http-proxy-middleware');
12 | const bodyParser = require('body-parser');
13 | var app = express();
14 | const request = require('request');
15 | const routes = require('./routes/index');
16 | const db = require('./db/db');
17 |
18 | const logger = require('./util/logger');
19 |
20 | app.use(
21 | bodyParser.urlencoded({
22 | parameterLimit: 10000,
23 | limit: '2mb',
24 | extended: true
25 | })
26 | );
27 | app.use(bodyParser.json({ limit: '2mb' }));
28 |
29 | /** Serve static files for UI website on root / */
30 | app.use('/', express.static('web/src/'));
31 | app.use('/scripts', express.static('node_modules/'));
32 |
33 | const server = require('http').createServer(app);
34 |
35 | app.use('/api/v2/', routes);
36 |
37 | if (app.get('env') === 'development') {
38 | // error handlers
39 | // development error handler
40 | // will print stacktrace
41 | app.use(function(err, req, res, next) {
42 | res.status(err.code || 500).json({
43 | status: 'error',
44 | message: err
45 | });
46 | });
47 | } else {
48 | // production error handler
49 | // no stacktraces leaked to user
50 | app.use(function(err, req, res, next) {
51 | res.status(err.status || 500).json({
52 | status: 'error',
53 | message: err
54 | });
55 | });
56 | }
57 |
58 | const listener = server.listen(5001);
59 |
60 | checkRasaUI();
61 | checkRasa();
62 |
63 | function checkRasaUI() {
64 | logger.winston.info(
65 | 'Rasa UI Server: http://localhost:' + listener.address().port
66 | );
67 | }
68 |
69 | function checkRasa() {
70 | request(global.rasa_endpoint + '/status', {timeout: 12000}, function(error, response, body) {
71 | try {
72 | logger.winston.info('Rasa Server: ' + global.rasa_endpoint);
73 | if (body !== undefined) {
74 | logger.winston.info('--> Connected');
75 | }
76 | if (error !== null) {
77 | logger.winston.error('--> Unable to connect to Rasa Server: ' + error);
78 | }
79 | } catch (err) {
80 | logger.winston.error('Rasa Connection Error: ' + err);
81 | }
82 | });
83 | }
84 |
85 | module.exports = server
--------------------------------------------------------------------------------
/server/test/common.js:
--------------------------------------------------------------------------------
1 | // Import the dependencies for testing
2 | const app = require('../server');
3 | const db = require('../db/db');
4 | const logger = require('../util/logger');
5 | logger.winston.level = "info";
6 |
7 | const chai = require('chai');
8 | const chaiHttp = require('chai-http');
9 |
10 | // Configure chai
11 | chai.use(chaiHttp);
12 | chai.should();
13 |
14 | module.exports = {
15 | chai,
16 | app,
17 | db
18 | }
--------------------------------------------------------------------------------
/server/test/db/test_db.sqlite3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paschmann/rasa-ui/3f5deadb92a4392838b647e95d6c08752964566d/server/test/db/test_db.sqlite3
--------------------------------------------------------------------------------
/server/test/test.js:
--------------------------------------------------------------------------------
1 | var common = require("./common");
2 | const fs = require('fs');
3 |
4 | function importTest(name, path) {
5 | describe(name, function () {
6 | require(path);
7 | });
8 | }
9 |
10 | setTimeout(function () {
11 | db_file_path = "server/test/db/test_db.sqlite3";
12 |
13 | //Wait for test data to be inserted into DB
14 | describe("Rasa UI Server Tests", function () {
15 | importTest("Bots", './tests/bots.test');
16 | importTest("Intents", './tests/intents.test');
17 | importTest("Entity", './tests/entities.test');
18 | importTest("Regex", './tests/regex.test');
19 | importTest("Actions", './tests/actions.test');
20 | importTest("Conversations", './tests/conversations.test');
21 | importTest("Expressions", './tests/expressions.test');
22 | importTest("Models", './tests/models.test');
23 | importTest("Parameters", './tests/parameters.test');
24 | importTest("Responses", './tests/responses.test');
25 | importTest("Settings", './tests/settings.test');
26 | importTest("Stories", './tests/stories.test');
27 | importTest("Synonyms", './tests/synonyms.test');
28 | importTest("Variants", './tests/variants.test');
29 | });
30 | run();
31 | }, 1000);
--------------------------------------------------------------------------------
/server/test/tests/actions.test.js:
--------------------------------------------------------------------------------
1 | var common = require("../common");
2 | var chai = common.chai;
3 | var app = common.app;
4 | var db = common.db;
5 |
6 | describe("actions.test", () => {
7 | describe("GET /api/v2/actions/", () => {
8 | before(function () {
9 | db.run("INSERT into actions values (1, 'Action 1', 1)");
10 | });
11 |
12 | it("createAction: should create a new record", (done) => {
13 | let data = {
14 | bot_id: 1,
15 | action_name: "Action 2"
16 | }
17 | chai.request(app)
18 | .post('/api/v2/actions')
19 | .send(data)
20 | .end((err, res) => {
21 | res.should.have.status(200);
22 | res.body.should.be.a('object');
23 | res.body.should.have.property('status').eql('success');
24 | done();
25 | });
26 | });
27 |
28 | it("getBotActionsAndResponses: should get all records", (done) => {
29 | chai.request(app)
30 | .get('/api/v2/actions?bot_id=1')
31 | .end((err, res) => {
32 | res.should.have.status(200);
33 | res.body.should.be.a('array');
34 | done();
35 | });
36 | });
37 |
38 | it("removeAction: should delete a record", (done) => {
39 | chai.request(app)
40 | .delete('/api/v2/actions?action_id=2')
41 | .end((err, res) => {
42 | res.should.have.status(200);
43 | res.body.should.be.a('object');
44 | res.body.should.have.property('status').eql('success');
45 | done();
46 | });
47 | });
48 | });
49 | });
--------------------------------------------------------------------------------
/server/test/tests/bots.test.js:
--------------------------------------------------------------------------------
1 | var common = require("../common");
2 | var chai = common.chai;
3 | var app = common.app;
4 | var db = common.db;
5 |
6 | describe("bots.test", () => {
7 | describe("GET /api/v2/bots/", () => {
8 | before(function () {
9 | db.run("INSERT into bots values (1, 'Test Bot 1', '{}', '/models')");
10 | });
11 |
12 | it("createBot: should create a new record", (done) => {
13 | let bot = {
14 | bot_name: "Test Bot 2",
15 | bot_config: "{}",
16 | bot_output_folder: "/models"
17 | }
18 | chai.request(app)
19 | .post('/api/v2/bots')
20 | .send(bot)
21 | .end((err, res) => {
22 | res.should.have.status(200);
23 | res.body.should.be.a('object');
24 | res.body.should.have.property('status').eql('success');
25 | done();
26 | });
27 | });
28 |
29 | it("getAllBots: should get all bots records", (done) => {
30 | chai.request(app)
31 | .get('/api/v2/bots/')
32 | .end((err, res) => {
33 | res.should.have.status(200);
34 | res.body.should.be.a('array');
35 | done();
36 | });
37 | });
38 |
39 | it("getSingleBot: should get a single bot record", (done) => {
40 | chai.request(app)
41 | .get('/api/v2/bots/2')
42 | .end((err, res) => {
43 | res.should.have.status(200);
44 | res.body.should.be.a('object');
45 | res.body.should.have.property('bot_id').eql(2);
46 | done();
47 | });
48 | });
49 |
50 | it("updateBot: should update a record", (done) => {
51 | let bot = {
52 | bot_name: "Test Bot 2 Updated",
53 | bot_config: "{}",
54 | bot_output_folder: "/models"
55 | }
56 | chai.request(app)
57 | .put('/api/v2/bots/2')
58 | .send(bot)
59 | .end((err, res) => {
60 | res.should.have.status(200);
61 | res.body.should.be.a('object');
62 | res.body.should.have.property('status').eql('success');
63 | done();
64 | });
65 | });
66 |
67 | it("removeBot: should delete a single bot record", (done) => {
68 | chai.request(app)
69 | .delete('/api/v2/bots/3')
70 | .end((err, res) => {
71 | res.should.have.status(200);
72 | res.body.should.be.a('object');
73 | res.body.should.have.property('status').eql('success');
74 | done();
75 | });
76 | });
77 | });
78 | });
--------------------------------------------------------------------------------
/server/test/tests/conversations.test.js:
--------------------------------------------------------------------------------
1 | var common = require("../common");
2 | var chai = common.chai;
3 | var app = common.app;
4 | var db = common.db;
5 |
6 | describe("conversations.test", () => {
7 | describe("GET /api/v2/conversations/", () => {
8 | before(function () {
9 | db.run("INSERT into conversations (bot_id) values (1)");
10 | });
11 |
12 | it("createConversation: should create a new record", (done) => {
13 | let data = {
14 | bot_id: 1
15 | }
16 | chai.request(app)
17 | .post('/api/v2/conversations')
18 | .send(data)
19 | .end((err, res) => {
20 | res.should.have.status(200);
21 | res.body.should.be.a('object');
22 | res.body.should.have.property('status').eql('success');
23 | done();
24 | });
25 | });
26 |
27 | it("getConversation: should get all records", (done) => {
28 | chai.request(app)
29 | .get('/api/v2/conversations/1')
30 | .end((err, res) => {
31 | res.should.have.status(200);
32 | res.body.should.be.a('array');
33 | done();
34 | });
35 | });
36 |
37 | it("removeConversation: should delete a record", (done) => {
38 | chai.request(app)
39 | .delete('/api/v2/conversations?conversation_id=2')
40 | .end((err, res) => {
41 | res.should.have.status(200);
42 | res.body.should.be.a('object');
43 | res.body.should.have.property('status').eql('success');
44 | done();
45 | });
46 | });
47 | });
48 | });
--------------------------------------------------------------------------------
/server/test/tests/entities.test.js:
--------------------------------------------------------------------------------
1 | var common = require("../common");
2 | var chai = common.chai;
3 | var app = common.app;
4 | var db = common.db;
5 |
6 | describe("entities.test", () => {
7 | describe("GET /api/v2/entities/", () => {
8 | before(function () {
9 | db.run("INSERT into entities values (1, 'Entity 1', 'TEXT', 1)");
10 | });
11 |
12 | it("createEntity: should create a new record", (done) => {
13 | let data = {
14 | bot_id: 1,
15 | entity_name: "Entity 2",
16 | slot_data_type: "TEXT"
17 | }
18 | chai.request(app)
19 | .post('/api/v2/entities')
20 | .send(data)
21 | .end((err, res) => {
22 | res.should.have.status(200);
23 | res.body.should.be.a('object');
24 | res.body.should.have.property('status').eql('success');
25 | done();
26 | });
27 | });
28 |
29 | it("getAllEntities: should get all records", (done) => {
30 | chai.request(app)
31 | .get('/api/v2/entities/bot/1')
32 | .end((err, res) => {
33 | res.should.have.status(200);
34 | res.body.should.be.a('array');
35 | done();
36 | });
37 | });
38 |
39 | it("getSingleEntity: should get a single record", (done) => {
40 | chai.request(app)
41 | .get('/api/v2/entities/1')
42 | .end((err, res) => {
43 | res.should.have.status(200);
44 | res.body.should.be.a('object');
45 | res.body.should.have.property('entity_id').eql(1);
46 | done();
47 | });
48 | });
49 |
50 | it("updateEntity: should update a record", (done) => {
51 | let data = {
52 | entity_name: "Entity 2 Updated"
53 | }
54 | chai.request(app)
55 | .put('/api/v2/entities/2')
56 | .send(data)
57 | .end((err, res) => {
58 | res.should.have.status(200);
59 | res.body.should.be.a('object');
60 | res.body.should.have.property('status').eql('success');
61 | done();
62 | });
63 | });
64 |
65 | it("removeIntent: should delete a record", (done) => {
66 | chai.request(app)
67 | .delete('/api/v2/entities/2')
68 | .end((err, res) => {
69 | res.should.have.status(200);
70 | res.body.should.be.a('object');
71 | res.body.should.have.property('status').eql('success');
72 | done();
73 | });
74 | });
75 | });
76 | });
--------------------------------------------------------------------------------
/server/test/tests/expressions.test.js:
--------------------------------------------------------------------------------
1 | var common = require("../common");
2 | var chai = common.chai;
3 | var app = common.app;
4 | var db = common.db;
5 |
6 | describe("expressions.test", () => {
7 | describe("GET /api/v2/expressions/", () => {
8 | before(function () {
9 | db.run("INSERT into expressions values (1, 1, 'Expression 1')");
10 | });
11 |
12 | it("createExpression: should create a new record", (done) => {
13 | let data = {
14 | intent_id: 1,
15 | expression_name: "Expression 2"
16 | }
17 | chai.request(app)
18 | .post('/api/v2/expressions')
19 | .send(data)
20 | .end((err, res) => {
21 | res.should.have.status(200);
22 | res.body.should.be.a('object');
23 | res.body.should.have.property('status').eql('success');
24 | done();
25 | });
26 | });
27 |
28 | it("getIntentExpressions: should get all records", (done) => {
29 | chai.request(app)
30 | .get('/api/v2/intents/1/expressions')
31 | .end((err, res) => {
32 | res.should.have.status(200);
33 | res.body.should.be.a('array');
34 | done();
35 | });
36 | });
37 |
38 | it("getIntentExpressionQuery: should get all records", (done) => {
39 | chai.request(app)
40 | .get('/api/v2/intent_expressions?intent_ids=1,2,3')
41 | .end((err, res) => {
42 | res.should.have.status(200);
43 | res.body.should.be.a('array');
44 | done();
45 | });
46 | });
47 |
48 | it("getSingleExpression: should get a single record", (done) => {
49 | chai.request(app)
50 | .get('/api/v2/expressions/1')
51 | .end((err, res) => {
52 | res.should.have.status(200);
53 | res.body.should.be.a('object');
54 | res.body.should.have.property('expression_id').eql(1);
55 | done();
56 | });
57 | });
58 |
59 | it("updateExpression: should update a record", (done) => {
60 | let data = {
61 | expression_text: "Expression 2 Updated"
62 | }
63 | chai.request(app)
64 | .put('/api/v2/expressions/2')
65 | .send(data)
66 | .end((err, res) => {
67 | res.should.have.status(200);
68 | res.body.should.be.a('object');
69 | res.body.should.have.property('status').eql('success');
70 | done();
71 | });
72 | });
73 |
74 | it("removeExpression: should delete a record", (done) => {
75 | chai.request(app)
76 | .delete('/api/v2/expressions/2')
77 | .end((err, res) => {
78 | res.should.have.status(200);
79 | res.body.should.be.a('object');
80 | res.body.should.have.property('status').eql('success');
81 | done();
82 | });
83 | });
84 | });
85 | });
--------------------------------------------------------------------------------
/server/test/tests/intents.test.js:
--------------------------------------------------------------------------------
1 | var common = require("../common");
2 | var chai = common.chai;
3 | var app = common.app;
4 | var db = common.db;
5 |
6 | describe("intents.test", () => {
7 | describe("GET /api/v2/intents/", () => {
8 | before(function () {
9 | db.run("INSERT into intents values (1, 'Intent 1', 1)");
10 | });
11 |
12 | it("createBotIntent: should create a new record", (done) => {
13 | let data = {
14 | bot_id: 1,
15 | intent_name: "Intent 2"
16 | }
17 | chai.request(app)
18 | .post('/api/v2/intents')
19 | .send(data)
20 | .end((err, res) => {
21 | res.should.have.status(200);
22 | res.body.should.be.a('object');
23 | res.body.should.have.property('status').eql('success');
24 | done();
25 | });
26 | });
27 |
28 | it("getBotIntents: should get all records", (done) => {
29 | chai.request(app)
30 | .get('/api/v2/bots/1/intents')
31 | .end((err, res) => {
32 | res.should.have.status(200);
33 | res.body.should.be.a('array');
34 | done();
35 | });
36 | });
37 |
38 | it("getSingleIntent: should get a single record", (done) => {
39 | chai.request(app)
40 | .get('/api/v2/intents/1')
41 | .end((err, res) => {
42 | res.should.have.status(200);
43 | res.body.should.be.a('object');
44 | res.body.should.have.property('intent_id').eql(1);
45 | done();
46 | });
47 | });
48 |
49 | it("updateIntent: should update a record", (done) => {
50 | let data = {
51 | intent_name: "Intent 2 Updated"
52 | }
53 | chai.request(app)
54 | .put('/api/v2/intents/2')
55 | .send(data)
56 | .end((err, res) => {
57 | res.should.have.status(200);
58 | res.body.should.be.a('object');
59 | res.body.should.have.property('status').eql('success');
60 | done();
61 | });
62 | });
63 |
64 | it("removeIntent: should delete a record", (done) => {
65 | chai.request(app)
66 | .delete('/api/v2/intents/2')
67 | .end((err, res) => {
68 | res.should.have.status(200);
69 | res.body.should.be.a('object');
70 | res.body.should.have.property('status').eql('success');
71 | done();
72 | });
73 | });
74 | });
75 | });
--------------------------------------------------------------------------------
/server/test/tests/models.test.js:
--------------------------------------------------------------------------------
1 | var common = require("../common");
2 | var chai = common.chai;
3 | var app = common.app;
4 | var db = common.db;
5 |
6 | describe("models.test", () => {
7 | describe("GET /api/v2/models/", () => {
8 | before(function () {
9 | //model_name, comment, bot_id, server_path, local_path
10 | db.run("INSERT into models (model_id, model_name, comment, bot_id, server_path, local_path) values (1, 'Model 1', 'comment', 1, '/server/path', '/local/path')");
11 | });
12 |
13 | it("createModel: should create a new record", (done) => {
14 | let data = {
15 | bot_id: 1,
16 | model_name: "Model 2",
17 | comment: "Comment",
18 | server_path: "/server/path",
19 | file_name: "filename"
20 | }
21 | chai.request(app)
22 | .post('/api/v2/models')
23 | .send(data)
24 | .end((err, res) => {
25 | res.should.have.status(200);
26 | res.body.should.be.a('object');
27 | res.body.should.have.property('status').eql('success');
28 | done();
29 | });
30 | });
31 |
32 | it("getBotModels: should get all records", (done) => {
33 | chai.request(app)
34 | .get('/api/v2/models/1')
35 | .end((err, res) => {
36 | res.should.have.status(200);
37 | res.body.should.be.a('array');
38 | done();
39 | });
40 | });
41 |
42 | it("removeAction: should delete a record", (done) => {
43 | chai.request(app)
44 | .delete('/api/v2/models?model_id=2')
45 | .end((err, res) => {
46 | res.should.have.status(200);
47 | res.body.should.be.a('object');
48 | res.body.should.have.property('status').eql('success');
49 | done();
50 | });
51 | });
52 | });
53 | });
--------------------------------------------------------------------------------
/server/test/tests/parameters.test.js:
--------------------------------------------------------------------------------
1 | var common = require("../common");
2 | var chai = common.chai;
3 | var app = common.app;
4 | var db = common.db;
5 |
6 | describe("parameters.test", () => {
7 | describe("GET /api/v2/parameters/", () => {
8 | before(function () {
9 | db.run("insert into expression_parameters(expression_id, parameter_start, parameter_end, parameter_value, intent_id) values (1, 2, 3, 'test', 1)");
10 | });
11 |
12 | it("createParameter: should create a new record", (done) => {
13 | let data = {
14 | expression_id: 1,
15 | parameter_start: 3,
16 | parameter_end: 5,
17 | parameter_value: "Values",
18 | intent_id: 1
19 | }
20 | chai.request(app)
21 | .post('/api/v2/parameters')
22 | .send(data)
23 | .end((err, res) => {
24 | res.should.have.status(200);
25 | res.body.should.be.a('object');
26 | res.body.should.have.property('status').eql('success');
27 | done();
28 | });
29 | });
30 |
31 | it("getIntentParameters: should get all records", (done) => {
32 | chai.request(app)
33 | .get('/api/v2/intent/1/parameters')
34 | .end((err, res) => {
35 | res.should.have.status(200);
36 | res.body.should.be.a('array');
37 | done();
38 | });
39 | });
40 |
41 | it("getExpressionParametersQuery: should get all records", (done) => {
42 | chai.request(app)
43 | .get('/api/v2/expression_parameters?expression_ids=1,2')
44 | .end((err, res) => {
45 | res.should.have.status(200);
46 | res.body.should.be.a('array');
47 | done();
48 | });
49 | });
50 |
51 | it("getExpressionParameters: should get all records", (done) => {
52 | chai.request(app)
53 | .get('/api/v2/expresions/1/parameters')
54 | .end((err, res) => {
55 | res.should.have.status(200);
56 | res.body.should.be.a('array');
57 | done();
58 | });
59 | });
60 |
61 | it("updateParameter: should update a record", (done) => {
62 | let data = {
63 | entity_id: 1,
64 | parameter_id: 1
65 | }
66 | chai.request(app)
67 | .put('/api/v2/parameters/1')
68 | .send(data)
69 | .end((err, res) => {
70 | res.should.have.status(200);
71 | res.body.should.be.a('object');
72 | res.body.should.have.property('status').eql('success');
73 | done();
74 | });
75 | });
76 |
77 | it("removeExpressionParameter: should delete a record", (done) => {
78 | chai.request(app)
79 | .delete('/api/v2/parameters/2')
80 | .end((err, res) => {
81 | res.should.have.status(200);
82 | res.body.should.be.a('object');
83 | res.body.should.have.property('status').eql('success');
84 | done();
85 | });
86 | });
87 | });
88 | });
--------------------------------------------------------------------------------
/server/test/tests/regex.test.js:
--------------------------------------------------------------------------------
1 | var common = require("../common");
2 | var chai = common.chai;
3 | var app = common.app;
4 | var db = common.db;
5 |
6 | describe("regex.test", () => {
7 | describe("GET /api/v2/regex/", () => {
8 | before(function () {
9 | db.run("INSERT into regex values (1, 'Regex 1', '*.*', 1)");
10 | });
11 |
12 | it("createRegex: should create a new record", (done) => {
13 | let data = {
14 | bot_id: 1,
15 | regex_name: "Regex 2",
16 | regex_pattern: "*.?*"
17 | }
18 | chai.request(app)
19 | .post('/api/v2/regex')
20 | .send(data)
21 | .end((err, res) => {
22 | res.should.have.status(200);
23 | res.body.should.be.a('object');
24 | res.body.should.have.property('status').eql('success');
25 | done();
26 | });
27 | });
28 |
29 | it("getBotRegex: should get all records", (done) => {
30 | chai.request(app)
31 | .get('/api/v2/bot/1/regex')
32 | .end((err, res) => {
33 | res.should.have.status(200);
34 | res.body.should.be.a('array');
35 | done();
36 | });
37 | });
38 |
39 | it("getSingleRegex: should get a single record", (done) => {
40 | chai.request(app)
41 | .get('/api/v2/regex/1')
42 | .end((err, res) => {
43 | res.should.have.status(200);
44 | res.body.should.be.a('object');
45 | res.body.should.have.property('regex_id').eql(1);
46 | done();
47 | });
48 | });
49 |
50 | it("updateRegex: should update a record", (done) => {
51 | let data = {
52 | regex_name: "Regex 2 Updated"
53 | }
54 | chai.request(app)
55 | .put('/api/v2/regex/2')
56 | .send(data)
57 | .end((err, res) => {
58 | res.should.have.status(200);
59 | res.body.should.be.a('object');
60 | res.body.should.have.property('status').eql('success');
61 | done();
62 | });
63 | });
64 |
65 | it("removeIntent: should delete a record", (done) => {
66 | chai.request(app)
67 | .delete('/api/v2/regex/2')
68 | .end((err, res) => {
69 | res.should.have.status(200);
70 | res.body.should.be.a('object');
71 | res.body.should.have.property('status').eql('success');
72 | done();
73 | });
74 | });
75 | });
76 | });
--------------------------------------------------------------------------------
/server/test/tests/responses.test.js:
--------------------------------------------------------------------------------
1 | var common = require("../common");
2 | var chai = common.chai;
3 | var app = common.app;
4 | var db = common.db;
5 |
6 | describe("responses.test", () => {
7 | describe("GET /api/v2/responses/", () => {
8 | before(function () {
9 | db.run("INSERT into responses values (1, 'Response 1', 1, 'TEXT')");
10 | });
11 |
12 | it("createResponse: should create a new record", (done) => {
13 | let data = {
14 | action_id: 1,
15 | response_text: "Response 2",
16 | response_type: "TEXT"
17 | }
18 | chai.request(app)
19 | .post('/api/v2/response')
20 | .send(data)
21 | .end((err, res) => {
22 | res.should.have.status(200);
23 | res.body.should.be.a('object');
24 | res.body.should.have.property('status').eql('success');
25 | done();
26 | });
27 | });
28 |
29 | it("updateResponse: should update a record", (done) => {
30 | let data = {
31 | response_id: 2,
32 | response_name: "Response 2 Updated",
33 | response_type: "TEXT"
34 | }
35 | chai.request(app)
36 | .put('/api/v2/response')
37 | .send(data)
38 | .end((err, res) => {
39 | res.should.have.status(200);
40 | res.body.should.be.a('object');
41 | res.body.should.have.property('status').eql('success');
42 | done();
43 | });
44 | });
45 |
46 |
47 | it("removeResponse: should delete a record", (done) => {
48 | chai.request(app)
49 | .delete('/api/v2/response')
50 | .end((err, res) => {
51 | res.should.have.status(200);
52 | res.body.should.be.a('object');
53 | res.body.should.have.property('status').eql('success');
54 | done();
55 | });
56 | });
57 | });
58 | });
--------------------------------------------------------------------------------
/server/test/tests/settings.test.js:
--------------------------------------------------------------------------------
1 | var common = require("../common");
2 | var chai = common.chai;
3 | var app = common.app;
4 | var db = common.db;
5 |
6 | describe("settings.test", () => {
7 | describe("GET /api/v2/settings/", () => {
8 |
9 | it("getSettings: should get all records", (done) => {
10 | chai.request(app)
11 | .get('/api/v2/settings')
12 | .end((err, res) => {
13 | res.should.have.status(200);
14 | res.body.should.be.a('array');
15 | done();
16 | });
17 | });
18 |
19 | it("getSetting: should get one records", (done) => {
20 | chai.request(app)
21 | .get('/api/v2/settings/refresh_time')
22 | .end((err, res) => {
23 | console.log("body: " + res.body);
24 | res.should.have.status(200);
25 | res.body.should.be.a('object');
26 | done();
27 | });
28 | });
29 |
30 | it("updateSetting: should update a record", (done) => {
31 | let data = {
32 | setting_value: "60000",
33 | setting_name: "refresh_time"
34 | }
35 | chai.request(app)
36 | .put('/api/v2/settings/refresh_time')
37 | .send(data)
38 | .end((err, res) => {
39 | res.should.have.status(200);
40 | res.body.should.be.a('object');
41 | res.body.should.have.property('status').eql('success');
42 | done();
43 | });
44 | });
45 | });
46 | });
--------------------------------------------------------------------------------
/server/test/tests/stories.test.js:
--------------------------------------------------------------------------------
1 | var common = require("../common");
2 | var chai = common.chai;
3 | var app = common.app;
4 | var db = common.db;
5 |
6 | describe("stories.test", () => {
7 | describe("GET /api/v2/stories/", () => {
8 | before(function () {
9 | db.run("INSERT into stories (story_id, story_name, story, bot_id) values (1, 'Story 1', 'story text', 1)");
10 | });
11 |
12 | it("createStory: should create a new record", (done) => {
13 | let data = {
14 | story_name: "Story 2",
15 | story: "story",
16 | bot_id: 1
17 | }
18 | chai.request(app)
19 | .post('/api/v2/stories')
20 | .send(data)
21 | .end((err, res) => {
22 | res.should.have.status(200);
23 | res.body.should.be.a('object');
24 | res.body.should.have.property('status').eql('success');
25 | done();
26 | });
27 | });
28 |
29 | it("searchStoryAttributes: search all records", (done) => {
30 | chai.request(app)
31 | .get('/api/v2/stories/1/search?search_text=story')
32 | .end((err, res) => {
33 | res.should.have.status(200);
34 | res.body.should.be.a('array');
35 | done();
36 | });
37 | });
38 |
39 | it("getAllBotStories: should get all records", (done) => {
40 | chai.request(app)
41 | .get('/api/v2/stories/1')
42 | .end((err, res) => {
43 | res.should.have.status(200);
44 | res.body.should.be.a('array');
45 | done();
46 | });
47 | });
48 |
49 | it("updateStory: should update a record", (done) => {
50 | let data = {
51 | story: "Story 2 Updated",
52 | story_id: 2
53 | }
54 | chai.request(app)
55 | .put('/api/v2/stories')
56 | .send(data)
57 | .end((err, res) => {
58 | res.should.have.status(200);
59 | res.body.should.be.a('object');
60 | res.body.should.have.property('status').eql('success');
61 | done();
62 | });
63 | });
64 |
65 | it("removSeStory: should delete a record", (done) => {
66 | chai.request(app)
67 | .delete('/api/v2/stories?story_id=2')
68 | .end((err, res) => {
69 | res.should.have.status(200);
70 | res.body.should.be.a('object');
71 | res.body.should.have.property('status').eql('success');
72 | done();
73 | });
74 | });
75 | });
76 | });
--------------------------------------------------------------------------------
/server/test/tests/synonyms.test.js:
--------------------------------------------------------------------------------
1 | var common = require("../common");
2 | var chai = common.chai;
3 | var app = common.app;
4 | var db = common.db;
5 |
6 | describe("synonyms.test", () => {
7 | describe("GET /api/v2/synonyms/", () => {
8 | before(function () {
9 | db.run("INSERT into synonyms (bot_id, synonym_reference, regex_pattern) values (1, 'NYC', '*.*')");
10 | });
11 | //req.body.bot_id, req.body.synonym_reference, req.body.regex_pattern
12 | it("createBotSynonym: should create a new record", (done) => {
13 | let bot = {
14 | bot_id: 1,
15 | synonym_reference: "NYC",
16 | regex_pattern: "*.?"
17 | }
18 | chai.request(app)
19 | .post('/api/v2/synonyms')
20 | .send(bot)
21 | .end((err, res) => {
22 | res.should.have.status(200);
23 | res.body.should.be.a('object');
24 | res.body.should.have.property('status').eql('success');
25 | done();
26 | });
27 | });
28 |
29 | it("getBotSynonyms: should get all bot records", (done) => {
30 | chai.request(app)
31 | .get('/api/v2/bot/1/synonyms')
32 | .end((err, res) => {
33 | res.should.have.status(200);
34 | res.body.should.be.a('array');
35 | done();
36 | });
37 | });
38 |
39 | it("getSingleSynonym: should get a record", (done) => {
40 | chai.request(app)
41 | .get('/api/v2/synonyms/1')
42 | .end((err, res) => {
43 | res.should.have.status(200);
44 | res.body.should.be.a('object');
45 | res.body.should.have.property('synonym_id').eql(1);
46 | done();
47 | });
48 | });
49 |
50 | it("removeSynonym: should delete a record", (done) => {
51 | chai.request(app)
52 | .delete('/api/v2/synonyms/2')
53 | .end((err, res) => {
54 | res.should.have.status(200);
55 | res.body.should.be.a('object');
56 | res.body.should.have.property('status').eql('success');
57 | done();
58 | });
59 | });
60 | });
61 | });
--------------------------------------------------------------------------------
/server/test/tests/variants.test.js:
--------------------------------------------------------------------------------
1 | var common = require("../common");
2 | var chai = common.chai;
3 | var app = common.app;
4 | var db = common.db;
5 |
6 | describe("variants.test", () => {
7 | describe("GET /api/v2/variants/", () => {
8 | before(function () {
9 | db.run("INSERT into synonym_variants values (1, 'Big Apple', 1)");
10 | });
11 |
12 | it("createVariant: should create a new record", (done) => {
13 | let data = {
14 | synonym_id: 1,
15 | synonym_value: "New York City"
16 | }
17 | chai.request(app)
18 | .post('/api/v2/variants')
19 | .send(data)
20 | .end((err, res) => {
21 | res.should.have.status(200);
22 | res.body.should.be.a('object');
23 | res.body.should.have.property('status').eql('success');
24 | done();
25 | });
26 | });
27 |
28 | it("getSingleVariant: should get a single record", (done) => {
29 | chai.request(app)
30 | .get('/api/v2/variants/1')
31 | .end((err, res) => {
32 | res.should.have.status(200);
33 | res.body.should.be.a('object');
34 | res.body.should.have.property('synonym_variant_id').eql(1);
35 | done();
36 | });
37 | });
38 |
39 | it("getSynonymsVariants: should get all records", (done) => {
40 | chai.request(app)
41 | .get('/api/v2/synonyms_variants/1,2')
42 | .end((err, res) => {
43 | res.should.have.status(200);
44 | res.body.should.be.a('array');
45 | done();
46 | });
47 | });
48 |
49 | it("getSynonymVariants: should get all records", (done) => {
50 | chai.request(app)
51 | .get('/api/v2/synonyms/1/variants')
52 | .end((err, res) => {
53 | res.should.have.status(200);
54 | res.body.should.be.a('array');
55 | done();
56 | });
57 | });
58 |
59 | it("removeVariant: should delete a record", (done) => {
60 | chai.request(app)
61 | .delete('/api/v2/variants/2')
62 | .end((err, res) => {
63 | res.should.have.status(200);
64 | res.body.should.be.a('object');
65 | res.body.should.have.property('status').eql('success');
66 | done();
67 | });
68 | });
69 |
70 | it("removeSynonymVariants: should delete a record", (done) => {
71 | chai.request(app)
72 | .delete('/api/v2//synonyms/2/variants')
73 | .end((err, res) => {
74 | res.should.have.status(200);
75 | res.body.should.be.a('object');
76 | res.body.should.have.property('status').eql('success');
77 | done();
78 | });
79 | });
80 |
81 |
82 | });
83 | });
--------------------------------------------------------------------------------
/server/util/logger.js:
--------------------------------------------------------------------------------
1 | const winston = require('winston');
2 |
3 | class Logger {
4 | constructor(appliName) {
5 | this.appliName = appliName || 'rasa-ui';
6 |
7 | this.logFormat = winston.format.printf(info => {
8 | const formattedDate = info.timestamp.replace('T', ' ').replace('Z', '');
9 | return `${formattedDate}|${this.appliName}|${info.level}|${
10 | info.message
11 | };`;
12 | });
13 |
14 | this.winston = winston.createLogger({
15 | level: global.loglevel || 'info',
16 | format: winston.format.combine(
17 | winston.format.timestamp(),
18 | this.logFormat
19 | ),
20 | transports: [new winston.transports.Console({})]
21 | });
22 | }
23 | }
24 |
25 | const logger = new Logger();
26 |
27 | module.exports = logger;
28 |
--------------------------------------------------------------------------------
/web/src/app/app.js:
--------------------------------------------------------------------------------
1 | var app = angular
2 | .module("app", ["ngCookies", "ngSanitize", "ngFileUpload", "angularUtils.directives.dirPagination", "ngRoute", "chart.js", "ngResource", "ngTagsInput", "jsonFormatter", "angularModalService", "ngStorage"])
3 | .run(function ($rootScope, $http, $sessionStorage, appConfig) {
4 |
5 | // keep user logged in after page refresh
6 | if ($sessionStorage.jwt) {
7 | $rootScope.authenticated = true;
8 | $http.defaults.headers.common.Authorization = "Bearer " + $sessionStorage.jwt;
9 | } else {
10 | //show login page
11 | $rootScope.authenticated = false;
12 | $rootScope.$broadcast("INVALID_JWT_TOKEN");
13 | }
14 |
15 | $rootScope.$on("USER_AUTHENTICATED", function (event) {
16 | $rootScope.authenticated = true;
17 | $http.defaults.headers.common.Authorization =
18 | "Bearer " + $sessionStorage.jwt;
19 | });
20 |
21 | $rootScope.$on("INVALID_JWT_TOKEN", function (event) {
22 | $rootScope.authenticated = false;
23 | $sessionStorage.$reset();
24 | });
25 | });
26 |
27 | angular
28 | .module("app")
29 | .controller("appCtrl", function ($rootScope, $scope, $route, $routeParams, $location, $timeout, $http, $sessionStorage, $cookies, appConfig, Auth, Settings, Rasa_Status, $interval, Rasa_Version) {
30 | $scope.$route = $route;
31 | $scope.$location = $location;
32 | $scope.$routeParams = $routeParams;
33 |
34 | $scope.go = function (path) {
35 | $location.path(path);
36 | };
37 |
38 | executeRefreshSettings();
39 |
40 | $scope.formData = {};
41 |
42 | $scope.$on("setAlertText", function (event, alert_text) {
43 | $("#alertTextDiv").addClass("show");
44 | $scope.alert_text = alert_text;
45 | $timeout(function () {
46 | $("#alertTextDiv").removeClass("show");
47 | }, 2000);
48 | });
49 |
50 | $scope.loginUser = function (user) {
51 | Auth.save(JSON.stringify(user)).$promise.then(function (response) {
52 | $sessionStorage.jwt = response.token;
53 | $cookies.put("loggedinjwt", $sessionStorage.jwt);
54 | $rootScope.$broadcast("USER_AUTHENTICATED");
55 | });
56 | }
57 |
58 | $scope.cleanResponse = function (data) {
59 | return JSON.parse(angular.toJson(data));
60 | }
61 |
62 | $scope.objectFindByKey = function (array, key, value) {
63 | for (let i = 0; i < array.length; i++) {
64 | if (array[i][key] === value) {
65 | return array[i];
66 | }
67 | }
68 | return null;
69 | }
70 |
71 | $scope.$on('refreshIntervelUpdate', function (event, expression_text) {
72 | $interval.cancel(configcheck);
73 | executeRefreshSettings();
74 | });
75 |
76 | function executeRefreshSettings() {
77 | Settings.query(function (data) {
78 | $rootScope.settings = data;
79 | for (let key in data) {
80 | $rootScope.settings[data[key]['setting_name']] = data[key]['setting_value'];
81 | }
82 | if ($rootScope.settings['refresh_time'] !== '-1' && $rootScope.settings['refresh_time'] !== undefined) {
83 | configcheck = $interval(getRasaStatus, Number($rootScope.settings['refresh_time']));
84 | }
85 | getRasaStatus();
86 | });
87 | }
88 |
89 | $scope.$on('$destroy', function () {
90 | $interval.cancel(configcheck);
91 | });
92 |
93 | function getRasaStatus() {
94 | Rasa_Status.get(function (statusdata) {
95 | $rootScope.config = statusdata.toJSON();
96 | $rootScope.config.isonline = 1;
97 |
98 | Rasa_Version.get(function (version_data) {
99 | $rootScope.config.version_data = version_data.toJSON();
100 | });
101 | }, function (error) {
102 | $rootScope.config.isonline = 0;
103 | });
104 | }
105 |
106 | $scope.timeConverter = function(UNIX_timestamp) {
107 | var a = new Date(UNIX_timestamp * 1000);
108 | var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
109 | var year = a.getFullYear();
110 | var month = months[a.getMonth()];
111 | var date = a.getDate();
112 | var hour = a.getHours();
113 | var min = a.getMinutes();
114 | var sec = a.getSeconds();
115 | var time = date + ' ' + month + ' ' + year + ' ' + hour + ':' + min + ':' + sec;
116 | return time;
117 | }
118 |
119 | $scope.pastelColors = function() {
120 | const hue = Math.floor(Math.random() * 360);
121 | return 'hsl(' + hue + ', 100%, 87.5%)';
122 | }
123 |
124 | if (!String.prototype.splice) {
125 | /**
126 | * {JSDoc}
127 | *
128 | * The splice() method changes the content of a string by removing a range of
129 | * characters and/or adding new characters.
130 | *
131 | * @this {String}
132 | * @param {number} start Index at which to start changing the string.
133 | * @param {number} delCount An integer indicating the number of old chars to remove.
134 | * @param {string} newSubStr The String that is spliced in.
135 | * @return {string} A new string with the spliced substring.
136 | */
137 | String.prototype.splice = function(start, delCount, newSubStr) {
138 | return this.slice(0, start) + newSubStr + this.slice(start + Math.abs(delCount));
139 | };
140 | }
141 |
142 |
143 |
144 |
145 | });
--------------------------------------------------------------------------------
/web/src/app/components/bots/add_bot.html:
--------------------------------------------------------------------------------
1 |
2 | - Bots
3 | - Add Bot
4 |
5 |
6 |
--------------------------------------------------------------------------------
/web/src/app/components/bots/add_bot.js:
--------------------------------------------------------------------------------
1 | angular
2 | .module('app')
3 | .controller('AddBotController', AddBotController)
4 |
5 | function AddBotController($scope, Bot) {
6 | $scope.addBot = function(params) {
7 | Bot.save(this.formData).$promise.then(function() {
8 | $scope.formData.bot_name = "";
9 | $scope.go('/bots')
10 | });
11 | };
12 | }
13 |
--------------------------------------------------------------------------------
/web/src/app/components/bots/bots.html:
--------------------------------------------------------------------------------
1 |
2 | - Bots
3 |
4 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/web/src/app/components/bots/bots.js:
--------------------------------------------------------------------------------
1 | angular
2 | .module('app')
3 | .controller('BotsController', BotsController);
4 |
5 | function BotsController($scope, $rootScope, Bot,$http,appConfig,$window) {
6 | Bot.query(function(data) {
7 | $scope.botList = data;
8 | });
9 | }
10 |
--------------------------------------------------------------------------------
/web/src/app/components/bots/edit_bot.js:
--------------------------------------------------------------------------------
1 | angular.module('app').controller('EditBotController', EditBotController);
2 |
3 | function EditBotController($scope, Bot, Intents, BotEntities, Actions, BotSynonyms, BotRegex, $rootScope) {
4 | Bot.get({ bot_id: $scope.$routeParams.bot_id }, function(data) {
5 | $scope.bot = data;
6 | /* Core feature
7 | $scope.storiesList = [];
8 | parseStories(data.story_details);
9 | */
10 | });
11 |
12 | Intents.query({ bot_id: $scope.$routeParams.bot_id }, function(data) {
13 | $scope.intentList = data;
14 | });
15 |
16 | BotSynonyms.query({ bot_id: $scope.$routeParams.bot_id }, function(data) {
17 | $scope.synonymsList = data;
18 | });
19 |
20 | BotRegex.query({ bot_id: $scope.$routeParams.bot_id }, function(data) {
21 | $scope.regexList = data;
22 | });
23 |
24 | BotEntities.query({ bot_id: $scope.$routeParams.bot_id }, function(data) {
25 | $scope.entitiesList = data;
26 | });
27 |
28 | $scope.editBotInfo = function(bot) {
29 | Bot.update({ bot_id: bot.bot_id }, bot).$promise.then(function() {
30 | $rootScope.$broadcast('setAlertText', "Bot information updated Sucessfully!!");
31 | });
32 | };
33 |
34 | function parseStories(story_details) {
35 | if (angular.isUndefined(story_details) || story_details === null) return;
36 | const lines = story_details.split('\n');
37 |
38 | for (let i = 0; i < lines.length; i++) {
39 | const currentLine = lines[i];
40 | if (currentLine.startsWith('##')) {
41 | $scope.storiesList.push(currentLine.substring(2, currentLine.length));
42 | }
43 | }
44 | }
45 |
46 | $scope.deleteBot = function() {
47 | Bot.remove({ bot_id: $scope.$routeParams.bot_id }).$promise.then(
48 | function() {
49 | $scope.go('/bots');
50 | }
51 | );
52 | };
53 | }
54 |
--------------------------------------------------------------------------------
/web/src/app/components/bots/import_bot.html:
--------------------------------------------------------------------------------
1 |
2 | - Bots
3 | - Import Bot
4 |
5 |
6 |
7 |
8 |
9 |
10 |
34 |
35 |
38 |
39 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/web/src/app/components/bots/import_bot.js:
--------------------------------------------------------------------------------
1 | /* TODO: Import feature */
2 |
3 | angular
4 | .module('app')
5 | .controller('ImportBotController', ImportBotController);
6 |
7 | function ImportBotController($scope, $rootScope, Bot, $route, $location) {
8 | $scope.show_preview = false;
9 | $scope.fileInvalid = true;
10 | $scope.show_progress = false;
11 |
12 | $scope.importBot = function() {
13 | let postRequest = {
14 | bot_name: $scope.formData.bot_name,
15 | data: $scope.botImportData
16 | };
17 | Bot.save({ bot_id: 'upload' }, postRequest).$promise.then(function() {
18 | $rootScope.$broadcast('setAlertText', 'Bot uploaded successfully');
19 | if ($location.path().endsWith('bots')) {
20 | $route.reload();
21 | }
22 | });
23 | $rootScope.$broadcast(
24 | 'setAlertText',
25 | 'Bot upload in progress.. Notification will be sent when done!!'
26 | );
27 | $scope.formData.bot_name = '';
28 | $scope.go('/bots');
29 | };
30 |
31 | $scope.validateAndPreviewBot = function(file) {
32 | $scope.filesize = file.size + ' bytes';
33 | $scope.show_preview = true;
34 | $scope.show_progress = true;
35 | $scope.botImportData = 'Loading ...';
36 | let reader = new FileReader();
37 | reader.onload = function() {
38 | $scope.show_progress = false;
39 | try {
40 | $scope.botImportData = JSON.parse(reader.result);
41 | $scope.fileInvalid = false;
42 | } catch (e) {
43 | $scope.botImportData = 'Invalid JSON';
44 | return false;
45 | }
46 | };
47 | reader.onerror = function() {
48 | $scope.botImportData = 'Error Occurred while uploading the file';
49 | };
50 | reader.readAsText(file);
51 | };
52 | }
53 |
--------------------------------------------------------------------------------
/web/src/app/components/dashboard/dashboard.html:
--------------------------------------------------------------------------------
1 |
2 | -
3 | Dashboard
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
{{ request_processed }}
20 |
Requests Processed
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
{{ total_log_entries }}
35 |
Total Log Entries
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
{{ trained_at }}
50 |
Model: {{ model_file }}
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
63 |
64 |
65 |
66 |
Usage
67 |
Last 30 days
68 |
69 |
70 |
71 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
{{ config.version_data.version }}
91 |
Rasa Version
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
{{ settings[1].ui_version }}
107 |
UI DB Version
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
--------------------------------------------------------------------------------
/web/src/app/components/dashboard/dashboard.js:
--------------------------------------------------------------------------------
1 | angular.module('app').controller('DashboardController', DashboardController);
2 |
3 | function DashboardController($scope, $http, Rasa_Status, NLU_log_stats, appConfig) {
4 | getRasaStatus();
5 | getTotalLogEntries();
6 | getRequestUsageTotalStatus();
7 |
8 | function getRequestUsageTotalStatus() {
9 | NLU_log_stats.get({ path: 'request_usage_total' }, function(data) {
10 | $scope.request_processed = data.total_request_usage;
11 | });
12 | }
13 |
14 | function getTotalLogEntries() {
15 | NLU_log_stats.get({ path: 'total_log_entries' }, function(data) {
16 | $scope.total_log_entries = data.total_log_entries;
17 | });
18 | }
19 |
20 | function getRasaStatus() {
21 | Rasa_Status.get(function(data) {
22 | if (data.model_file != undefined) {
23 | $scope.model_file = data.model_file;
24 | } else {
25 | $scope.model_file = "No model Loaded";
26 | $scope.trained_at = "Unavailable";
27 | }
28 | if (data.fingerprint != undefined) {
29 | $scope.trained_at = $scope.timeConverter(data.fingerprint.trained_at);
30 | } else {
31 | $scope.model_file = "No model loaded";
32 | $scope.trained_at = "Unavailable";
33 | }
34 | });
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/web/src/app/components/dashboard/widgets.js:
--------------------------------------------------------------------------------
1 | // Default colors
2 | const brandPrimary = '#20a8d8';
3 | const brandSuccess = '#4dbd74';
4 | const brandInfo = '#63c2de';
5 | const brandWarning = '#f8cb00';
6 | const brandDanger = '#f86c6b';
7 |
8 | const grayDark = '#2a2c36';
9 | const gray = '#55595c';
10 | const grayLight = '#818a91';
11 | const grayLighter = '#d1d4d7';
12 | const grayLightest = '#f8f9fa';
13 |
14 | angular
15 | .module('app')
16 | .controller('cardChartCtrl1', cardChartCtrl1)
17 | .controller('cardChartCtrl2', cardChartCtrl2)
18 | .controller('cardChartCtrl2', cardChartCtrl2)
19 | .controller('usageChartCtrl', usageChartCtrl);
20 |
21 | //convert Hex to RGBA
22 | function convertHex(hex, opacity) {
23 | hex = hex.replace('#', '');
24 | const r = parseInt(hex.substring(0, 2), 16);
25 | const g = parseInt(hex.substring(2, 4), 16);
26 | const b = parseInt(hex.substring(4, 6), 16);
27 |
28 | const result = 'rgba(' + r + ',' + g + ',' + b + ',' + opacity / 100 + ')';
29 | return result;
30 | }
31 |
32 | function random(min, max) {
33 | return Math.floor(Math.random() * (max - min + 1) + min);
34 | }
35 |
36 | function usageChartCtrl($scope, NLU_log, NLU_log_stats) {
37 | NLU_log_stats.query({ path: 'intent_usage_by_day' }, function(data) {
38 | const elements = data.length;
39 | const data1 = [];
40 | const labels = [];
41 |
42 | for (let i = 0; i <= elements - 1; i++) {
43 | labels.push(data[i].day);
44 | data1.push(data[i].cnt);
45 | }
46 |
47 | $scope.labels = labels;
48 | $scope.series = ['Processed'];
49 | $scope.data = [data1];
50 | $scope.colors = [
51 | {
52 | backgroundColor: convertHex(brandInfo, 10),
53 | borderColor: brandInfo,
54 | pointHoverBackgroundColor: '#fff'}
55 | ];
56 | $scope.options = {
57 | responsive: true,
58 | maintainAspectRatio: false,
59 | scales: {
60 | xAxes: [
61 | {
62 | gridLines: {
63 | drawOnChartArea: false
64 | },
65 | ticks: {
66 | callback: function(value) {
67 | return value;
68 | }}
69 | }
70 | ],
71 | yAxes: [
72 | {
73 | ticks: {
74 | beginAtZero: true,
75 | maxTicksLimit: 5,
76 | stepSize: Math.ceil(
77 | (Math.max.apply(Math, data1) +
78 | Math.max.apply(Math, data1) / 10) /
79 | 5
80 | ),
81 | max: Math.ceil(
82 | Math.max.apply(Math, data1) + Math.max.apply(Math, data1) / 10
83 | )
84 | }
85 | }
86 | ]
87 | },
88 | elements: {
89 | point: {
90 | radius: 0,
91 | hitRadius: 10,
92 | hoverRadius: 4,
93 | hoverBorderWidth: 3}
94 | }
95 | };
96 | });
97 | }
98 |
99 | function cardChartCtrl1($scope) {
100 | $scope.onlineusers = 1110;
101 |
102 | $scope.labels = [
103 | 'January',
104 | 'February',
105 | 'March',
106 | 'April',
107 | 'May',
108 | 'June',
109 | 'July'
110 | ];
111 | $scope.data = [[65, 59, 84, 84, 51, 55, 40]];
112 | $scope.colors = [
113 | {
114 | backgroundColor: brandPrimary,
115 | borderColor: 'rgba(255,255,255,.55)'
116 | }
117 | ];
118 | $scope.options = {
119 | maintainAspectRatio: false,
120 | scales: {
121 | xAxes: [
122 | {
123 | gridLines: {
124 | color: 'transparent',
125 | zeroLineColor: 'transparent'},
126 | ticks: {
127 | fontSize: 2,
128 | fontColor: 'transparent'}
129 | }
130 | ],
131 | yAxes: [
132 | {
133 | display: false,
134 | ticks: {
135 | display: false,
136 | min: Math.min.apply(Math, $scope.data[0]) - 5,
137 | max: Math.max.apply(Math, $scope.data[0]) + 5}}
138 | ]
139 | },
140 | elements: {
141 | line: {
142 | borderWidth: 1},
143 | point: {
144 | radius: 4,
145 | hitRadius: 10,
146 | hoverRadius: 4}
147 | }
148 | };
149 | }
150 |
151 | function cardChartCtrl2() {
152 | this.onlineusers = 334;
153 | }
154 |
--------------------------------------------------------------------------------
/web/src/app/components/entities/add_entity.html:
--------------------------------------------------------------------------------
1 |
2 | - Bots
3 | - {{ bot.bot_name }}
4 | - Add Entity
5 |
6 |
7 |
--------------------------------------------------------------------------------
/web/src/app/components/entities/add_entity.js:
--------------------------------------------------------------------------------
1 | angular
2 | .module('app')
3 | .controller('AddEntityController', AddEntityController);
4 |
5 | function AddEntityController($scope, Entity,Bot, $rootScope) {
6 |
7 | Bot.get({bot_id: $scope.$routeParams.bot_id}, function(data) {
8 | $scope.bot = data;
9 | });
10 |
11 | $scope.addEntity = function(params) {
12 | this.formData.bot_id = $scope.$routeParams.bot_id;
13 | Entity.save(this.formData).$promise.then(function() {
14 | $scope.formData.entity_name = "";
15 | $rootScope.$broadcast('setAlertText', "Entity Added for " + $scope.bot.bot_name + " Sucessfully !!");
16 | $scope.go('/bot/' + $scope.$routeParams.bot_id)
17 | });
18 | };
19 | }
20 |
--------------------------------------------------------------------------------
/web/src/app/components/entities/edit_entity.html:
--------------------------------------------------------------------------------
1 |
2 | - Bots
3 | - {{ entity.bot.bot_name }}
4 | - {{ entity.entity_name }}
5 |
6 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/web/src/app/components/entities/edit_entity.js:
--------------------------------------------------------------------------------
1 | angular.module('app').controller('EntityController', EntityController);
2 |
3 | function EntityController($rootScope, $scope, Bot, Entity) {
4 | $scope.tags = [{}];
5 |
6 | Entity.get({ entity_id: $scope.$routeParams.entity_id }, function(data) {
7 | $scope.entity = data;
8 | });
9 |
10 | Bot.query(function(data) {
11 | $scope.botsList = data;
12 | });
13 |
14 | Bot.get({ bot_id: $scope.$routeParams.bot_id }, function(data) {
15 | $scope.entity.bot = data;
16 | });
17 |
18 | $scope.deleteEntity = function() {
19 | Entity.remove({ entity_id: $scope.$routeParams.entity_id }, function(data) {
20 | $scope.go('/bot/' + $scope.entity.bot.bot_id);
21 | });
22 | };
23 |
24 | $scope.updateEntity = function(entity) {
25 | Entity.update({ entity_id: entity.entity_id }, entity).$promise.then(
26 | function() {
27 | $rootScope.$broadcast('setAlertText', 'Entity information updated sucessfully');
28 | }
29 | );
30 | };
31 | }
32 |
--------------------------------------------------------------------------------
/web/src/app/components/intents/add_intent.html:
--------------------------------------------------------------------------------
1 |
2 | - Bots
3 | - {{ bot.bot_name }}
4 | - Add Intent
5 |
6 |
7 |
8 |
9 |
10 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/web/src/app/components/intents/add_intent.js:
--------------------------------------------------------------------------------
1 | angular
2 | .module('app')
3 | .controller('AddIntentController', AddIntentController);
4 |
5 | function AddIntentController($scope, Bot, Intent) {
6 | Bot.get({bot_id: $scope.$routeParams.bot_id}, function(data) {
7 | $scope.bot = data;
8 | });
9 |
10 | $scope.addIntent = function(params) {
11 | this.formData.bot_id = $scope.$routeParams.bot_id;
12 | Intent.save(this.formData).$promise.then(function(resp) {
13 | $scope.formData.intent_name = '';
14 | $scope.go('/bot/' + $scope.bot.bot_id)
15 | });
16 | };
17 | }
18 |
--------------------------------------------------------------------------------
/web/src/app/components/intents/edit_intent.js:
--------------------------------------------------------------------------------
1 | angular.module('app').controller('EditIntentController', EditIntentController);
2 |
3 | function EditIntentController($rootScope, $scope, Bot, BotEntities, Intent, Expressions, Expression, Parameter, Parameters, Entities, Response, Response) {
4 | Bot.get({ bot_id: $scope.$routeParams.bot_id }, function (data) {
5 | $scope.bot = data;
6 | });
7 |
8 | BotEntities.query({ bot_id: $scope.$routeParams.bot_id }, function (data) {
9 | $scope.entityList = data;
10 | });
11 |
12 | Intent.get({ intent_id: $scope.$routeParams.intent_id }, function (data) {
13 | $scope.intent = data;
14 | });
15 |
16 | loadExpressions();
17 |
18 | function loadExpressions() {
19 | Expressions.query({ intent_id: $scope.$routeParams.intent_id }, function (data) {
20 | $scope.expressionList = data;
21 | loadExpressionParameters();
22 | });
23 | }
24 |
25 | function loadExpressionParameters() {
26 | Parameters.query({ intent_id: $scope.$routeParams.intent_id }, function (
27 | data
28 | ) {
29 | $scope.parameterList = data;
30 | $scope.parameterFilterList = data;
31 | //Loop through each parameter and highlight the words it is for
32 | for (let z = 0; z <= $scope.expressionList.length; z++) {
33 | if ($scope.expressionList[z] !== undefined) {
34 | let text = $scope.expressionList[z].expression_text;
35 | for (let i = 0; i <= data.length - 1; i++) {
36 | if (
37 | $scope.expressionList[z].expression_id === data[i].expression_id
38 | ) {
39 | text = highlight(text, data[i].parameter_value);
40 | }
41 | }
42 | $scope.expressionList[z].expression_highlighted_text = text;
43 | }
44 | }
45 | });
46 | }
47 |
48 | $scope.updateIntentNameAndWebhook = function (intent) {
49 | Intent.update({ intent_id: intent.intent_id }, intent).$promise.then(
50 | function () {
51 | $rootScope.$broadcast(
52 | 'setAlertText',
53 | 'Intent information updated Sucessfully!!'
54 | );
55 | }
56 | );
57 | };
58 |
59 | $scope.runExpression = function (expression_text) {
60 | $rootScope.$broadcast('executeTestRequest', expression_text);
61 | };
62 |
63 | $scope.deleteIntent = function () {
64 | Intent.remove({ intent_id: $scope.$routeParams.intent_id }).$promise.then(
65 | function () {
66 | $scope.go('/bot/' + $scope.$routeParams.bot_id);
67 | }
68 | );
69 | };
70 |
71 | function highlight(str, word) {
72 | const highlighted = str.replace(
73 | word,
74 | '
' +
77 | word +
78 | ""
79 | );
80 | return highlighted;
81 | }
82 |
83 | $scope.toggleArrow = function (expression_id) {
84 | if ($('#table_expression_' + expression_id).hasClass('show')) {
85 | $('#icon_expression_' + expression_id)
86 | .removeClass('icon-arrow-up')
87 | .addClass('icon-arrow-down');
88 | } else {
89 | $('#icon_expression_' + expression_id)
90 | .removeClass('icon-arrow-down')
91 | .addClass('icon-arrow-up');
92 | }
93 | };
94 |
95 |
96 | $scope.addParameter = function (expression_id) {
97 | const selectedText = window.getSelection().toString();
98 | if (selectedText !== '') {
99 | const expressionText = $('#expression_' + expression_id).text();
100 | const newObj = {};
101 | newObj.expression_id = expression_id;
102 | newObj.parameter_start = expressionText.indexOf(selectedText);
103 | newObj.parameter_end = newObj.parameter_start + selectedText.length;
104 | newObj.parameter_value = selectedText;
105 | newObj.intent_id = Number($scope.$routeParams.intent_id);
106 | Parameter.save(newObj).$promise.then(function () {
107 | loadExpressions();
108 | });
109 |
110 | //Make sure parameter table is open
111 | $('#table_expression_' + expression_id).addClass('show');
112 | }
113 | };
114 |
115 | $scope.deleteParameter = function (parameter_id) {
116 | Parameter.remove({ parameter_id: parameter_id }).$promise.then(function () {
117 | loadExpressions();
118 | });
119 | };
120 |
121 | $scope.addExpression = function () {
122 | const newObj = {};
123 | newObj.intent_id = $scope.$routeParams.intent_id;
124 | newObj.expression_text = this.expression_text;
125 |
126 | Expression.save(newObj).$promise.then(function () {
127 | $scope.expression_text = '';
128 | loadExpressions();
129 | });
130 | };
131 |
132 | $scope.updateParameterEntity = function (param_id, entity_id) {
133 | Parameter.update(
134 | { parameter_id: param_id },
135 | { parameter_id: param_id, entity_id: entity_id }
136 | ).$promise.then(function () {
137 | //loadUniqueIntentEntities();
138 | //loadExpressions();
139 | });
140 | };
141 |
142 | $scope.deleteExpression = function (expression_id) {
143 | Expression.remove({ expression_id: expression_id }).$promise.then(
144 | function () {
145 | loadExpressions();
146 | }
147 | );
148 | };
149 | }
150 |
--------------------------------------------------------------------------------
/web/src/app/components/logs/logs.html:
--------------------------------------------------------------------------------
1 |
2 | - Logs
3 |
4 |
5 |
6 |
7 |
8 |
9 |
27 |
28 |
29 |
30 |
31 |
32 | Date |
33 | IP Address |
34 | Event |
35 | Data |
36 |
37 |
38 |
39 | |
40 | {{ entry.ip_address }} |
41 | {{ entry.event_type }} |
42 | {{ entry.event_data }} |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/web/src/app/components/logs/logs.js:
--------------------------------------------------------------------------------
1 | angular
2 | .module('app')
3 | .controller('LogsController', LogsController);
4 |
5 | function LogsController($scope, $http, $sce, NLU_log) {
6 |
7 | $scope.loadLogs = function(type) {
8 | const query = type;
9 | NLU_log.query({query}, function(data) {
10 | $scope.logData = data;
11 | });
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/web/src/app/components/models/add_model.html:
--------------------------------------------------------------------------------
1 |
2 | - Models
3 | - Add Model
4 |
5 |
6 |
7 |
8 |
9 |
10 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/web/src/app/components/models/add_model.js:
--------------------------------------------------------------------------------
1 | angular
2 | .module('app')
3 | .controller('AddModelController', AddModelController)
4 |
5 | function AddModelController($scope, Model) {
6 | $scope.addModel = function(params) {
7 | this.formData.bot_id = $scope.$routeParams.bot_id;
8 | Model.save(this.formData).$promise.then(function() {
9 | $scope.go('/models/' + $scope.$routeParams.bot_id)
10 | });
11 | };
12 | }
13 |
--------------------------------------------------------------------------------
/web/src/app/components/models/models.html:
--------------------------------------------------------------------------------
1 |
2 | - Models
3 |
4 |
5 |
6 |
7 |
8 |
9 | {{message.text}}
10 |
11 |
23 |
24 |
25 |
26 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
56 |
57 |
58 |
59 |
60 | Create Date/Time |
61 | File |
62 | Comment |
63 | Actions |
64 |
65 |
66 |
67 |
68 | {{ model.timestamp }} |
69 | File: {{ model.model_name }} Local Path: {{ model.local_path }} Rasa Server Path: {{ model.server_path }} |
70 | {{ model.comment }} |
71 |
72 |
75 |
78 | |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
--------------------------------------------------------------------------------
/web/src/app/components/models/models.js:
--------------------------------------------------------------------------------
1 | angular.module('app').controller('ModelController', ModelController);
2 |
3 | function ModelController($scope, $rootScope, appConfig, Model, Bot, Rasa_Status, $http) {
4 | $scope.message = {};
5 | $scope.message.text = "";
6 | $scope.botList = {};
7 | $scope.bot = {};
8 |
9 | checkRasaStatus();
10 |
11 | Bot.query(function (data) {
12 | $scope.botList = data;
13 |
14 | if ($scope.$routeParams.bot_id) {
15 | $scope.selectedBot = $scope.objectFindByKey($scope.botList, 'bot_id', Number($scope.$routeParams.bot_id));
16 | $scope.bot.bot_id = $scope.selectedBot.bot_id;
17 | loadBotModels(Number($scope.$routeParams.bot_id));
18 | }
19 | });
20 |
21 | function checkRasaStatus() {
22 | Rasa_Status.get(function (statusdata) {
23 | $scope.config = JSON.parse(angular.toJson(statusdata));
24 | });
25 | }
26 |
27 | $scope.getData = function (bot_id) {
28 | if (bot_id) {
29 | $scope.selectedBot = $scope.objectFindByKey($scope.botList, 'bot_id', bot_id);
30 | loadBotModels(bot_id);
31 | }
32 | }
33 |
34 | function loadBotModels(bot_id) {
35 | Model.query({ bot_id: bot_id }, function (data) {
36 | data = $scope.cleanResponse(data);
37 | for (var i = 0; i < data.length; i++) {
38 | if (data[i].local_path != "Manually added") {
39 | data[i].server_path = $scope.selectedBot.output_folder + "/" + data[i].server_path
40 | }
41 | }
42 | $scope.modelList = data;
43 | });
44 | checkRasaStatus();
45 | }
46 |
47 | $scope.deleteModel = function (model_id) {
48 | let model = $scope.objectFindByKey($scope.modelList, 'model_id', model_id);
49 | Model.remove({ model_id: model_id, local_path: model.local_path }).$promise.then(function () {
50 | loadBotModels($scope.selectedBot.bot_id);
51 | });
52 | }
53 |
54 | $scope.loadRasaModel = function (server_model) {
55 | let botToTrain = $scope.objectFindByKey($scope.botList, 'bot_id', $scope.bot.bot_id);
56 | $scope.message = {text: "Loading model: " + server_model, type: "info"};
57 | /* TODO: Replace with factory methods */
58 | $http.put(appConfig.api_endpoint_v2 + "/rasa/model", { "model_file": server_model }).then(
59 | function (response) {
60 | if (response.data.code && response.data.code == 400) {
61 | $scope.message = {text: "Error loading model: " + JSON.stringify(response), type: "danger"};
62 | } else {
63 | $scope.message = {text: "Loaded model: " + server_model, type: "success"};
64 | }
65 | loadBotModels(botToTrain.bot_id);
66 | },
67 | function (err) {
68 | $scope.message = {text: "Loading for: " + botToTrain.bot_name + " failed", type: "danger"};
69 | $rootScope.trainings_under_this_process = 0;
70 | }
71 | );
72 | }
73 |
74 | $scope.unloadRasaModel = function (server_model) {
75 | let botToTrain = $scope.objectFindByKey($scope.botList, 'bot_id', $scope.bot.bot_id);
76 | $scope.message = {text: "Unloading model: " + server_model, type: "info"};
77 | /* TODO: Replace with factory methods */
78 | $http.delete(appConfig.api_endpoint_v2 + "/rasa/model").then(
79 | function (response) {
80 | $scope.message = {text: "Unloaded the model", type: "success"};
81 | loadBotModels(botToTrain.bot_id);
82 | },
83 | function (err) {
84 | $scope.message = {text: "Unloading the model failed", type: "danger"};
85 | }
86 | );
87 | }
88 | }
--------------------------------------------------------------------------------
/web/src/app/components/rasaconfig/rasa_config.html:
--------------------------------------------------------------------------------
1 |
2 | - Rasa Configuration
3 |
4 |
5 |
6 |
7 |
8 |
31 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/web/src/app/components/rasaconfig/rasa_config.js:
--------------------------------------------------------------------------------
1 | angular
2 | .module('app')
3 | .controller('RasaConfigController', RasaConfigController);
4 |
5 | function RasaConfigController($scope, $rootScope) {
6 |
7 | }
8 |
--------------------------------------------------------------------------------
/web/src/app/components/regex/add_regex.html:
--------------------------------------------------------------------------------
1 |
2 | - Bots
3 | -
4 | {{ bot.bot_name }}
5 |
6 | - Add Regex
7 |
8 |
9 |
10 |
11 |
12 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/web/src/app/components/regex/add_regex.js:
--------------------------------------------------------------------------------
1 | angular.module('app').controller('AddRegexController', AddRegexController);
2 |
3 | function AddRegexController($rootScope, $scope, Regex, Bot, $location) {
4 | Bot.get({ bot_id: $scope.$routeParams.bot_id }, function (data) {
5 | $scope.bot = data;
6 | });
7 |
8 | $scope.addRegex = function () {
9 | this.formData.bot_id = $scope.$routeParams.bot_id;
10 | Regex.save(this.formData).$promise.then(function (resp) {
11 | $scope.formData.regex_name = '';
12 | $scope.formData.regex_pattern = '';
13 | $rootScope.$broadcast('setAlertText', "Regex added sucessfully!");
14 | $scope.go('/bot/' + $scope.bot.bot_id);
15 | });
16 | };
17 | }
18 |
--------------------------------------------------------------------------------
/web/src/app/components/regex/edit_regex.html:
--------------------------------------------------------------------------------
1 |
2 | - Bots
3 | -
4 | {{ bot.bot_name }}
5 |
6 | - {{ regex.regex_name }}
7 |
8 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | {{ message }}
22 |
23 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/web/src/app/components/regex/edit_regex.js:
--------------------------------------------------------------------------------
1 | angular.module('app').controller('EditRegexController', EditRegexController);
2 |
3 | function EditRegexController($rootScope, $scope, Regex, Bot) {
4 | $scope.message = '';
5 |
6 | Bot.get({ bot_id: $scope.$routeParams.bot_id }, function (data) {
7 | $scope.bot = data;
8 | });
9 |
10 | Regex.get({ regex_id: $scope.$routeParams.regex_id }, function (data) {
11 | $scope.regex = data;
12 | });
13 |
14 | $scope.deleteRegex = function () {
15 | Regex.remove({ regex_id: $scope.$routeParams.regex_id }).$promise.then(
16 | function () {
17 | $scope.go(`/bot/${$scope.$routeParams.bot_id}`);
18 | }
19 | );
20 | };
21 |
22 | $scope.editRegex = function (bot) {
23 | Regex.update(
24 | { regex_id: $scope.regex.regex_id },
25 | $scope.regex
26 | ).$promise.then(function () {
27 | $rootScope.$broadcast('setAlertText', "Regex updated Sucessfully!!");
28 | $scope.go(`/bot/${$scope.$routeParams.bot_id}`);
29 | });
30 | };
31 | }
32 |
--------------------------------------------------------------------------------
/web/src/app/components/responses/add_action.html:
--------------------------------------------------------------------------------
1 |
2 | - Responses
3 | - Add Action
4 |
5 |
6 |
7 |
8 |
9 |
10 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/web/src/app/components/responses/add_action.js:
--------------------------------------------------------------------------------
1 | angular
2 | .module('app')
3 | .controller('AddActionController', AddActionController)
4 |
5 | function AddActionController($scope, Actions) {
6 | $scope.bot_id = $scope.$routeParams.bot_id;
7 | $scope.addAction = function(params) {
8 | this.formData.bot_id = $scope.bot_id
9 | Actions.save(this.formData).$promise.then(function() {
10 | $scope.go('/responses/' + $scope.bot_id);
11 | });
12 | };
13 | }
14 |
--------------------------------------------------------------------------------
/web/src/app/components/responses/responses.html:
--------------------------------------------------------------------------------
1 |
2 | - Responses
3 |
4 |
5 |
6 |
7 |
8 |
9 | {{message.text}}
10 |
11 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
38 |
39 |
40 |
41 |
42 |
43 | {{ action.action_name }}
44 |
45 |
51 |
56 |
57 |
58 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
--------------------------------------------------------------------------------
/web/src/app/components/responses/responses.js:
--------------------------------------------------------------------------------
1 | angular.module('app').controller('ResponseController', ResponseController);
2 |
3 | function ResponseController($rootScope, $scope, $sce, Bot, Response, Actions ) {
4 | $scope.message = {};
5 | $scope.message.text = "";
6 | $scope.bot = {};
7 | $scope.selectedBot = {};
8 |
9 | $scope.graphData = '';
10 | $scope.responseTypeList = [{id: "text", type: "text"}, {id: "button", type: "buttons"}];
11 | $scope.responseList = [];
12 |
13 | Bot.query(function (data) {
14 | $scope.botList = data;
15 |
16 | if ($scope.$routeParams.bot_id) {
17 | $scope.selectedBot = $scope.objectFindByKey($scope.botList, 'bot_id', Number($scope.$routeParams.bot_id));
18 | $scope.bot.bot_id = $scope.selectedBot.bot_id;
19 | $scope.loadBotActionsAndResponses($scope.selectedBot.bot_id);
20 | }
21 | });
22 |
23 | $scope.saveResponse = function(action, action_id) {
24 | action.new_response.action_id = action_id;
25 | Response.save(action.new_response).$promise.then(function() {
26 | $scope.loadBotActionsAndResponses($scope.selectedBot.bot_id);
27 | });
28 | }
29 |
30 | $scope.updateResponse = function(response_id, response_type, response_text) {
31 | Response.update({ response_id: response_id, response_type: response_type, response_text: response_text}).$promise.then(function() {
32 | $scope.go('/responses/' + $scope.selectedBot.bot_id);
33 | $rootScope.$broadcast('setAlertText', 'Response updated');
34 | });
35 | }
36 |
37 | $scope.loadBotActionsAndResponses = function(bot_id) {
38 | $scope.selectedBot = $scope.objectFindByKey($scope.botList, 'bot_id', bot_id);
39 | Actions.query({bot_id: bot_id }, data => {
40 | $scope.actionsList = data[0].actions;
41 | $scope.responseList = data[0].responses;
42 | });
43 | }
44 |
45 | $scope.deleteResponse = function(response_id) {
46 | Response.delete({response_id: response_id }, data => {
47 | $scope.loadBotActionsAndResponses($scope.selectedBot.bot_id);
48 | });
49 | }
50 |
51 | $scope.deleteAction = function(action_id) {
52 | Actions.delete({action_id: action_id }, data => {
53 | $scope.loadBotActionsAndResponses($scope.selectedBot.bot_id);
54 | });
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/web/src/app/components/settings/settings.html:
--------------------------------------------------------------------------------
1 |
2 | - UI Settings
3 |
4 |
--------------------------------------------------------------------------------
/web/src/app/components/settings/settings.js:
--------------------------------------------------------------------------------
1 | angular
2 | .module('app')
3 | .controller('SettingsController', SettingsController);
4 |
5 | function SettingsController($rootScope, $scope, Settings) {
6 | $scope.updateSettings = function (setting_name, setting_value) {
7 | Settings.update({ setting_name: setting_name }, { setting_name: setting_name, setting_value: setting_value }).$promise.then(function () {
8 | $rootScope.$broadcast('refreshIntervelUpdate');
9 | $rootScope.$broadcast('setAlertText', 'Refresh interval updated Successfully');
10 | });
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/web/src/app/components/stories/stories.html:
--------------------------------------------------------------------------------
1 |
2 | - Stories
3 |
4 |
5 |
6 |
7 |
8 |
9 | {{message.text}}
10 |
11 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
38 |
39 |
40 |
41 | {{story.story_name}}
{{ story.timestamp }}
42 |
43 |
48 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
60 |
61 |
74 |
75 |
76 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
--------------------------------------------------------------------------------
/web/src/app/components/synonyms/add_synonym.html:
--------------------------------------------------------------------------------
1 |
2 | - Bots
3 | -
4 | {{ bot.bot_name }}
5 |
6 | -
7 | Add Synonym
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/web/src/app/components/synonyms/add_synonym.js:
--------------------------------------------------------------------------------
1 | angular.module('app').controller('AddSynonymController', AddSynonymController);
2 |
3 | function AddSynonymController($scope, Synonym, EntitySynonymVariants, Bot, SynonymVariant, $location) {
4 | Bot.get({ bot_id: $scope.$routeParams.bot_id }, function (data) {
5 | $scope.bot = data;
6 | });
7 |
8 | $scope.addSynonym = function (params) {
9 | const obNew = { bot_id: $scope.$routeParams.bot_id, synonym_reference: $("#synonym_reference").val() };
10 | $('#synonym_reference').val('');
11 | Synonym.save(obNew).$promise.then(function (resp) {
12 | $scope.go('/bot/' + $scope.bot.bot_id + '/synonym/' + resp.synonym_id)
13 | });
14 | };
15 | }
--------------------------------------------------------------------------------
/web/src/app/components/synonyms/edit_synonym.html:
--------------------------------------------------------------------------------
1 |
2 | - Bots
3 | -
4 | {{ bot.bot_name }}
5 |
6 | -
7 | {{ synonym.synonym_reference }}
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | {{ synonym.synonym_reference }} |
22 |
23 |
27 | |
28 |
29 |
32 | |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/web/src/app/components/synonyms/edit_synonym.js:
--------------------------------------------------------------------------------
1 | angular.module('app').controller('SynonymController', SynonymController);
2 |
3 | function SynonymController($scope, Synonym, EntitySynonymVariants, Bot, SynonymVariant, $location) {
4 | $scope.tags = [{}];
5 |
6 | Bot.get({ bot_id: $scope.$routeParams.bot_id }, function (data) {
7 | $scope.bot = data;
8 | });
9 |
10 | if ($scope.$routeParams.synonym_id) {
11 | Synonym.query({ synonym_id: $scope.$routeParams.synonym_id }, function (data) {
12 | $scope.synonym = data;
13 | getEntitySynonymVariants($scope.synonym.synonym_id);
14 | });
15 | }
16 |
17 | $scope.synonymRemoved = function (tag) {
18 | SynonymVariant.remove({ synonym_variant_id: tag.synonym_variant_id });
19 | };
20 |
21 | $scope.synonymAdded = function (tag, synonym_id) {
22 | var objNew = {};
23 | objNew.synonym_value = tag.text;
24 | objNew.synonym_id = synonym_id;
25 | SynonymVariant.save(objNew, function (data) {
26 | //Set the tag id once we have it from the DB
27 | tag.synonym_variant_id = data.synonym_variant_id
28 | });
29 | };
30 |
31 | function getEntitySynonymVariants(synonym_id) {
32 | EntitySynonymVariants.query({ synonym_id: synonym_id }).$promise.then(function (data) {
33 | var tags = [];
34 | for (var i = 0; i <= data.length - 1; i++) {
35 | tags.push({
36 | text: data[i].synonym_value,
37 | synonym_variant_id: data[i].synonym_variant_id
38 | });
39 | }
40 | $scope.tags[synonym_id] = tags;
41 | }
42 | );
43 | }
44 |
45 | $scope.deleteSynonym = function (synonym_id) {
46 | //First delete all synonym variants, then the synonym
47 | EntitySynonymVariants.remove({ synonym_id: synonym_id }, function (data) {
48 | Synonym.remove({ synonym_id: synonym_id }, function (data) {
49 | $location.path(`/bot/${$scope.$routeParams.bot_id}`);
50 | });
51 | });
52 | };
53 | }
54 |
--------------------------------------------------------------------------------
/web/src/app/components/training/training.html:
--------------------------------------------------------------------------------
1 |
2 | - Training
3 |
4 |
5 |
6 |
7 |
8 |
9 | {{message}}
10 |
11 |
12 | {{ generateError }}
13 |
14 |
15 | Training is currently running.
16 |
17 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
74 |
75 |
110 |
111 |
--------------------------------------------------------------------------------
/web/src/app/config/app.config.js:
--------------------------------------------------------------------------------
1 | angular.module("app").constant("appConfig", {
2 | api_endpoint_v2: "/api/v2"
3 | });
4 |
--------------------------------------------------------------------------------
/web/src/app/directives.js:
--------------------------------------------------------------------------------
1 | angular.module('app')
2 | .directive('a', navigationDirective)
3 | .directive('confirmClick', confirmClickDirective)
4 | .directive('a', navigationDirective)
5 | .directive('button', layoutToggleDirective)
6 | .directive('button', collapseMenuTogglerDirective)
7 | .directive('scrollBottom', function () {
8 | return {
9 | link: function (scope, element) {
10 | scope.$watch(function () {
11 | element.scrollTop(element[0].scrollHeight);
12 | });
13 | }
14 | }
15 | })
16 | .directive('tooltip', function () {
17 | return {
18 | restrict: 'A',
19 | link: function (scope, element) {
20 | element.hover(
21 | function () {
22 | element.tooltip('show');
23 | },
24 | function () {
25 | element.tooltip('hide');
26 | }
27 | );
28 | element.click(
29 | function () {
30 | element.tooltip('hide');
31 | }
32 | );
33 | }
34 | };
35 | }).filter('trusted',
36 | function ($sce) {
37 | return function (ss) {
38 | return $sce.trustAsHtml(ss)
39 | };
40 | }
41 | ).filter('chatDate', function($filter) {
42 | var angularDateFilter = $filter('date');
43 | return function(theDate) {
44 | const today = new Date();
45 | const filterDate = new Date(theDate);
46 | if (filterDate.setHours(0,0,0,0) == today.setHours(0,0,0,0)) {
47 | return angularDateFilter(theDate, 'HH:mm:ss');
48 | } else {
49 | return angularDateFilter(theDate, 'MM/dd/yyyy h:mm:ss a');
50 | }
51 | }
52 | });;
53 |
54 | function confirmClickDirective() {
55 | let i = 0;
56 | return {
57 | restrict: 'A',
58 | priority: 1,
59 | compile: function (tElem, tAttrs) {
60 | const fn = '$$confirmClick' + i++,
61 | _ngClick = tAttrs.ngClick;
62 | tAttrs.ngClick = fn + '($event)';
63 |
64 | return function (scope, elem, attrs) {
65 | const confirmTitle = attrs.confirmClickTitle || 'Please confirm';
66 | const confirmMsg = attrs.confirmClick || 'Are you sure?';
67 |
68 | scope[fn] = function (event) {
69 | $('#modal_confirm').modal('show');
70 | $('#modal_body').text(confirmMsg);
71 | $('#modal_title').text(confirmTitle);
72 | $('#modal_confirm').one('click', '#modal_save_btn', function (e) {
73 | scope.$eval(_ngClick, { $event: event });
74 | try {
75 | $('#modal_confirm').modal('hide');
76 | } catch (err) {
77 | // Bug in bootstrap 4 with hiding = transition error
78 | }
79 | });
80 | };
81 | };
82 | }
83 | };
84 | }
85 |
86 | function navigationDirective() {
87 | return {
88 | restrict: 'E',
89 | link
90 | };
91 |
92 | function link(scope, element, attrs) {
93 | if (element.hasClass('nav-dropdown-toggle') && angular.element('body').width() > 782) {
94 | element.on('click', function () {
95 | if (!angular.element('body').hasClass('compact-nav')) {
96 | element.parent().toggleClass('open').find('.open').removeClass('open');
97 | }
98 | });
99 | } else if (element.hasClass('nav-dropdown-toggle') && angular.element('body').width() < 783) {
100 | element.on('click', function () {
101 | element.parent().toggleClass('open').find('.open').removeClass('open');
102 | });
103 | }
104 | }
105 | }
106 |
107 | //Dynamic resize .sidebar-nav
108 | sidebarNavDynamicResizeDirective.$inject = ['$window', '$timeout'];
109 | function sidebarNavDynamicResizeDirective($window, $timeout) {
110 | return {
111 | restrict: 'E',
112 | link
113 | };
114 |
115 | function link(scope, element, attrs) {
116 |
117 | if (element.hasClass('sidebar-nav') && angular.element('body').hasClass('fixed-nav')) {
118 | const bodyHeight = angular.element(window).height();
119 | scope.$watch(function () {
120 | const headerHeight = angular.element('header').outerHeight();
121 |
122 | if (angular.element('body').hasClass('sidebar-off-canvas')) {
123 | element.css('height', bodyHeight);
124 | } else {
125 | element.css('height', bodyHeight - headerHeight);
126 | }
127 | });
128 |
129 | angular.element($window).bind('resize', function () {
130 | const bodyHeight = angular.element(window).height();
131 | const headerHeight = angular.element('header').outerHeight();
132 | const sidebarHeaderHeight = angular.element('.sidebar-header').outerHeight();
133 | const sidebarFooterHeight = angular.element('.sidebar-footer').outerHeight();
134 |
135 | if (angular.element('body').hasClass('sidebar-off-canvas')) {
136 | element.css('height', bodyHeight - sidebarHeaderHeight - sidebarFooterHeight);
137 | } else {
138 | element.css('height', bodyHeight - headerHeight - sidebarHeaderHeight - sidebarFooterHeight);
139 | }
140 | });
141 | }
142 | }
143 | }
144 |
145 | //LayoutToggle
146 | layoutToggleDirective.$inject = ['$interval'];
147 | function layoutToggleDirective($interval) {
148 | return {
149 | restrict: 'E',
150 | link
151 | };
152 |
153 | function link(scope, element, attrs) {
154 | element.on('click', function () {
155 |
156 | if (element.hasClass('sidebar-toggler')) {
157 | angular.element('body').toggleClass('sidebar-hidden');
158 | }
159 |
160 | if (element.hasClass('aside-menu-toggler')) {
161 | angular.element('body').toggleClass('aside-menu-hidden');
162 | }
163 | });
164 | }
165 | }
166 |
167 | //Collapse menu toggler
168 | function collapseMenuTogglerDirective() {
169 | return {
170 | restrict: 'E',
171 | link
172 | };
173 |
174 | function link(scope, element, attrs) {
175 | element.on('click', function () {
176 | if (element.hasClass('navbar-toggler') && !element.hasClass('layout-toggler')) {
177 | angular.element('body').toggleClass('sidebar-mobile-show')
178 | }
179 | })
180 | }
181 | }
182 |
--------------------------------------------------------------------------------
/web/src/app/services/api.js:
--------------------------------------------------------------------------------
1 | var app = angular.module('app');
2 |
3 | app.factory('Bot', function ($resource, appConfig) {
4 | return $resource(
5 | appConfig.api_endpoint_v2 + '/bots/:bot_id/:path',
6 | { bot_id: '@id', path: '@path' },
7 | {
8 | update: { method: 'PUT' }
9 | }
10 | );
11 | });
12 |
13 | /* Core API's */
14 | app.factory('Stories', function ($resource, appConfig) {
15 | return $resource(appConfig.api_endpoint_v2 + '/stories/:bot_id/:path',
16 | { bot_id: '@id', path: '@path' },
17 | {
18 | update: { method: 'PUT' }
19 | });
20 | });
21 |
22 | app.factory('Response', function ($resource, appConfig) {
23 | return $resource(
24 | appConfig.api_endpoint_v2 + '/response',
25 | { action_id: '@id' },
26 | {
27 | update: { method: 'PUT' }
28 | }
29 | );
30 | });
31 |
32 | app.factory('Actions', function ($resource, appConfig) {
33 | return $resource(
34 | appConfig.api_endpoint_v2 + '/actions',
35 | { action_id: '@id' },
36 | {
37 | update: { method: 'PUT' }
38 | }
39 | );
40 | });
41 |
42 | app.factory('Conversations', function ($resource, appConfig) {
43 | return $resource(appConfig.api_endpoint_v2 + '/conversations/:bot_id', {
44 | bot_id: '@id'
45 | });
46 | });
47 |
48 |
49 | app.factory('BotActions', function ($resource, appConfig) {
50 | return $resource(appConfig.api_endpoint_v2 + '/bots/:bot_id/actions', {
51 | bot_id: '@id'
52 | });
53 | });
54 |
55 | app.factory('ActionResponses', function ($resource, appConfig) {
56 | return $resource(appConfig.api_endpoint_v2 + '/actionresponse/:action_id', {
57 | action_id: '@id'
58 | });
59 | });
60 |
61 | app.factory('IntentResponse', function ($resource, appConfig) {
62 | return $resource(appConfig.api_endpoint_v2 + '/rndmresponse');
63 | });
64 |
65 | /* End Core API's */
66 |
67 | app.factory('Auth', function ($resource, appConfig) {
68 | return $resource(appConfig.api_endpoint_v2 + '/auth');
69 | });
70 |
71 | app.factory('Intent', function ($resource, appConfig) {
72 | return $resource(
73 | appConfig.api_endpoint_v2 + '/intents/:intent_id',
74 | { intent_id: '@id' },
75 | {
76 | update: { method: 'PUT' }
77 | }
78 | );
79 | });
80 |
81 | app.factory('Intents', function ($resource, appConfig) {
82 | return $resource(appConfig.api_endpoint_v2 + '/bots/:bot_id/intents', {
83 | bot_id: '@id'
84 | });
85 | });
86 |
87 | app.factory('Expressions', function ($resource, appConfig) {
88 | return $resource(
89 | appConfig.api_endpoint_v2 + '/intents/:intent_id/expressions',
90 | {
91 | intent_id: '@id'
92 | }
93 | );
94 | });
95 |
96 | app.factory('IntentExpressions', function ($resource, appConfig) {
97 | return $resource(appConfig.api_endpoint_v2 + '/intent_expressions');
98 | });
99 |
100 | app.factory('Expression', function ($resource, appConfig) {
101 | return $resource(
102 | appConfig.api_endpoint_v2 + '/expressions/:expression_id',
103 | {
104 | expression_id: '@id'
105 | },
106 | {
107 | update: { method: 'PUT' }
108 | }
109 | );
110 | });
111 |
112 | app.factory('Parameters', function ($resource, appConfig) {
113 | return $resource(appConfig.api_endpoint_v2 + '/intent/:intent_id/parameters');
114 | });
115 |
116 | app.factory('ExpressionParameters', function ($resource, appConfig) {
117 | return $resource(
118 | appConfig.api_endpoint_v2 + '/expression_parameters/:expression_id'
119 | );
120 | });
121 |
122 | app.factory('Parameter', [
123 | '$resource',
124 | 'appConfig',
125 | function ($resource, appConfig) {
126 | return $resource(
127 | appConfig.api_endpoint_v2 + '/parameters/:parameter_id',
128 | { parameter_id: '@id' },
129 | {
130 | update: { method: 'PUT' }
131 | }
132 | );
133 | }
134 | ]);
135 |
136 | app.factory('Entity', [
137 | '$resource',
138 | 'appConfig',
139 | function ($resource, appConfig) {
140 | return $resource(
141 | appConfig.api_endpoint_v2 + '/entities/:entity_id',
142 | { entity_id: '@id' },
143 | {
144 | update: { method: 'PUT' }
145 | }
146 | );
147 | }
148 | ]);
149 |
150 | app.factory('Entities', function ($resource, appConfig) {
151 | return $resource(appConfig.api_endpoint_v2 + '/entities');
152 | });
153 |
154 | app.factory('Regex', [
155 | '$resource',
156 | 'appConfig',
157 | function ($resource, appConfig) {
158 | return $resource(
159 | appConfig.api_endpoint_v2 + '/regex/:regex_id',
160 | { regex_id: '@id' },
161 | {
162 | update: { method: 'PUT' }
163 | }
164 | );
165 | }
166 | ]);
167 |
168 | app.factory('BotRegex', [
169 | '$resource',
170 | 'appConfig',
171 | function ($resource, appConfig) {
172 | return $resource(appConfig.api_endpoint_v2 + '/bot/:bot_id/regex', {
173 | bot_id: '@id'
174 | });
175 | }
176 | ]);
177 |
178 | app.factory('BotSynonyms', function ($resource, appConfig) {
179 | return $resource(appConfig.api_endpoint_v2 + '/bot/:bot_id/synonyms', {
180 | bot_id: '@id'
181 | });
182 | });
183 |
184 | app.factory('BotEntities', function ($resource, appConfig) {
185 | return $resource(appConfig.api_endpoint_v2 + '/entities/bot/:bot_id', {
186 | bot_id: '@id'
187 | });
188 | });
189 |
190 | app.factory('Synonym', function ($resource, appConfig) {
191 | return $resource(
192 | appConfig.api_endpoint_v2 + '/synonyms/:synonym_id',
193 | {
194 | synonym_id: '@id'
195 | },
196 | {
197 | query: { method: 'GET', isArray: false }
198 | }
199 | );
200 | });
201 |
202 | app.factory('EntitySynonymVariants', function ($resource, appConfig) {
203 | return $resource(
204 | appConfig.api_endpoint_v2 + '/synonyms/:synonym_id/variants',
205 | {
206 | synonym_id: '@id'
207 | }
208 | );
209 | });
210 |
211 | app.factory('SynonymsVariants', function ($resource, appConfig) {
212 | return $resource(
213 | appConfig.api_endpoint_v2 + '/synonyms_variants/:synonyms_id',
214 | {
215 | synonyms_id: '@id'
216 | }
217 | );
218 | });
219 |
220 | app.factory('SynonymVariant', function ($resource, appConfig) {
221 | return $resource(
222 | appConfig.api_endpoint_v2 + '/variants/:synonym_variant_id',
223 | {
224 | synonym_variant_id: '@id'
225 | }
226 | );
227 | });
228 |
229 | app.factory('AllSynonymVariants', function ($resource, appConfig) {
230 | return $resource(appConfig.api_endpoint_v2 + '/synonymvariants');
231 | });
232 |
233 | app.factory('Settings', [
234 | '$resource',
235 | 'appConfig',
236 | function ($resource, appConfig) {
237 | return $resource(
238 | appConfig.api_endpoint_v2 + '/settings/:setting_name',
239 | { setting_name: '@setting_name' },
240 | {
241 | update: { method: 'PUT' }
242 | }
243 | );
244 | }
245 | ]);
246 |
247 | app.factory('Model', function ($resource, appConfig) {
248 | return $resource(
249 | appConfig.api_endpoint_v2 + '/models/:bot_id',
250 | { bot_id: '@id', path: '@path' }
251 | );
252 | });
253 |
--------------------------------------------------------------------------------
/web/src/app/services/log.js:
--------------------------------------------------------------------------------
1 | var app = angular.module('app');
2 |
3 | app.factory('NLU_log', function($resource, appConfig) {
4 | return $resource(appConfig.api_endpoint_v2 + '/nlu_log/:query', {
5 | query: '@id'
6 | });
7 | });
8 |
9 | app.factory('NLU_log_stats', function($resource, appConfig) {
10 | return $resource(appConfig.api_endpoint_v2 + '/:path', { path: '@path' });
11 | });
12 |
--------------------------------------------------------------------------------
/web/src/app/services/rasa_api.js:
--------------------------------------------------------------------------------
1 | var app = angular.module('app');
2 |
3 | app.factory('Rasa_Parse', function($resource, appConfig) {
4 | return $resource(
5 | appConfig.api_endpoint_v2 + '/rasa/parse?q=:query&model=:model',
6 | { query: '@id', model: '@id' }
7 | );
8 | });
9 |
10 | app.factory('Rasa_Status', function($resource, appConfig) {
11 | return $resource(appConfig.api_endpoint_v2 + '/rasa/status');
12 | });
13 |
14 | app.factory('Rasa_Config', function($resource, appConfig) {
15 | return $resource(appConfig.api_endpoint_v2 + '/rasa/config');
16 | });
17 |
18 | app.factory('Rasa_Version', function($resource, appConfig) {
19 | return $resource(appConfig.api_endpoint_v2 + '/rasa/version');
20 | });
21 |
22 | app.factory('Rasa_Story', function($resource, appConfig) {
23 | return $resource(appConfig.api_endpoint_v2 + '/rasa/story');
24 | });
--------------------------------------------------------------------------------
/web/src/app/shared/aside/aside.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/web/src/app/shared/aside/aside.js:
--------------------------------------------------------------------------------
1 | angular.module('app').controller('AsideController', AsideController);
2 |
3 | function AsideController($scope, $rootScope, $http, appConfig) {
4 | $scope.test_text = '';
5 | $scope.test_text_response = {};
6 | $rootScope.config = {}; //Initilize in case server is not online at startup
7 | let configcheck;
8 |
9 | $scope.$on('executeTestRequest', function (event, expression_text) {
10 | $scope.test_text = expression_text;
11 | $scope.executeTestRequest();
12 | });
13 |
14 | function addOverlay() {
15 | $('.aside-menu').addClass('dimmed');
16 | }
17 |
18 | function removeOverlay() {
19 | $('.aside-menu').removeClass('dimmed');
20 | }
21 |
22 | $scope.executeTestRequest = function () {
23 | $scope.response_text = [];
24 | $scope.test_text_response = {};
25 | let reqMessage = {};
26 |
27 | reqMessage = { text: $scope.test_text };
28 |
29 | //TODO: We should use a factory method for this
30 | if ($scope.test_text) {
31 | //make a httpcall
32 | addOverlay();
33 | $http.post(appConfig.api_endpoint_v2 + '/rasa/model/parse', JSON.stringify(reqMessage)).then(function (response) {
34 | // success callback
35 | removeOverlay();
36 | $scope.test_text_response = response.data;
37 | if (!$scope.wsEnabled) {
38 | if ($scope.test_text_response > 0) {
39 | $scope.test_text_response.forEach(function (response) {
40 | $scope.response_text.push(response.response_text);
41 | });
42 | }
43 | }
44 | },
45 | function (errorResponse) {
46 | removeOverlay();
47 | }
48 | );
49 | }
50 | };
51 | }
52 |
--------------------------------------------------------------------------------
/web/src/app/shared/navbar/navbar.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/web/src/app/shared/navbar/navbar.js:
--------------------------------------------------------------------------------
1 | angular.module("app").controller("NavBarController", NavBarController);
2 |
3 | function NavBarController($scope, $rootScope, appConfig, $route) {
4 | $scope.toggleAside = function () {
5 | if (angular.element("body").hasClass("aside-menu-hidden")) {
6 | angular
7 | .element("body")
8 | .removeClass("aside-menu-hidden")
9 | .addClass("aside-menu-fixed");
10 | } else {
11 | angular
12 | .element("body")
13 | .removeClass("aside-menu-fixed")
14 | .addClass("aside-menu-hidden");
15 | }
16 | };
17 |
18 | $scope.toggleSidebar = function () {
19 | if (angular.element("body").hasClass("sidebar-fixed")) {
20 | angular
21 | .element("body")
22 | .removeClass("sidebar-fixed")
23 | .addClass("sidebar-hidden");
24 | } else {
25 | angular
26 | .element("body")
27 | .addClass("sidebar-fixed")
28 | .removeClass("sidebar-hidden");
29 | }
30 | };
31 |
32 | $scope.logout = function () {
33 | $rootScope.$broadcast("INVALID_JWT_TOKEN");
34 | $route.reload();
35 | };
36 | }
37 |
--------------------------------------------------------------------------------
/web/src/app/shared/sidebar/sidebar.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/web/src/app/shared/sidebar/sidebar.js:
--------------------------------------------------------------------------------
1 | angular
2 | .module('app')
3 | .controller('SideBarController', SideBarController);
4 |
5 | function SideBarController($rootScope, $scope) {
6 | $scope.logout = function () {
7 | $rootScope.$broadcast("INVALID_JWT_TOKEN");
8 | };
9 | }
10 |
--------------------------------------------------------------------------------
/web/src/assets/css/fonts/FontAwesome.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paschmann/rasa-ui/3f5deadb92a4392838b647e95d6c08752964566d/web/src/assets/css/fonts/FontAwesome.otf
--------------------------------------------------------------------------------
/web/src/assets/css/fonts/fontawesome-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paschmann/rasa-ui/3f5deadb92a4392838b647e95d6c08752964566d/web/src/assets/css/fonts/fontawesome-webfont.eot
--------------------------------------------------------------------------------
/web/src/assets/css/fonts/fontawesome-webfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paschmann/rasa-ui/3f5deadb92a4392838b647e95d6c08752964566d/web/src/assets/css/fonts/fontawesome-webfont.ttf
--------------------------------------------------------------------------------
/web/src/assets/css/fonts/fontawesome-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paschmann/rasa-ui/3f5deadb92a4392838b647e95d6c08752964566d/web/src/assets/css/fonts/fontawesome-webfont.woff
--------------------------------------------------------------------------------
/web/src/assets/css/fonts/fontawesome-webfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paschmann/rasa-ui/3f5deadb92a4392838b647e95d6c08752964566d/web/src/assets/css/fonts/fontawesome-webfont.woff2
--------------------------------------------------------------------------------
/web/src/assets/css/style.css:
--------------------------------------------------------------------------------
1 | .list-group-item.active {
2 | background-color: #EEE;
3 | border-color: #20a8d8;
4 | color: #151b1e
5 | }
6 |
7 | .app-header.navbar .navbar-brand {
8 | background-image: url("../img/logo.png");
9 | }
10 |
11 | canvas.chart {
12 | display: inline-block!important;
13 | }
14 |
15 | .callout {
16 | border-left-width: 0;
17 | }
18 |
19 | .header-buttons {
20 | color: #999;
21 | }
22 |
23 | .sidebar-toggler {
24 | left: inherit !important;
25 | right: 0px;
26 | }
27 |
28 | .aside-menu {
29 | width: 350px;
30 | }
31 |
32 | .datainput {
33 | width: 100%;
34 | height: 250px;
35 | color: #3e515b;
36 | }
37 |
38 | textarea {
39 | border: 1px solid #c2cfd6;
40 | }
41 |
42 | .dimmed {
43 | position: relative;
44 | }
45 |
46 | .dimmed:after {
47 | content: " ";
48 | z-index: 10;
49 | display: block;
50 | position: absolute;
51 | height: 100%;
52 | top: 0;
53 | left: 0;
54 | right: 0;
55 | background: rgba(0, 0, 0, 0.2);
56 | }
57 |
58 | @media (max-width: 991px) {
59 | .aside-menu {
60 | margin-right: 0px;
61 | width: 250px;
62 | }
63 | .aside-menu-fixed .main, .aside-menu-fixed .app-footer {
64 | margin-right: 250px !important;
65 | }
66 | }
67 |
68 | .aside-menu-hidden .aside-menu {
69 | margin-right: -350px;
70 | }
71 |
72 | .aside-menu-fixed .main, .aside-menu-fixed .app-footer {
73 | margin-right: 350px;
74 | }
75 |
76 | .app-header.navbar .nav-item .nav-link, .app-header.navbar .nav-item .dropdown-toggle {
77 | cursor: pointer;
78 | }
79 |
80 | .p-a-1 {
81 | padding: 1rem!important;
82 | }
83 |
84 | .m-b-0, .m-y-0 {
85 | margin-bottom: 0!important;
86 | }
87 |
88 | .m-t-h, .m-y-h {
89 | margin-top: .5rem!important;
90 | }
91 |
92 | .td-middle {
93 | vertical-align: middle !important;
94 | }
95 |
96 | .tag-success {
97 | background-color: #4dbd74;
98 | }
99 |
100 | .tag {
101 | display: inline-block;
102 | padding: .25em .4em;
103 | font-size: 75%;
104 | line-height: 1;
105 | color: #fff;
106 | text-align: center;
107 | vertical-align: baseline;
108 | }
109 |
110 | tags-input .tags .tag-item .remove-button {
111 | color: #fff;
112 | }
113 | .filtertext {
114 | border: 0;
115 | outline: 0;
116 | background: transparent;
117 | border-bottom: 1px solid black;
118 | margin-left: 20px;
119 | }
120 | .list-group-item:hover, a.list-group-item:focus {text-decoration: none;background-color: rgb(245, 245, 245);}
121 | .list-group { margin-bottom:0px; }
122 |
123 | .alert-div{
124 | position: fixed;
125 | z-index: 9999;
126 | right: 10px;
127 | top: 5px;
128 | }
129 | .alert-text{
130 | @media (max-width: 991px) {
131 | .sidebar-hidden .sidebar {
132 | margin-left: -200px;
133 | }
134 | }
135 | }
136 |
137 |
138 | .incoming_msg {
139 | overflow:hidden;
140 | margin:26px 0 26px;
141 | width: 100%
142 | }
143 |
144 | .received_msg {
145 | padding: 0 0 0 10px;
146 | float: left;
147 | max-width: 50%;
148 | }
149 |
150 | .received_withd_msg p {
151 | background: #ebebeb none repeat scroll 0 0;
152 | border-radius: 10px;
153 | color: #646464;
154 | font-size: 14px;
155 | margin: 0;
156 | padding: 5px 10px 5px 12px;
157 | width: 100%;
158 | }
159 |
160 | .time_date {
161 | text-align: left;
162 | color: #747474;
163 | display: block;
164 | font-size: 12px;
165 | margin: 8px 0 0;
166 | padding-left: 7px;
167 | padding-right: 7px;
168 | }
169 |
170 | .sent {
171 | text-align: right;
172 | }
173 |
174 | .sent_msg {
175 | float: right;
176 | max-width: 50%;
177 | }
178 |
179 | .sent_msg p {
180 | background: #20a8d8 none repeat scroll 0 0;
181 | border-radius: 10px;
182 | font-size: 14px;
183 | margin: 0; color:#fff;
184 | padding: 5px 10px 5px 12px;
185 | width:100%;
186 | text-align: right;
187 | }
188 |
189 | .outgoing_msg {
190 | overflow:hidden;
191 | margin:26px 0 26px;
192 | width: 100%
193 | }
194 |
195 |
196 | .input_msg_write input {
197 | border: medium;
198 | color: #4c4c4c;
199 | font-size: 15px;
200 | min-height: 48px;
201 | width: 100%;
202 | padding-left: 5px;
203 | }
204 |
205 | .type_msg {
206 | border: 1px solid #c4c4c4;
207 | position: relative;
208 | }
209 |
210 | .msg_btn {
211 | background: #20a8d8 none repeat scroll 0 0;
212 | border: medium none;
213 | border-radius: 50%;
214 | color: #fff;
215 | cursor: pointer;
216 | font-size: 17px;
217 | height: 33px;
218 | position: absolute;
219 | right: 5px;
220 | top: 8px;
221 | width: 33px;
222 | padding-top:5px;
223 | }
224 |
225 | .send {
226 | padding-right:8px;
227 | }
228 |
229 | .reset {
230 | bottom: 0px;
231 | }
232 |
233 | .msg_history {
234 | height: 800px;
235 | display: table-cell;
236 | vertical-align: bottom;
237 | width: 100%;
238 | overflow: auto;
239 | table-layout: fixed;
240 | }
241 |
242 | #chat {
243 | display: table;
244 | height: 800px;
245 | width: 100%;
246 | overflow: hidden;
247 | }
248 |
249 | .wrapper {
250 | max-height: 800px;
251 | overflow-y: scroll;
252 | }
253 |
254 | .action_msg {
255 | text-align: center;
256 | color: lightgray;
257 | }
--------------------------------------------------------------------------------
/web/src/assets/img/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paschmann/rasa-ui/3f5deadb92a4392838b647e95d6c08752964566d/web/src/assets/img/favicon.png
--------------------------------------------------------------------------------
/web/src/assets/img/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paschmann/rasa-ui/3f5deadb92a4392838b647e95d6c08752964566d/web/src/assets/img/logo.png
--------------------------------------------------------------------------------
/web/src/assets/img/screenshot1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paschmann/rasa-ui/3f5deadb92a4392838b647e95d6c08752964566d/web/src/assets/img/screenshot1.png
--------------------------------------------------------------------------------
/web/src/assets/img/screenshot1_small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paschmann/rasa-ui/3f5deadb92a4392838b647e95d6c08752964566d/web/src/assets/img/screenshot1_small.png
--------------------------------------------------------------------------------
/web/src/assets/img/screenshot2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paschmann/rasa-ui/3f5deadb92a4392838b647e95d6c08752964566d/web/src/assets/img/screenshot2.png
--------------------------------------------------------------------------------
/web/src/assets/img/screenshot2_small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paschmann/rasa-ui/3f5deadb92a4392838b647e95d6c08752964566d/web/src/assets/img/screenshot2_small.png
--------------------------------------------------------------------------------