-
Notifications
You must be signed in to change notification settings - Fork 32
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1266 from openedx/ammar/advance-analytics-plotly-…
…chart-components advance analytics plotly chart components
- Loading branch information
Showing
32 changed files
with
3,324 additions
and
5 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,239 @@ | ||
import React, { useState } from 'react'; | ||
import { | ||
Form, Tabs, Tab, | ||
} from '@openedx/paragon'; | ||
import { Helmet } from 'react-helmet'; | ||
|
||
import { FormattedMessage, useIntl } from '@edx/frontend-platform/i18n'; | ||
import Hero from '../Hero'; | ||
import Stats from './Stats'; | ||
import Enrollments from './tabs/Enrollments'; | ||
import Engagements from './tabs/Engagements'; | ||
import Completions from './tabs/Completions'; | ||
import Leaderboard from './tabs/Leaderboard'; | ||
import Skills from './tabs/Skills'; | ||
|
||
const PAGE_TITLE = 'AnalyticsV2'; | ||
|
||
const AnalyticsV2Page = () => { | ||
const [activeTab, setActiveTab] = useState('enrollments'); | ||
const [granularity, setGranularity] = useState('daily'); | ||
const [calculation, setCalculation] = useState('total'); | ||
const dataRefreshDate = ''; | ||
const intl = useIntl(); | ||
|
||
return ( | ||
<> | ||
<Helmet title={PAGE_TITLE} /> | ||
<Hero title={PAGE_TITLE} /> | ||
<div className="container-fluid w-100"> | ||
<div className="row data-refresh-msg-container mb-4"> | ||
<div className="col"> | ||
<span> | ||
<FormattedMessage | ||
id="advance.analytics.data.refresh.msg" | ||
defaultMessage="Data updated on {date}" | ||
description="Data refresh message" | ||
values={{ date: dataRefreshDate }} | ||
/> | ||
</span> | ||
</div> | ||
</div> | ||
|
||
<div className="row filter-container mb-4"> | ||
<div className="col"> | ||
<Form.Group> | ||
<Form.Label> | ||
<FormattedMessage | ||
id="advance.analytics.filter.start.date" | ||
defaultMessage="Start Date" | ||
description="Advance analytics Start date filter label" | ||
/> | ||
</Form.Label> | ||
<Form.Control | ||
type="date" | ||
/> | ||
</Form.Group> | ||
</div> | ||
<div className="col"> | ||
<Form.Group> | ||
<Form.Label> | ||
<FormattedMessage | ||
id="advance.analytics.filter.end.date" | ||
defaultMessage="End Date" | ||
description="Advance analytics End date filter label" | ||
/> | ||
</Form.Label> | ||
<Form.Control | ||
type="date" | ||
/> | ||
</Form.Group> | ||
</div> | ||
<div className="col"> | ||
<Form.Group> | ||
<Form.Label> | ||
<FormattedMessage | ||
id="advance.analytics.filter.date.granularity" | ||
defaultMessage="Date granularity" | ||
description="Advance analytics Date granularity filter label" | ||
/> | ||
</Form.Label> | ||
<Form.Control | ||
as="select" | ||
value={granularity} | ||
onChange={(e) => setGranularity(e.target.value)} | ||
> | ||
<option value="daily"> | ||
{intl.formatMessage({ | ||
id: 'advance.analytics.filter.granularity.option.daily', | ||
defaultMessage: 'Daily', | ||
description: 'Advance analytics granularity filter daily option', | ||
})} | ||
</option> | ||
<option value="weekly"> | ||
{intl.formatMessage({ | ||
id: 'advance.analytics.filter.granularity.option.weekly', | ||
defaultMessage: 'Weekly', | ||
description: 'Advance analytics granularity filter weekly option', | ||
})} | ||
</option> | ||
<option value="monthly"> | ||
{intl.formatMessage({ | ||
id: 'advance.analytics.filter.granularity.option.monthly', | ||
defaultMessage: 'Monthly', | ||
description: 'Advance analytics granularity filter monthly option', | ||
})} | ||
</option> | ||
<option value="quarterly"> | ||
{intl.formatMessage({ | ||
id: 'advance.analytics.filter.granularity.option.quarterly', | ||
defaultMessage: 'Quarterly', | ||
description: 'Advance analytics granularity filter quarterly option', | ||
})} | ||
</option> | ||
</Form.Control> | ||
</Form.Group> | ||
</div> | ||
<div className="col"> | ||
<Form.Group> | ||
<Form.Label> | ||
<FormattedMessage | ||
id="advance.analytics.filter.calculation" | ||
defaultMessage="Calculation" | ||
description="Advance analytics Calculation filter label" | ||
/> | ||
</Form.Label> | ||
<Form.Control | ||
as="select" | ||
value={calculation} | ||
onChange={(e) => setCalculation(e.target.value)} | ||
> | ||
<option value="total"> | ||
{intl.formatMessage({ | ||
id: 'advance.analytics.filter.calculation.option.total', | ||
defaultMessage: 'Total', | ||
description: 'Advance analytics calculation filter total option', | ||
})} | ||
</option> | ||
<option value="running_total"> | ||
{intl.formatMessage({ | ||
id: 'advance.analytics.filter.calculation.option.running.total', | ||
defaultMessage: 'Running Total', | ||
description: 'Advance analytics calculation filter running total option', | ||
})} | ||
</option> | ||
<option value="average_3"> | ||
{intl.formatMessage({ | ||
id: 'advance.analytics.filter.calculation.option.average.3', | ||
defaultMessage: 'Moving Average (3 Period)', | ||
description: 'Advance analytics calculation filter moving average 3 period option', | ||
})} | ||
</option> | ||
<option value="average_7"> | ||
{intl.formatMessage({ | ||
id: 'advance.analytics.filter.calculation.option.average.7', | ||
defaultMessage: 'Moving Average (7 Period)', | ||
description: 'Advance analytics calculation filter moving average 7 period option', | ||
})} | ||
</option> | ||
</Form.Control> | ||
</Form.Group> | ||
</div> | ||
</div> | ||
|
||
<div className="row stats-container mb-4"> | ||
<Stats | ||
enrollments={0} | ||
distinctCourses={0} | ||
dailySessions={0} | ||
learningHours={0} | ||
completions={0} | ||
/> | ||
</div> | ||
|
||
<div className="tabs-container"> | ||
<Tabs | ||
variant="tabs" | ||
activeKey={activeTab} | ||
onSelect={(tab) => { | ||
setActiveTab(tab); | ||
}} | ||
> | ||
<Tab | ||
eventKey="enrollments" | ||
title={intl.formatMessage({ | ||
id: 'advance.analytics.enrollment.tab.title', | ||
defaultMessage: 'Enrollments', | ||
description: 'Title for the enrollments tab in advance analytics.', | ||
})} | ||
> | ||
<Enrollments /> | ||
</Tab> | ||
<Tab | ||
eventKey="engagements" | ||
title={intl.formatMessage({ | ||
id: 'advance.analytics.engagement.tab.title', | ||
defaultMessage: 'Engagements', | ||
description: 'Title for the engagements tab in advance analytics.', | ||
})} | ||
> | ||
<Engagements /> | ||
</Tab> | ||
<Tab | ||
eventKey="completions" | ||
title={intl.formatMessage({ | ||
id: 'advance.analytics.completions.tab.title', | ||
defaultMessage: 'Completions', | ||
description: 'Title for the completions tab in advance analytics.', | ||
})} | ||
> | ||
<Completions /> | ||
</Tab> | ||
<Tab | ||
eventKey="leaderboard" | ||
title={intl.formatMessage({ | ||
id: 'advance.analytics.leaderboard.tab.title', | ||
defaultMessage: 'Leaderboard', | ||
description: 'Title for the leaderboard tab in advance analytics.', | ||
})} | ||
> | ||
<Leaderboard /> | ||
</Tab> | ||
<Tab | ||
eventKey="skills" | ||
title={intl.formatMessage({ | ||
id: 'advance.analytics.skills.tab.title', | ||
defaultMessage: 'Skills', | ||
description: 'Title for the skills tab in advance analytics.', | ||
})} | ||
> | ||
<Skills /> | ||
</Tab> | ||
</Tabs> | ||
</div> | ||
</div> | ||
</> | ||
); | ||
}; | ||
|
||
export default AnalyticsV2Page; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import React from 'react'; | ||
import PropTypes from 'prop-types'; | ||
|
||
const Header = ({ title, subtitle }) => ( | ||
<div className="analytics-header"> | ||
<h2 className="analytics-header-title">{title}</h2> | ||
{subtitle && <p className="analytics-header-subtitle">{subtitle}</p>} | ||
</div> | ||
); | ||
|
||
Header.defaultProps = { | ||
subtitle: undefined, | ||
}; | ||
|
||
Header.propTypes = { | ||
title: PropTypes.string.isRequired, | ||
subtitle: PropTypes.string, | ||
}; | ||
|
||
export default Header; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
import React from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import { FormattedMessage } from '@edx/frontend-platform/i18n'; | ||
|
||
const Stats = ({ | ||
enrollments, distinctCourses, dailySessions, learningHours, completions, | ||
}) => { | ||
const formatter = Intl.NumberFormat('en', { notation: 'compact', maximumFractionDigits: 2 }); | ||
|
||
return ( | ||
<div className="container-fluid analytics-stats"> | ||
<div className="row"> | ||
<div className="col d-flex flex-column justify-content-center align-items-center"> | ||
<p className="mb-0 small title-enrollments"> | ||
<FormattedMessage | ||
id="advance.analytics.stats.enrollments.title" | ||
defaultMessage="Enrollments" | ||
description="Title for the enrollments stat." | ||
/> | ||
</p> | ||
<p className="font-weight-bolder analytics-stat-number value-enrollments">{formatter.format(enrollments)}</p> | ||
</div> | ||
<div className="col d-flex flex-column justify-content-center align-items-center"> | ||
<p className="mb-0 small title-distinct-courses"> | ||
<FormattedMessage | ||
id="advance.analytics.stats.distinct.courses.title" | ||
defaultMessage="Distinct Courses" | ||
description="Title for the distinct courses stat." | ||
/> | ||
</p> | ||
<p className="font-weight-bolder analytics-stat-number value-distinct-courses">{formatter.format(distinctCourses)}</p> | ||
</div> | ||
<div className="col d-flex flex-column justify-content-center align-items-center"> | ||
<p className="mb-0 small title-daily-sessions"> | ||
<FormattedMessage | ||
id="advance.analytics.stats.daily.sessions.title" | ||
defaultMessage="Daily Sessions" | ||
description="Title for the daily sessions stat." | ||
/> | ||
</p> | ||
<p className="font-weight-bolder analytics-stat-number value-daily-sessions">{formatter.format(dailySessions)}</p> | ||
</div> | ||
<div className="col d-flex flex-column justify-content-center align-items-center"> | ||
<p className="mb-0 small title-learning-hours"> | ||
<FormattedMessage | ||
id="advance.analytics.stats.learning.hours.title" | ||
defaultMessage="Learning Hours" | ||
description="Title for the learning hours stat." | ||
/> | ||
</p> | ||
<p className="font-weight-bolder analytics-stat-number value-learning-hours">{formatter.format(learningHours)}</p> | ||
</div> | ||
<div className="col d-flex flex-column justify-content-center align-items-center"> | ||
<p className="mb-0 small title-completions"> | ||
<FormattedMessage | ||
id="advance.analytics.stats.completions.title" | ||
defaultMessage="Completions" | ||
description="Title for the completions stat." | ||
/> | ||
</p> | ||
<p className="font-weight-bolder analytics-stat-number value-completions">{formatter.format(completions)}</p> | ||
</div> | ||
</div> | ||
</div> | ||
); | ||
}; | ||
|
||
Stats.propTypes = { | ||
enrollments: PropTypes.number.isRequired, | ||
distinctCourses: PropTypes.number.isRequired, | ||
dailySessions: PropTypes.number.isRequired, | ||
learningHours: PropTypes.number.isRequired, | ||
completions: PropTypes.number.isRequired, | ||
}; | ||
|
||
export default Stats; |
Oops, something went wrong.