Add Info on Skill Usage Distribution for all Skills by an Author in SUSI.AI

SUSI Skill CMS has a dashboard option available at the /dashboard route which displays several data for the logged in user as the skills created by the user and the ratings the user has provided to all the skills, since we have a skill usage section available on all skill pages which depicts the skill usage count for the past week in a line chart. Skill creators didn’t have a functionality to see the skill usage distribution on their skills which can provide some useful insight like how some of the skills they created are performing in comparison to the others so I developed a ‘My Analytics’ section in the dashboard page and displayed the skill usage distribution in the form of pie chart among the skills created by the logged in users.

About the API

An API is developed at the server so from the client we call this API to fetch data from the server and plug this data into the chart we wish to render.

Endpoint :

/cms/getSkillsByAuthor.json?author_email={email}

 

Parameters :

Email ID which is taken from the cookies since it is stored there once the user logs in.

Sample API call :

/cms/getSkillsByAuthor.json?author_email=anshu.av97@gmail.com

Fetching the data for the component

We first create a separate My Analytics component and require it in the dashboard and make an AJAX call to the appropriate endpoint inside a loadSkillsUsage function which is called inside the componentDidMount hook after which the server returns raw data in the form of JSON. We then pass the response into a saveUsageData function to parse the data for our use and save it to the application state.

loadSKillsUsage = () => {
 let url =
        urls.API_URL +
`/cms/getSkillsByAuthor.json?author_email=${cookies.get('emailId')}`;
 let self = this;
 $.ajax({
        url: url,
        dataType: 'jsonp',
        jsonp: 'callback',
        crossDomain: true,
        success: function(data) {
         self.saveUsageData(data.author_skills || []);
         ...
        },
        error: function(err) {
         ...
        },
 });
};

 

Set the application state with the received data which the pie chart component will use as it’s data source.

saveUsageData = data => {
 const skillUsage = data.map(skill => {
        let dataObject = {};
        dataObject.skill_name = skill.skill_name;
        dataObject.usage_count = skill.usage_count || 0;
        return dataObject;
 });
 this.setState({ skillUsage });
};

Implementing the UI

We create a separate ‘My Analytics’ component which is imported into the dashboard component to make the code cleaner and manageable. So inside the My analytics component, we fetch the data from the server as depicted above and after that, we render the pie chart component after importing from the recharts library.

Importing the pie chart components from the recharts library.

import { Legend, PieChart, Pie, Sector, Cell, ResponsiveContainer } from 'recharts';

 

Rendering the pie chart component while supplying appropriate props most important of which is the data prop which will be used in the chart and that data is available in the application state as saved earlier. We also have other styling props and a function which is triggered when hovering over cells of the pie chart to represent the data of the hovered cell. We also supply the appropriate nameKey and dataKey props as per the data format available in the state.

<ResponsiveContainer width={600} height={350}>
 <PieChart>
        <Pie
         activeIndex={this.state.activePieIndex}
         activeShape={renderActiveShape}
         data={this.state.skillUsage}
         cx={300}
         cy={175}
         innerRadius={80}
         nameKey="skill_name"
         dataKey="usage_count"
         outerRadius={120}
         fill="#8884d8"
         onMouseEnter={this.onPieEnter}
        >

       ...
         </Pie>
        <Legend wrapperStyle={{ position: 'relative' }} />
 </PieChart>
</ResponsiveContainer>

 

Configuring color for each Cell in the pie so it looks more interactive and we have distinguished colors for all devices.

{this.state.skillUsage.map((entry, index) => (
 <Cell
   key={index}
   fill={
     [
       '#0088FE',
       '#00C49F',
       '#FFBB28',
       '#FF8042',
       '#EA4335',
     ][index % 5]
   }
 />
))}

 

Rendering the Pie only when data is available in props so we don’t end up rendering a blank chart which obviously won’t look good.

{
 this.state.skillUsage !== [] ? (
   ...
 ): ''
}

Resources

Continue ReadingAdd Info on Skill Usage Distribution for all Skills by an Author in SUSI.AI

Implementing a device wise usage section on the skill page

SUSI Skill CMS showcases all the skills on the index page as skill cards and users can visit any skill page for any skill by clicking on any of these cards, skill pages for each skill hold some interesting metrics like rating, usage data, country wise usage data etc. But since SUSI runs on different devices so we need something to distribute and showcase how a skill is performing on each device so we implemented a pie chart for visualization of device wise usage data.

About the API

An API is developed at the server so from the client we call this API to fetch data from the server and plug this data into the chart we wish to render.

Endpoint :

/cms/getDeviceWiseSkillUsage.json

 

Parameters :

  • model
  • group
  • language
  • skill

Sample API call :

/cms/getDeviceWiseSkillUsage.json?model=general&group=Knowledge&language=en&skill=ceo

 

Response

{
 "skill_usage": [
   {
     "count": 3,
     "device_type": "Others"
   },
   {
     "count": 39,
     "device_type": "Android"
   },
   {
     "count": 1,
     "device_type": "Web Client"
   }
 ],
 "session": {"identity": {
   "type": "host",
   "name": "162.158.166.37_35449f1b",
   "anonymous": true
 }},
 "skill_name": "news",
 "accepted": true,
 "message": "Device wise skill usage fetched"
}

Fetching the data for the chart

Setting the URL to fetch data from, this URL will be used to make the AJAX call.

let deviceUsageUrl = `${urls.API_URL}/cms/getSkillsByAuthor.json?author_email=${cookies.get('emailId')}`;
deviceUsageUrl = deviceUsageUrl + '?model=' + modelValue + '&group=' + this.groupValue + '&language=' + this.languageValue + '&skill=' + this.name;

 

Make an ajax call to extract data from the response and call a function which saves the data to the application state, this data will later be used to render our chart we wish to render.

$.ajax({
 url: deviceUsageUrl,
 ...
 success: function(data) {
   if (data.skill_usage) {
     self.saveDeviceUsageData(data.skill_usage);
   }
 },
 error: function(e) {
   self.saveDeviceUsageData();
 },
});

 

Set the application state with the received data which the pie chart component will use as it’s data source.

saveDeviceUsageData = (device_usage_data = []) => {
 this.setState({
   device_usage_data,
 });
};

Implementing the UI

We already have a card component for device usage section so we append our device wise usage section to this already present card. We fetch the data in the skillListing component and pass that data as props to the skill usage component so using data from the received props we render our pie chart.

Importing the needed components from recharts library.

import { Tooltip, Legend, PieChart, Pie, Sector, Cell } from 'recharts';

 

Rendering the Piechart component with appropriate props, the data props is the most important which is taken from the application state which we saved earlier.

<PieChart width={600} height={350}>
 <Pie
   data={this.props.device_usage_data}
   nameKey="device_type"
   dataKey="count"
   onMouseEnter={this.onPieEnter}
   ...
 >
   ...
 </Pie>
 <Legend wrapperStyle={{ position: 'relative' }} />
</PieChart>

 

Configuring color for each Cell in the pie so it looks more interactive and we have distinguished colors for all devices.

{this.props.device_usage_data.map((entry, index) => (
 <Cell
   key={index}
   fill={
     [
       '#0088FE',
       '#00C49F',
       '#FFBB28',
       '#FF8042',
       '#EA4335',
     ][index % 5]
   }
 />
))}

 

Rendering the Pie only when data is available in props so we don’t end up rendering a blank chart which obviously won’t look good.

{
 this.props.device_usage_data !== [] ? (
   ...
 ): ''
}

 

Resources

  • Swizec Teller, Rendering a pie chart using react and d3, URL
  • Pie chart example from recharts, URL
Continue ReadingImplementing a device wise usage section on the skill page