Implementing SUSI Linux App as a Finite State Machine

SUSI Linux app provides access to SUSI on Linux distributions on desktop as well as hardware devices like Raspberry Pi. It is a headless client that can be used to interact to SUSI via voice only. As more and more features like multiple hotword detection support and wake button support was added to SUSI Linux, the code became complex to understand and manage. A system was needed to model the app after. Finite State Machine is a perfect approach for such system. The Wikipedia definition of State Machine is “It is an abstract machine that can be in exactly one of a finite number of states at any given time. The FSM can change from one state to another in response to some external inputs; the change from one state to another is called a transition.” This means that if you can model your app into a finite number of states, you may consider using the State Machine implementation. State Machine implementation has following advantages: Better control over the working of the app. Improved Error handling by making an Error State to handle errors. States work independently which helps to modularize code in a better form. To begin with, we declare an abstract State class. This class declares all the common properties of a state and transition method. from abc import ABC, abstractclassmethod import logging class State(ABC): def __init__(self, components): self.components = components self.allowedStateTransitions = {} @abstractclassmethod def on_enter(self, payload=None): pass @abstractclassmethod def on_exit(self): pass def transition(self, state, payload=None): if not self.__can_transition(state): logging.warning("Invalid transition to State{0}".format(state)) return self.on_exit() state.on_enter(payload) def __can_transition(self, state): return state in self.allowedStateTransitions.values() We declared the on_enter() and on_exit() abstract method. These methods are executed on the entering and exiting a state respectively. The task designated for the state can be performed in the on_enter() method and it can free up resources or stop listening to callbacks in the on_exit() method. The transition method is to transition between one state to another. In a state machine, a state can transition to one of the allowed states only. Thus, we check if the transition is allowed or not before continuing it. The on_enter() and transition() methods additionally accepts a payload argument. This can be used to transfer some data to the state from the previous state. We also added the components property to the State. Components store the shared components that can be used across all the State and are needed to be initialized only once. We create a component class declaring all the components that are needed to be used by states. class Components: def __init__(self): recognizer = Recognizer() recognizer.dynamic_energy_threshold = False recognizer.energy_threshold = 1000 self.recognizer = recognizer self.microphone = Microphone() self.susi = susi self.config = json_config.connect('config.json') if self.config['hotword_engine'] == 'Snowboy': from main.hotword_engine import SnowboyDetector self.hotword_detector = SnowboyDetector() else: from main.hotword_engine import PocketSphinxDetector self.hotword_detector = PocketSphinxDetector() if self.config['wake_button'] == 'enabled': if self.config['device'] == 'RaspberryPi': from ..hardware_components import RaspberryPiWakeButton self.wake_button = RaspberryPiWakeButton() else: self.wake_button = None else: self.wake_button = None Now, we list out all the states that…

Continue ReadingImplementing SUSI Linux App as a Finite State Machine

Enhanced Skill Tiles in SUSI Skill CMS

The SUSI Skill Wiki is a management system for all the SUSI Skills and the Skill display screen ought to look attractive. The earlier version of the Skill Display was just a display with the skill name populated as cards as shown in the image. So as we progressed over to add more metadata to the SUSI Skills, we had the challenge to show all details which were as follows - An example of a skill metadata format- "cricketTest": { "image": "images/images.jpg", "author_url": "skill.susi.ai", "examples": ["Testing Works"], "developer_privacy_policy": "na", "author": "cms", "skill_name": "cricket", "dynamic_content": true, "terms_of_use": "na", "descriptions": "testing", "skill_rating": null } To embed the Skill metadata in the Tiles the following steps are to be followed - We first use the end point at the SUSI Server, http://api.susi.ai/cms/getSkillList.json with the following attributes - model - The skill follows a general model or maybe a tutorial model group -The category or group of the skill. language - The language of the skill output. 2.  An AJAX request to this end point gives us the following response. { accepted: true, model: "general", group: "Knowledge", language: "en", skills: { capital: { image: "images/capital.png", author_url: "https://github.com/chashmeetsingh", examples: [ "capital of Bangladesh" ], developer_privacy_policy: null, author: "chashmeet singh", skill_name: "capital", dynamic_content: true, terms_of_use: null, descriptions: "a skill to tell user about capital of any country.", skill_rating: { negative: "0", positive: "1" } } We use the descriptions, skill_name, examples, image from the skill metadata to create our Skill Tile. The styles of the cards follow a CSS flexbox structure. A sample mock up of the Skill Card looks as follows. We first handle all the base cases and show “No name available”, “No description available” for data which does not exist or is found to be “null”. We then create the card mock-up in ReactJS which looks somewhat like this code snippet in the file BrowseSkill.js <Card style={styles.row} key={el}> <div style={styles.right} key={el}> {image ? <div style={styles.imageContainer}> <img alt={skill_name} src={image} style={styles.image}/> </div>: <CircleImage name={el} size="48"/>} <div style={styles.titleStyle}>"{examples}"</div> </div> <div style={styles.details}> <h3 style={styles.name}>{skill_name}</h3> <p style={styles.description}>{description}</p> </div> </Card> We then add the following styles to the Card and its contents which complete the look of the View. imageContainer:{ position: 'relative', height: '80px', width: '80px', verticalAlign: 'top' }, name:{ textAlign: 'left', fontSize: '15px', color: '#4285f4', margin: '4px 0' }, details:{ paddingLeft:'10px' }, image:{ maxWidth: '100%', border: 0 }, description:{ textAlign:'left', fontSize: '14px' }, row: { width: 280, minHeight:'200px', margin:"10px", overflow:'hidden', justifyContent: "center", fontSize: '10px', textAlign: 'center', display: 'inline-block', background: '#f2f2f2', borderRadius: '5px', backgroundColor: '#f4f6f6', border: '1px solid #eaeded', padding: '4px', alignSelf:'flex-start' }, titleStyle:{ textAlign: 'left', fontStyle: 'italic', fontSize: '16px', textOverflow: 'ellipsis', overflow: 'hidden', width: '138px', marginLeft: '15px', verticalAlign: 'middle', display: 'block' } To see the SUSI Skills or to contribute to it, please visit http://skills.susi.ai Resources Material UI - http://material-ui.com CSS Flexbox Guide - https://css-tricks.com/snippets/css/a-guide-to-flexbox/

Continue ReadingEnhanced Skill Tiles in SUSI Skill CMS

Adding Fallback Images in SUSI.AI Skill CMS

SUSI.AI Skill CMS shows image of a every skill. Here we are going to talk about a special case, where we handle the case when image is not found. We will be discussing the author's skill component(all the skills by an author) and how we added fallback image in order to handle all the cases. For displaying image in table displaying all skills of author, we provide the path of image in SUSI Skill Data repository. The path is provided as follows : let image = 'https://raw.githubusercontent.com/fossasia/susi_skill_data/master/models/general/'+ parse[6]+'/'+parse[7]+'/images/'+parse[8].split('.')[0]; Explanation: parse is the array which contains the models, language ISO code, and the name of the skill. This is obtained after parsing JSON from this endpoint : "http://api.susi.ai/cms/getSkillsByAuthor.json?author=" + author; parse[6]: This represents a model of the skill. There are currently six models Assistants, Entertainment, Knowledge, Problem Solving, Shopping and Small Talks. parse[7]: This represents ISO language code of the skill. parse[8]: This represents the name of the skill. Now the image variable just needs the file extension. We have .jpg and .png extensions in images in our skill data repository. So we made two images : let image1 = image + '.png'; let image2 = image + '.jpg'; The img tag only takes one attribute in src and we can only add a string in alt tag. Now we needed to check which image exists and add proper src. This can be solved by following methods: We can use Jquery to solve this: $.get(image_url) .done(function() { // image exists }).fail(function() { // Image doesn't exist }) This will result in more code and and also this does not handles the case where no image is found and we need to show the Circle Image component which takes first two letters of skill and make a circular component. After researching the internet we found a perfect solution to our problem. There is an npm package named react-image, which is an alternative to default img tag. Features of react-image package helpful to us are: We can provide multiple fallback images in an array as source which will be used in order of index of array. This feature solves our problem of extensions, we add provide image with all extensions. We can show a fallback element in case no images are loaded. This solves our second problem where we needed to show Circle Image component. Code looks like this: <Img style={imageStyle} src={[ image1, image2 ]} unloader={<CircleImage name={name} size="40"/>} /> Resources: React-image npm package: https://www.npmjs.com/package/react-image Code for implementation: https://github.com/fossasia/susi_skill_cms/tree/master/src/components/AuthorSkills Code for Circle Image component: https://github.com/fossasia/susi_skill_cms/tree/master/src/components/CircleImage

Continue ReadingAdding Fallback Images in SUSI.AI Skill CMS

Displaying Blog Posts on SUSI AI Web Chat’s Blog Page and Share Posts

FOSSASIA is maintaining a superior blog and it contains blog posts about projects and programs run by FOSSASIA. While we were implementing SUSI Web Chat Application we got a requirement to implement a blog page. Speciality of this blog page is it is not a separate blog page, it fetches blog posts and other related data by filtering the FOSSASIA’s main blog. In this blog post I’ll discuss how we fetched and managed those data on front-end and how we made the appearance same as the FOSSASIA main blog. First we get blog posts as a JSON. For that we used rss2json API. we can get the RSS feed as a JSON by sending our RSS feed URL to the rss2json API. Check the rss2json API documentation here. It produces all posts as items array. Next we store this array of responses in our application as a state. This response contains blog post titles featured images’ details and post content and other metadata such as tags, author name and published date. We had few requirements to fulfill. First one is to show full content of the blogpost in a new blog page. We can take the full content from response like this, this.state.posts.slice(this.state.startPage, this.state.startPage + 10).map((posts, i) => { let content = posts.content; }) We can use “cintent” variable to show content but it contains the featured image. We have to skip that image. For that, let htmlContent = content.replace(/<img.*?>/, ''); Now we have to render this string value as HTML. For that we have to install “test-to-html” package using below command. npm install html-to-text --save Now we can convert text into html like this htmlContent = renderHTML(htmlContent); We used this HTML content inside the “CardText” tag. <CardText> {htmlContent} </CardText> At the bottom of the post we needed to show author name, tags list and categories list. Since tags and categories come in one array, we have to separate them. First we defined an array which contains all the categories in Fossasia blog. Then we compared that array with the categories we got like this. const allCategories = ['FOSSASIA','GSoC','SUSI.AI'] Compare two arrays, posts.categories.map((cat) => { let k = 0; for (k = 0; k < allCategories.length; k++) { if (cat === allCategories[k]) { category.push(cat); } } }); we defined this “arrDiff” simple function to get the difference of two arrays. var tags=arrDiff(category,posts.categories) Make the list of categories let fCategory=category.map((cat) => <span key={cat} ><a className="tagname" href={'.//category/' + cat.replace(/\s+/g, '-').toLowerCase()} rel="noopener noreferrer">{cat}</a></span> ); We can use above step to make tags list. Then after used it in the “CardActions” <span className='categoryContainer'> <i className="fa fa-folder-open-o tagIcon"></i> {fCategory} </span>   According to the final requirement we needed to add social media share buttons for Facebook and Twitter. If we need to make a twitter share button we have to follow up this method. But we can use “react-share” npm package to make these kind of share buttons. This is how we made Facebook and Twitter share buttons. First of all we have to install…

Continue ReadingDisplaying Blog Posts on SUSI AI Web Chat’s Blog Page and Share Posts

Sorting Users and Implementing Animations on SUSI Web Chat Team Page

While we were developing the chat application, we wanted to show details of Developers.  So we planned to build a team page for SUSI Web Chat Application. In this post I discuss few things we built there. Like sorting feature, animations of the page, usage of Material UI. First we made an array of objects to store user details. In that array we grouped them in sub arrays so we can refer them in different sections separately. We stored following data in “TeamList.js” in an array. var team = [{ 'mentors': [{ 'name': 'Mario Behling', 'github': 'http://github.com/mariobehling', 'avatar': 'http://fossasia.org/img/mariobehling.jpg', 'twitter': 'https://twitter.com/mariobehling', 'linkedin': 'https://www.linkedin.com/in/mariobehling/', 'blog': '#' }] },{ 'server': [{ }] } There was a requirement to sort developers by their name so we had to build a way to sort out array data which are in main array. This is how we built that. The function we are going to use for sorting. function compare(a, b) { if (a.name < b.name) { return -1; } if (a.name > b.name) { return 1; } return 0; } This is how we have used it to sort developers. import team from './TeamList'; team[1].server.sort(compare); In this function we took values of object two by two and compared. Now we have to show these sorted information on view. Extract data that we want from array and we used material UI Cards to show these data on view. This is how we extracted data from the array. team[1].server.sort(compare); let server = team[1].server.map((serv, i) => { return ( <Card className='team-card' key={i}> <CardMedia className="container" > <img src={serv.avatar} alt={serv.name} className="image" /> <div className="overlay" > <div className="text"> <FourButtons member={serv} /> </div> </div> </CardMedia> <CardTitle title={serv.name} subtitle={serv.designation} /> </Card>) }) Now it shows data on the view. “” contains an image of the member. We need to show social media links of the user on mouseover. We did that using simple CSS. I added a block comment around those particular styles. Check those styles here. .overlay { position: absolute; bottom: 100%; left: 0; right: 0; background-color: #000; overflow: hidden; width: 100%; height:0; transition: .3s ease; opacity:0; } .container:hover .overlay { bottom: 0; height: 100%; opacity:0.7; } Above lines show that how we made the animation of the overlay animation. Now we want to show social media buttons on the overlay. We made another separate component for buttons and return those like this. render() { let member= this.props.member; return (<div> <CardActions> <IconButton href={member.github} target="_blank" > <CardActions> </div>)} Finally we showed those data on Team page. We returned these JSX from render(){} method. <div className="team-header"> <div className="support__heading">Developers</div> </div> <div className='team-container'>{server}</div> I have mentioned few resources which I used to implement these features. If you are willing to contribute SUSI AI Web Chat application. Fork our repository on github. Resources Documentation of Array.sort https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort How to use Image overlay CSS effects: https://www.w3schools.com/howto/howto_css_image_overlay.asp

Continue ReadingSorting Users and Implementing Animations on SUSI Web Chat Team Page

Preparing for Automatic Publishing of Android Apps in Play Store

I spent this week searching through libraries and services which provide a way to publish built apks directly through API so that the repositories for Android apps can trigger publishing automatically after each push on master branch. The projects to be auto-deployed are: Open Event Orga App Open Event Android PSLab Android Loklak Wok Android Phimpe Android SUSI Android I had eyes on fastlane for a couple of months and it came out to be the best solution for the task. The tool not only allows publishing of APK files, but also Play Store listings, screenshots, and changelogs. And that is only a subset of its capabilities bundled in a subservice supply. There is a process before getting started to use this service, which I will go through step by step in this blog. The process is also outlined in the README of the supply project. Enabling API Access The first step in the process is to enable API access in your Play Store Developer account if you haven’t done so. For that, you have to open the Play Dev Console and go to Settings > Developer Account > API access. If this is the first time you are opening it, you’ll be presented with a confirmation dialog detailing about the ramifications of the action and if you agree to do so. Read carefully about the terms and click accept if you agree with them. Once you do, you’ll be presented with a setting panel like this: Creating Service Account As you can see there is no registered service account here and we need to create one. So, click on CREATE SERVICE ACCOUNT button and this dialog will pop up giving you the instructions on how to do so: So, open the highlighted link in the new tab and Google API Console will open up, which will look something like this: Click on Create Service Account and fill in these details: Account Name: Any name you want Role: Project > Service Account Actor And then, select Furnish a new private key and select JSON. Click CREATE. A new JSON key will be created and downloaded on your device. Keep this secret as anyone with access to it can at least change play store listings of your apps if not upload new apps in place of existing ones (as they are protected by signing keys). Granting Access Now return to the Play Console tab (we were there in Figure 2 at the start of Creating Service Account), and click done as you have created the Service Account now. And you should see the created service account listed like this: Now click on grant access, choose Release Manager from Role dropdown, and select these PERMISSIONS: Of course you don’t want the fastlane API to access financial data or manage orders. Other than that it is up to you on what to allow or disallow. Same choice with expiry date as we have left it to never expire. Click on ADD USER and…

Continue ReadingPreparing for Automatic Publishing of Android Apps in Play Store

Generating Map Action Responses in SUSI AI

SUSI AI responds to location related user queries with a Map action response. The different types of responses are referred to as actions which tell the client how to render the answer. One such action type is the Map action type. The map action contains latitude, longitude and zoom values telling the client to correspondingly render a map with the given location. Let us visit SUSI Web Chat and try it out. Query: Where is London Response: (API Response) The API Response actions contain text describing the specified location, an anchor with text ‘Here is a map` linked to openstreetmaps and a map with the location coordinates. Let us look at how this is implemented on server. For location related queries, the key where is used as an identifier. Once the query is matched with this key, a regular expression `where is (?:(?:a )*)(.*)` is used to parse the location name. "keys"   : ["where"], "phrases": [ {"type":"regex", "expression":"where is (?:(?:a )*)(.*)"}, ] The parsed location name is stored in $1$ and is used to make API calls to fetch information about the place and its location. Console process is used to fetch required data from an API. "process": [ { "type":"console", "expression":"SELECT location[0] AS lon, location[1] AS lat FROM locations WHERE query='$1$';"}, { "type":"console", "expression":"SELECT object AS locationInfo FROM location-info WHERE query='$1$';"} ], Here, we need to make two API calls : For getting information about the place For getting the location coordinates First let us look at how a Console Process works. In a console process we provide the URL needed to fetch data from, the query parameter needed to be passed to the URL and the path to look for the answer in the API response. url = <url>   - the url to the remote json service which will be used to retrieve information. It must contain a $query$ string. test = <parameter> - the parameter that will replace the $query$ string inside the given url. It is required to test the service. For getting the information about the place, we used Wikipedia API. We name this console process as location-info and added the required attributes to run it and fetch data from the API. "location-info": { "example":"http://127.0.0.1:4000/susi/console.json?q=%22SELECT%20*%20FROM%20location-info%20WHERE%20query=%27london%27;%22", "url":"https://en.wikipedia.org/w/api.php?action=opensearch&limit=1&format=json&search=", "test":"london", "parser":"json", "path":"$.[2]", "license":"Copyright by Wikipedia, https://wikimediafoundation.org/wiki/Terms_of_Use/en" } The attributes used are : url : The Media WIKI API endpoint test : The Location name which will be appended to the url before making the API call. parser : Specifies the response type for parsing the answer path : Points to the location in the response where the required answer is present The API endpoint called is of the following format : https://en.wikipedia.org/w/api.php?action=opensearch&limit=1&format=json&search=LOCATION_NAME For the query where is london, the API call made returns [ "london", ["London"], ["London  is the capital and most populous city of England and the United Kingdom."], ["https://en.wikipedia.org/wiki/London"] ] The path $.[2] points to the third element of the array i.e "London  is the capital and most populous city of England and the United Kingdom.” which…

Continue ReadingGenerating Map Action Responses in SUSI AI

Adding Push Wake Button to SUSI on Raspberry PI

SUSI Linux for Raspberry Pi provides the ability to call SUSI with the help of a Hotword ‘Susi’. Calling via Hotword is a natural way of interaction but it is even handier to invoke SUSI listening mode with the help of a Push button. It enables to call SUSI in a noisy environment where detection of Hotword is not that accurate. To enable Push Wake button is Susi, we need access to Hardware Pins. Devices like Raspberry PI provides GPIO (General Purpose Input Output) Pins for interacting with Hardware Devices. In this tutorial, we are adding support for Push Wake Button in Raspberry PI, though similar procedure can be extended to add Wake Button to Orange Pi, Beaglebone Black, and other devices. For adding push wake button, we require: Tactile Push Button Male to Female Jumper wires Breadboard Raspberry Pi We now need to do wiring to connect button to Raspberry Pi. The button can be connected to Raspberry Pi following the connection diagram.  After this, we need to install the Raspberry Pi GPIO Python Library. Install it using: $ pip3 install RPi.GPIO Now, we may detect the press of the button in our code. We declare an abstract class for implementing Wake Button. In this way, we can later extend our code to include Wake Buttons for more platforms. import os from abc import ABC, abstractclassmethod from queue import Queue from threading import Thread from utils.susi_config import config class WakeButton(ABC, Thread): def __init__(self, detection_callback, callback_queue: Queue): super().__init__() self.detection_callback = detection_callback self.callback_queue = callback_queue self.is_active = False @abstractclassmethod def run(self): pass def on_detected(self): if self.is_active: self.callback_queue.put(self.detection_callback) os.system('play {0} &'.format(config['detection_bell_sound'])) self.is_active = False We defined WakeButton class as a Thread. This is done to ensure that listening to Wake Buttons is done in background thread and it does not disturb the main thread. The callback to be executed on main thread after button press is detected is added to callback queue. Main Thread listens on the callback queue and executes any pending functions from other threads. We also play an Audio File additionally on detection of a button press to confirm the activation of detection to the user. Now, we define Raspberry Pi Wake Button class. This class extends from abstract WakeButton declared above. from queue import Queue import RPi.GPIO as GPIO import time from .wake_button import WakeButton class RaspberryPiWakeButton(WakeButton): def __init__(self, detection_callback, callback_queue: Queue): super().__init__(detection_callback, callback_queue) GPIO.setmode(GPIO.BCM) GPIO.setup(18, GPIO.IN, pull_up_down=GPIO.PUD_UP) def run(self): while True: input_state = GPIO.input(18) if not input_state: self.on_detected() self.is_active = False time.sleep(0.2) This class defines the Wake Button for Raspberry Pi. We continuously poll for the input value of GPIO Pin number 18 on which button is connected. If value is negative, it indicated that button was pressed. Now, we need to add an option if configuration script to give users a choice to enable or disable wake button. We first need to check, if device is Raspberry Pi, since feature is available on Raspberry PI only. To do this, we try to import RPi.GPIO module. If module…

Continue ReadingAdding Push Wake Button to SUSI on Raspberry PI

Getting skills by an author in SUSI.AI Skill CMS

The skill description page of any skill in SUSI.AI skill cms displays all the details regarding the skill. It displays image, description, examples and name of author. The skill made by author can impress the users and they might want to know more skills made by that particular author. We decided to display all the skills by an author. We needed an endpoint from server to get skills by author. This cannot be done on client side as that would result in multiple ajax calls to server for each skill of user. The endpoint used is : "http://api.susi.ai/cms/getSkillsByAuthor.json?author=" + author Here the author is the name of the author who published the particular skill. We make an ajax call to the server with the endpoint mentioned above and this is done when the user clicks the author. The ajax call response is as follows(example) : { 0: "/home/susi/susi_skill_data/models/general/Entertainment/en/creator_info.txt", 1: "/home/susi/susi_skill_data/models/general/Entertainment/en/flip_coin.txt", 2: "/home/susi/susi_skill_data/models/general/Assistants/en/websearch.txt", session: { identity: { type: "host", name: "139.5.254.154", anonymous: true } } } The response contains the list of skills made by author. We parse this response to get the required information. We decided to display a table containing name, category and language of the skill. We used map function on object keys to parse information from every key present in JSON response. Every value corresponding to a key represents a response of following type: "/home/susi/susi_skill_data/models/general/Category/language/name.txt" Explanation: Category: There are currently six categories Assistants, Entertainment, Knowledge, Problem Solving, Shopping and Small Talks. Each skill falls under a different category. language: This represents the ISO language code of the language in which skill is written. name: This is the name of the skill. We want these attributes from the string so we have used the split function: let parse = data[skill].split('/'); data is JSON response and skill is the key corresponding to which we are parsing information. We store the array returned by split function in variable parse. Now we return the following table in map function: return ( <TableRow> <TableRowColumn> <div> <Img style={imageStyle} src={[ image1, image2 ]} unloader={<CircleImage name={name} size="40"/>} /> {name} </div> </TableRowColumn> <TableRowColumn>{parse[6]}</TableRowColumn> <TableRowColumn>{isoConv(parse[7])}</TableRowColumn> </TableRow> ) Here : name: The name of skill converted into Title case by the following code : let name = parse[8].split('.')[0]; name = name.charAt(0).toUpperCase() + name.slice(1); parse[6]: This represents the category of the skill. isoConv(parse[7]): parse[7] is the ISO code of the language of skill and isoConv is an npm package used to get full form of the language from ISO code. CircleImage: This is a fallback option in case image at the URL is not found. This takes first two words from the name and makes a circular component. After successful execution of the code, we have the following looking table: Resources: Full code for implementation: https://github.com/fossasia/susi_skill_cms/tree/master/src/components/AuthorSkills isoConv npm package: https://www.npmjs.com/package/iso-language-converter Ajax’s guide on MDN: https://developer.mozilla.org/en-US/docs/AJAX/Getting_Started Split function in javascript: https://www.w3schools.com/jsref/jsref_split.asp Map function in javascript: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/map Material UI Table: http://www.material-ui.com/#/components/table

Continue ReadingGetting skills by an author in SUSI.AI Skill CMS

Implementation of React Routers in SUSI Web Chat

When we were developing the SUSI Web Chat application we wanted to implement set of static pages with the chat application. In the start we just wanted to navigate  through different static pages and move back to the web chat application. But it takes time to load a new page when user clicks on a link. Our goal was therefore to minimize the loading time by using lazy loading. For that we used react-route .It is standard library for react js. From the docs: “React Router keeps your UI synced with the URL. It has a simple API with powerful features like lazy code loading, dynamic route matching, and location transition handling built right in. Make the URL your first thought, not an after-thought.” (https://www.npmjs.com/package/react-router-plus) We need react-route to be installed in our application first. We can install it using NPM by running this command on project folder. npm install --save react-router-dom Next we have to set up our routes. We have two types of headers in our application. One is chat application header, second one is static page header. In static page header we have a navigation to switch between static pages. First we need to choose the router type because there are two types of routers in react. “” and “” we can use “” in our example because our server can handle dynamic requests. If we are requesting data from static page we should use “” . We used that in “” and made another new component called “” and used it on “index.js” like this. import { BrowserRouter as Router } from 'react-router-dom'; Import App from ‘.App’; ReactDOM.render( <IntlProvider locale={defaultPrefLanguage}> <Router> <App /> </Router> </IntlProvider>, document.getElementById('root') ); In “App.js” we can set up routes like this. <Switch> <Route exact path='/' component={ChatApp}/> <Route exact path="/overview" component={Overview} /> <Route exact path='/blog' component={Blog} /> <Route exact path="/logout" component={Logout} /> <Route exact path="/settings" component={Settings} /> <Route exact path="*" component={NotFound} /> </Switch> We use elements to render component when they match with the corresponding path. We use “path” to add router location that we need to match width the component. We use “exact” property to render the component if location exactly matches with the “path”. If we do not use “exact” property it renders when we have child routes after the path like “/blog/1 “ . We used “” element to group routes. We can’t use anchor () tags to navigate pages without reloading. We have to use tags instead of that. We have to replace all the places we have used <a href= ‘URL’>lable name </a> with this, <Link to=’URL’>Lable name</Link>    After doing above changes application will perform faster and it will load all page contents soon after you click the navigation links. If you would like to join with FOSSASIA and contribute to SUSI Web Chat Application please fork this repository on Github. Resources React Route v4 tutorial and other options: https://medium.com/@pshrmn/a-simple-react-router-v4-tutorial-7f23ff27adf React-router-dom node package https://www.npmjs.com/package/react-router-dom

Continue ReadingImplementation of React Routers in SUSI Web Chat