diff --git a/app/controllers/api/v0/statistics_controller.rb b/app/controllers/api/v0/statistics_controller.rb index c533cd2..57c2e43 100644 --- a/app/controllers/api/v0/statistics_controller.rb +++ b/app/controllers/api/v0/statistics_controller.rb @@ -84,6 +84,47 @@ end end + # /api/v0/statistics/created_plans + # Returns the number of created plans within the user's org for the data start_date and end_date specified + def created_plans + raise Pundit::NotAuthorizedError unless Api::V0::StatisticsPolicy.new(@user, :statistics).plans? + + roles = Role.where("#{Role.creator_condition} OR #{Role.administrator_condition}") + + users = User.unscoped + if @user.can_super_admin? && params[:org_id].present? + users = users.where(org_id: params[:org_id]) + else + users = users.where(org_id: @user.org_id) + end + + plans = Plan.all + if params[:range_dates].present? + r = {} + params[:range_dates].each_pair do |k, v| + range_date_plans = plans + .where('plans.created_at >=?', v['start_date']) + .where('plans.created_at <=?', v['end_date']) + r[k] = roles.joins(:user, :plan).merge(users).merge(range_date_plans).select(:plan_id).distinct.count + end + respond_to do |format| + format.json { render(json: r.to_json) } + format.csv { + send_data(CSV.generate do |csv| + csv << [_('Month'), _('No. Plans')] + total = 0 + r.each_pair{ |k,v| csv << [k,v]; total+=v } + csv << [_('Total'), total] + end, filename: "#{_('plans')}.csv") } + end + else + plans = plans.where('plans.created_at >= ?', Date.parse(params[:start_date])) if params[:start_date].present? + plans = plans.where('plans.created_at <= ?', Date.parse(params[:end_date])) if params[:end_date].present? + count = roles.joins(:user, :plan).merge(users).merge(plans).select(:plan_id).distinct.count + render(json: { created_plans: count }) + end + end + ## # GET # @return the number of DMPs using the specified template between the optional specified dates diff --git a/app/views/usage/index.html.erb b/app/views/usage/index.html.erb index 122a71d..26ef8ef 100644 --- a/app/views/usage/index.html.erb +++ b/app/views/usage/index.html.erb @@ -16,7 +16,7 @@ <%= select_tag('topic', options_for_select( [ [_('Users'), 'users', { 'data-url': users_joined_api_v0_statistics_path }], - [_('Completed Plans'), 'completed_plans', { 'data-url': completed_plans_api_v0_statistics_path }] + [_('Plans'), 'plans', { 'data-url': created_plans_api_v0_statistics_path }] ]), class: 'form-control') %> @@ -62,7 +62,7 @@

<%= _('New users') %>

-

<%= _('Completed plans') %>

+

<%= _('Plans') %>

@@ -71,7 +71,7 @@

<%= _('Total users') %>

-

<%= _('Total completed plans') %>

+

<%= _('Total plans') %>

@@ -82,31 +82,30 @@
-
+
-

<%= _('No. users joined during last year') %>

+

<%= _('No. users joined during last year') %>

+ -
-
-
-
+
-

<%= _('No. completed plans during last year') %>

+

<%= _('No. plans during last year') %>

-
+
\ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index 6f7b3db..ee376eb 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -239,6 +239,7 @@ member do get :users_joined get :completed_plans + get :created_plans get :using_template get :plans_by_template get :plans diff --git a/lib/assets/javascripts/views/usage/index.js b/lib/assets/javascripts/views/usage/index.js index e3ef491..f60eb70 100644 --- a/lib/assets/javascripts/views/usage/index.js +++ b/lib/assets/javascripts/views/usage/index.js @@ -44,6 +44,11 @@ label: tooltipItem => `${tooltipItem.yLabel} ${appendTolabel}`, }, }, + scales: { + yAxes: [{ + ticks: { min: 0, suggestedMax: 50 }, + }], + }, }, }); }; @@ -62,26 +67,29 @@ url: topicToURL[topic], data: totals ? { topic, org_id: orgId } : target.serialize(), }); - $.when($.ajax(ajaxSettings()), $.ajax(ajaxSettings({ totals: true }))).then((r1, r2) => { - let dataRange; - let dataTotals; - if (topic === 'users') { - dataRange = r1[0].users_joined; - dataTotals = r2[0].users_joined; - } else if (topic === 'completed_plans') { - dataRange = r1[0].completed_plans; - dataTotals = r2[0].completed_plans; - } else { - dataRange = null; - dataTotals = null; - } - const dataTopics = $('[data-topics]'); - const views = $(`[data-topic="${topic}"]`); - dataRange !== null ? dataTopics.find('[data-range]').html(dataRange) : undefined; // eslint-disable-line no-unused-expressions - dataTotals !== null ? dataTopics.find('[data-totals]').html(dataTotals) : undefined; // eslint-disable-line no-unused-expressions - views.show(); - dataTopics.show(); - }); // TODO request error handling + // Awaits until both AJAX request responds. + // Note, the success handler is only executed if both AJAX requests return success + $.when($.ajax(ajaxSettings()), $.ajax(ajaxSettings({ totals: true }))).then( + (dataRangeSuccessCb, dataTotalsSuccessCb) => { + let dataRange = null; + let dataTotals = null; + if (dataRangeSuccessCb[0]) { // data is the first argument of the successCb ranges + const dataKeys = Object.keys(dataRangeSuccessCb[0]); + // We assume the dataRange is the first key of the object responded + dataRange = dataKeys.length > 0 ? dataRangeSuccessCb[0][dataKeys[0]] : null; + } + if (dataTotalsSuccessCb[0]) { // data is the first argument of the successCb for totals + const dataKeys = Object.keys(dataTotalsSuccessCb[0]); + // We assume the dataTotals is the first key of the object responded + dataTotals = dataKeys.length > 0 ? dataTotalsSuccessCb[0][dataKeys[0]] : null; + } + const dataTopics = $('[data-topics]'); + const views = $(`[data-topic="${topic}"]`); + dataRange !== null ? dataTopics.find('[data-range]').html(dataRange) : undefined; // eslint-disable-line no-unused-expressions + dataTotals !== null ? dataTopics.find('[data-totals]').html(dataTotals) : undefined; // eslint-disable-line no-unused-expressions + views.show(); + dataTopics.show(); + }); // TODO request error handling }); /* Click event associated to each Export button @@ -106,8 +114,16 @@ link.remove(); }); }); + const yearlySuccesHandler = ({ data, selector } = {}) => { + const keys = Object.keys(data); // Keys are Month-Year strings and values might be [0...N] + if (keys.findIndex(k => data[k] > 0) > -1) { + createChart({ selector, data }); + } else { + $(selector).prev().show(); + } + }; // Sends an AJAX request to our two current endpoints that generate yearly data - // (e.g. users_joined_api_v0_statistics_path, completed_plans_api_v0_statistics_path ) + // (e.g. users_joined_api_v0_statistics_path, created_plans_api_v0_statistics_path ) // and draws a barChart when success response is found const initialise = () => { // Only fire AJAX requests if topicToURL object has keys, i.e. topics mapping to URLs @@ -118,14 +134,14 @@ url: topicToURL.users, data: { range_dates: rangeDates }, }).then((data) => { - createChart({ selector: '#yearly_users', data, appendTolabel: 'users' }); + yearlySuccesHandler({ data, selector: '#yearly_users' }); }); // TODO request error handling $.ajax({ headers: { Authorization: `Token token="${apiToken}"` }, - url: topicToURL.completed_plans, + url: topicToURL.plans, data: { range_dates: rangeDates }, }).then((data) => { - createChart({ selector: '#yearly_plans', data, appendTolabel: 'completed plans' }); + yearlySuccesHandler({ data, selector: '#yearly_plans' }); }); // TODO request error handling } };