Individual skill usage subsections in SUSI Skill CMS

In SUSI.AI Skills CMS several interactive skill related statistics are displayed on the skill page for each skill which includes user ratings, ratings over time, user feedback and skill usage data displayed interactively. The skill usage section is further subdivided to get more insight into how the skill has been used and from where. Therefore we have three subsections which display Time wise skill usage, device wise usage, and country wise usage. All this data can help evaluate which devices are mostly using the skill or data like in which country the skill is more popular than others. So in this post, we mainly discuss the UI of how these sections are implemented.

Implementation

Adding a Card component to the skill page component at the bottom of the skill page component.

<SkillUsageCard
 skill_usage={this.state.skill_usage}
 device_usage_data={this.state.device_usage_data}
 countryWiseSkillUsage={this.state.countryWiseSkillUsage}
/>

 

In the render function of the newly made component, we import the Paper component from material-ui and render it at the top to contain the subsections to give it a card-like UI.

<div>
   <Paper className="margin-b-md margin-t-md">
           ...
   </Paper>
</div>

 

Create div for the time wise skill usage. Calculate total skill usage for displaying the total skill usage count and also it helps to decide whether we need to render the section or not. So if the total skill usage by time count is greater than zero then render the line chart for visual analysis and display the total skill usage count too.

let totalSkillUsage = 0;
if (this.props.skill_usage) {
 // eslint-disable-next-line
 totalSkillUsage = this.props.skill_usage.reduce((totalCount, day) => {
        if (day) {
         return totalCount + day.count;
        }
        return totalCount;
 }, 0);
}

<div className="time-chart">
 <div>
        <ResponsiveContainer width={this.state.width} height={300}>
         <LineChart
           ...
         >
           <XAxis dataKey="date" padding={{ right: 20 }} />
           <YAxis allowDecimals={false} />
           <Tooltip wrapperStyle={{ height: '60px' }} />
           <Legend />
           <Line
             ...
           />
         </LineChart>
        </ResponsiveContainer>
 </div>
</div>
<div className="total-hits">
 <div className="large-text">{totalSkillUsage}</div>
 Hits this week
</div>

 

Create div for the Device wise usage. Conditionally render it in case the device wise data is available in the props.

<div className="device-usage">
 <div className="sub-title">Device wise Usage</div>
 {this.props.device_usage_data &&
 this.props.device_usage_data.length ? (
        <div className="pie-chart">
         <ResponsiveContainer width={600} height={350}>
           <PieChart>
             <Pie
               ...
             >
               {this.props.device_usage_data.map((entry, index) => (
                 <Cell key={index} fill={entry.color} />
               ))}
             </Pie>
             <Legend wrapperStyle={{ position: 'relative' }} />
           </PieChart>
         </ResponsiveContainer>
        </div>
</div>

 

Create a div for the country wise usage. We get the country wise usage data from the props and then we plug in the data in the geo chart component and also display the data as a table on the side. In case no data comes in or is unavailable we do not render the component at all.

<div>
 {countryWiseSkillUsage && countryWiseSkillUsage.length ? (
        <div className="country-usage-container">
         <div className="country-usage-graph">
           <GeoChart data={countryWiseSkillUsage} />
         </div>
         <div className="country-usage-list">
           <Table>
             ...
         </div>
        </div>
 ) : (
        <div className="unavailable-message">
         Country wise usage distribution is not available.
        </div>
 )}
</div>

 

This is how the three subsection in the skill usage component are implemented

Resources

How to Store Mobile Settings in the Server from SUSI Web Chat Settings Page

While we are adding new features and capabilities to SUSI Web Chat application, we wanted to provide settings changing capability to SUSI users. SUSI team decided to maintain a settings page to give that capability to users.

This is how it’s interface looks like now.

In this blog post I’m going to add another setting category to our setting page. This one is for  saving mobile phone number and dial code in the server.

UI Development:

First we need to  add new category to settings page and it should be invisible when user is not logged in. Anonymous users should not get mobile phone category in settings page.

     let menuItems = cookies.get('loggedIn') ?
            <div>
                <div className="settings-list">
                    <Menu
                        onItemTouchTap={this.loadSettings}
                        selectedMenuItemStyle={blueThemeColor}
                        style={{ width: '100%' }}
                        value={this.state.selectedSetting}
                    >
                       <MenuItem value='Mobile' className="setting-item" leftIcon={<MobileIcon />}>Mobile<ChevronRight className="right-chevron" /></MenuItem>
                        <hr className="break-line" />
                    </Menu>
                </div>
            </div>

 

Next we have to show settings UI when user clicks on the category name.

 if (this.state.selectedSetting === 'Mobile' && cookies.get('loggedIn')) {}
                currentSetting = (
  <Translate text="Country/region : " />
                            <DropDownMenu maxHeight={300}
               value={this.state.countryCode?this.state.countryCode:'US'}

 

Show US if the state does not deines the country code

                                onChange={this.handleCountryChange}>
                                {countries}
                            </DropDownMenu>
<Translate text="Phone number : " />
                            <TextField name="selectedCountry"
                            disabled={true}
                            value={countryData.countries[this.state.countryCode?this.state.countryCode:'US'].countryCallingCodes[0] }
                         	/>
                            <TextField name="serverUrl"
                                onChange={this.handleTelephoneNoChange}
                                value={this.state.phoneNo }
 />
)}

 

Then we need to get list of country names and country dial codes to show in the above drop down. We used country-data node module for that.

To install country-data module use this  command.

npm install --save country-data

 

We have used it in the settings page as below.

import countryData from 'country-data';
    	countryData.countries.all.sort(function(a, b) {
            if(a.name < b.name){ return -1};
            if(a.name > b.name){ return 1};
            return 0;
        });
        let countries = countryData.countries.all.map((country, i) => {
         	return (<MenuItem value={countryData.countries.all[i].alpha2} key={i} primaryText={ countryData.countries.all[i].name+' '+ countryData.countries.all[i].countryCallingCodes[0] } />);
        });

 

First we sort the country data list from it’s name. After that we made a list of “”s from this list of data.
Then we have to check whether the user changed or added the phone number and region (dial code).
It handles by this function mentioned above. ( onChange={this.handleCountryChange}> and
onChange={this.handleTelephoneNoChange} )

    handleCountryChange = (event, index, value) => {
        this.setState({'countryCode': value });
    }

 

Then we have to get the phone number using below function.

    handleTelephoneNoChange = (event, value) => {
        this.setState({'phoneNo': value});
    }

 

Next we have to update the function that triggers when user clicks the save button.

    handleSubmit = () => {
        let newCountryCode = !this.state.countryCode?
        this.intialSettings.countryCode:this.state.countryCode;
        let newCountryDialCode = !this.state.countryDialCode?
        this.intialSettings.countryDialCode:this.state.countryDialCode;
        let newPhoneNo = this.state.phoneNo;
        let vals = {
            countryCode: newCountryCode,
            countryDialCode: newCountryDialCode,
            phoneNo: newPhoneNo
}
let settings = Object.assign({}, vals);
cookies.set('settings', settings);
 this.implementSettings(vals);
 }

 

This code snippet stores Country Code, Country Dial code and phone no in the server.
Now we have to update the Store. Here we are going to change UserPreferencesStore “UserPreferencesStore” .
First we have to setup default values for things we are going to store.

let _defaults = {
	  CountryCode: 'US',
   	  CountryDialCode: '+1',
   	  PhoneNo: ''
}

 

Finally we have to update the dispatchToken to change and get these new data

UserPreferencesStore.dispatchToken = ChatAppDispatcher.register(action => {
   switch (action.type) {
       case ActionTypes.SETTINGS_CHANGED: {
           let settings = action.settings;
           if(settings.hasOwnProperty('theme')){
                   _defaults.Theme = settings.theme;
           }
           if(settings.hasOwnProperty('countryDialCode')){
               _defaults.countryDialCode = settings.countryDialCode;
           }
           if(settings.hasOwnProperty('phoneNo')){
               _defaults.phoneNo = settings.phoneNo;
           }
           if(settings.hasOwnProperty('countryCode')){
               _defaults.countryCode = settings.countryCode;
           }
           UserPreferencesStore.emitChange();
           break;
}
}

 

Finally application is ready to store and update Mobile phone number and region code in the server.

Resources: