- );
- },
-});
-
-
-var secondsMap = {
- 'hour': 60 * 60,
- 'day': 24 * 60 * 60,
- 'week': 7 * 24 * 60 * 60,
- 'month': 30 * 24 * 60 * 60,
- 'year': 365 * 24 * 60 * 60,
-};
-
-
-// Builds the target chart from scratch. NVD3 surprisingly handles this well.
-// domTarget is the SVG element's parent and data is the info that will be graphed.
-var updateChart = function(domTarget, data, xAxisFormatter, yAxisFormatter, yAxisLabel, timezoneOffset, tooltipUnits) {
- // We pass in the timezone offset and calculate a locale offset. The former
- // is based on the UserProfile's specified timezone and the latter is the user's
- // computer's timezone offset. We manually shift the data to work around
- // d3's conversion into the user's computer's timezone. Note that for my laptop
- // in PST, the locale offset is positive (7hrs) while the UserProfile offset
- // is negative (-7hrs).
- var localeOffset = 60 * (new Date()).getTimezoneOffset();
- var shiftedData = [];
- for (var index in data) {
- var newSeries = { 'key': data[index]['key'] };
- var newValues = [];
- for (var series_index in data[index]['values']) {
- var newValue = [
- // Shift out of the locale offset to 'convert' to UTC and then shift
- // back into the operator's tz by adding the tz offset from the server.
- data[index]['values'][series_index][0] + 1e3 * localeOffset + 1e3 * timezoneOffset,
- data[index]['values'][series_index][1]
- ];
- newValues.push(newValue);
- }
- newSeries['values'] = newValues;
- shiftedData.push(newSeries);
- }
-
- nv.addGraph(function() {
- var chart = nv.models.lineChart()
- .x(function(d) { return d[0] })
- .y(function(d) { return d[1] })
- .color(d3.scale.category10().range())
- .interpolate('monotone')
- .showYAxis(true)
- ;
- chart.xAxis
- .tickFormat(function(d) {
- return d3.time.format(xAxisFormatter)(new Date(d));
- });
- // Fixes x-axis time alignment.
- chart.xScale(d3.time.scale.utc());
- chart.yAxis
- .axisLabel(yAxisLabel)
- .axisLabelDistance(25)
- .tickFormat(d3.format(yAxisFormatter));
- // Fixes the axis-labels being rendered out of the SVG element.
- chart.margin({right: 80});
- chart.tooltipContent(function(key, x, y) {
- return '
- );
- }
-});
-
-
-var TimeSeriesChartElement = React.createClass({
- // When the request params have changed, get new data and rebuild the graph.
- // We circumvent react's typical re-render cycle for this component by returning false.
- shouldComponentUpdate: function(nextProps) {
- var nextData = JSON.stringify(nextProps.data);
- var prevData = JSON.stringify(this.props.data);
- if (nextData !== prevData) {
- updateChart(
- '#' + this.props.chartID,
- nextProps.data['results'],
- nextProps.xAxisFormatter,
- nextProps.yAxisFormatter,
- nextProps.yAxisLabel,
- this.props.timezoneOffset,
- this.props.tooltipUnits
- );
- }
- return false;
- },
-
- render: function() {
- var inlineStyles = {
- height: this.props.chartHeight
- };
- return (
-
- );
- }
-});
-
-
-var RangeButton = React.createClass({
- propTypes: {
- buttonText: React.PropTypes.string.isRequired
- },
-
- getDefaultProps: function() {
- return {
- buttonText: 'day',
- activeButtonText: '',
- onButtonClick: null,
- }
- },
-
- render: function() {
- // Determine whether this particular button is active by checking
- // this button's text vs the owner's knowledge of the active button.
- // Then change styles accordingly.
- var inlineStyles = {
- marginRight: 20
- };
- if (this.props.buttonText == this.props.activeButtonText) {
- inlineStyles.cursor = 'inherit';
- inlineStyles.color = 'black';
- inlineStyles.textDecoration = 'none';
- } else {
- inlineStyles.cursor = 'pointer';
- }
- return (
-
- {this.props.buttonText}
-
- );
- },
-
- onThisClick: function(text) {
- this.props.onButtonClick(text);
- },
-});
-
-
-var LoadingText = React.createClass({
- getDefaultProps: function() {
- return {
- visible: false,
- }
- },
-
- render: function() {
- var inlineStyles = {
- display: this.props.visible ? 'inline' : 'none',
- marginRight: 20,
- };
-
- return (
-
- (loading..)
-
- );
- },
-});
-
-
-var DatePicker = React.createClass({
- getDefaultProps: function() {
- return {
- label: 'date',
- pickerID: 'some-datetimepicker-id',
- epochTime: 0,
- onDatePickerChange: null,
- datePickerOptions : {
- icons: {
- time: 'fa fa-clock-o',
- date: 'fa fa-calendar',
- up: 'fa fa-arrow-up',
- down: 'fa fa-arrow-down',
- previous: 'fa fa-arrow-left',
- next: 'fa fa-arrow-right',
- today: 'fa fa-circle-o',
- },
- showTodayButton: true,
- format: 'YYYY-MM-DD [at] h:mmA',
- },
- dateFormat: 'YYYY-MM-DD [at] h:mmA',
- }
- },
-
- componentDidMount: function() {
- var formattedDate = moment.unix(this.props.epochTime).format(this.props.dateFormat);
- var domTarget = '#' + this.props.pickerID;
- $(domTarget)
- .datetimepicker(this.props.datePickerOptions)
- .data('DateTimePicker')
- .date(formattedDate);
- var dateFormat = this.props.dateFormat;
- var handler = this.props.onDatePickerChange;
- $(domTarget).on('dp.change', function(event) {
- var newEpochTime = moment(event.target.value, dateFormat).unix();
- handler(newEpochTime);
- });
- },
-
- shouldComponentUpdate: function(nextProps) {
- var formattedDate = moment.unix(nextProps.epochTime).format(nextProps.dateFormat);
- var domTarget = '#' + nextProps.pickerID;
- $(domTarget).data('DateTimePicker').date(formattedDate);
- return false
- },
-
- render: function() {
- return (
-
-
-
-
- );
- },
-});
diff --git a/cloud/endagaweb/templates/dashboard/index.html b/cloud/endagaweb/templates/dashboard/index.html
index 417197b9..ae68e2d7 100644
--- a/cloud/endagaweb/templates/dashboard/index.html
+++ b/cloud/endagaweb/templates/dashboard/index.html
@@ -7,7 +7,7 @@
LICENSE file in the root directory of this source tree. An additional grant
of patent rights can be found in the PATENTS file in the same directory.
{% endcomment %}
-
+{% load guardian_tags %}
{% load apptags %}
@@ -15,26 +15,34 @@
{% block pagestyle %}
+
+
{% endblock %}
{% block content %}
+{% get_obj_perms request.user for network as 'user_permission' %}
+{% include "dashboard/report/header.html" with header='Call Sms & Data Usage' %}
-
-
-
Graphs
-
-
-{% if network_has_activity %}
+
+ {% include "dashboard/report/nav.html" with active_tab='Call_Sms_Data_Usage' %}
+
+ {% if 'view_graph' in user_permission %}
+ {% include "dashboard/report/csd-filter-action.html" with action_url='/dashboard' %}
+ {% if network_has_activity %}
@@ -42,8 +50,13 @@