refinerycms-stats 0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,5 @@
1
+ module Admin
2
+ class StatsController < Admin::BaseController
3
+
4
+ end
5
+ end
@@ -0,0 +1,7 @@
1
+ class Stat < ActiveRecord::Base
2
+
3
+ acts_as_indexed :fields => [:bidon]
4
+
5
+ validates :bidon, :presence => true, :uniqueness => true
6
+
7
+ end
@@ -0,0 +1,93 @@
1
+ <% content_for :after_javascript_libraries do %>
2
+ <%= javascript_include_tag 'https://www.google.com/jsapi' %>
3
+ <%= javascript_include_tag 'refinerycms-stat' %>
4
+ <%= javascript_include_tag 'refinerycms-stat-translate' %>
5
+ <% end %>
6
+
7
+ <div id="login" style="visibility:hidden;">
8
+ <form action='#'>
9
+ <span id='status'><%= t('.login_analytics_html', :analytics_page_code => RefinerySetting.find_or_set(:analytics_page_code, "UA-0000000-0")) %></span>
10
+ <br/>
11
+ <input id='buttonLogin' type='button' value='<%= t(".button_login_text") %>'/>
12
+ </form>
13
+ </div>
14
+ <div id="logged" style="visibility:hidden;">
15
+ <%= t('.link_analytics_html') %>
16
+ <div id="tabs">
17
+ <ul>
18
+ <li><a href="#tabs-1"><%= t('.title_page_views') %></a></li>
19
+ <li><a href="#tabs-2"><%= t('.title_visits') %></a></li>
20
+ <li><a href="#tabs-3"><%= t('.title_visitors') %></a></li>
21
+ <li><a href="#tabs-4"><%= t('.title_average_time') %></a></li>
22
+ <li><a href="#tabs-5"><%= t('.title_source') %></a></li>
23
+ <li><a href="#tabs-6"><%= t('.title_keywords') %></a></li>
24
+ </ul>
25
+ <div id="page_part_editors">
26
+ <div id="tabs-1" class="stat">
27
+ <div id='pageViewsTableDiv'></div>
28
+ <div id='pageViewsColumnChartDiv' style="display:inline"></div>
29
+ <div id='pageViewsChartDiv' style="display:inline"></div>
30
+ </div>
31
+ <div id="tabs-2" class="stat">
32
+ <table>
33
+ <tr>
34
+ <td><div id='visitsTableDiv' style="display:inline"></div></td>
35
+ <td><div id='visitsLineChartDiv' style="display:inline"></div></td>
36
+ </tr>
37
+ </table>
38
+ </div>
39
+ <div id="tabs-3" class="stat">
40
+ <table>
41
+ <tr>
42
+ <td><div id='visitorsTableDiv' style="display:inline"></div></td>
43
+ <td><div id='visitorsLineChartDiv' style="display:inline"></div></td>
44
+ </tr>
45
+ </table>
46
+ </div>
47
+ <div id="tabs-4" class="stat">
48
+ <table>
49
+ <tr>
50
+ <td><div id='timesOnSiteTableDiv' style="display:inline"></div></td>
51
+ <td><div id='timesOnSiteLineChartDiv' style="display:inline"></div></td>
52
+ </tr>
53
+ </table>
54
+ </div>
55
+ <div id="tabs-5" class="stat">
56
+ <table>
57
+ <tr>
58
+ <td><div id='sourceTableDiv' style="display:inline"></div></td>
59
+ <td><div id='sourcePieChartDiv' style="display:inline"></div></td>
60
+ </tr>
61
+ </table>
62
+ </div>
63
+ <div id="tabs-6" class="stat">
64
+ <table>
65
+ <tr>
66
+ <td><div id='keywordTableDiv' style="display:inline"></div></td>
67
+ <td><div id='keywordPieChartDiv' style="display:inline"></div></td>
68
+ </tr>
69
+ </table>
70
+ </div>
71
+ </div>
72
+ <!-- For the API to work in IE, an image must be requested from the same
73
+ domain the script is hosted on. The image doesn't actually have
74
+ to exist, just be requested. More info here :
75
+ http://code.google.com/apis/gdata/client-js.html
76
+ -->
77
+ <img style='visibility:hidden' src='__utm.gif' alt='required for GData'/>
78
+ </div>
79
+
80
+ <% content_for :javascripts do %>
81
+ <script>
82
+ $(document).ready(function(){
83
+ $(function() {
84
+ $( "#tabs" ).tabs();
85
+ });
86
+ collectStatsData('<%= RefinerySetting.find_or_set(:analytics_page_code, "UA-0000000-0") %>');
87
+ });
88
+ </script>
89
+ <% end %>
90
+
91
+ <% content_for :stylesheets do %>
92
+ <%= stylesheet_link_tag 'stat' %>
93
+ <% end %>
@@ -0,0 +1,16 @@
1
+ en:
2
+ plugins:
3
+ stats:
4
+ title: Stats
5
+ admin:
6
+ stats:
7
+ index:
8
+ title_keywords: Keywords
9
+ title_page_views: Page views
10
+ title_source: Source
11
+ title_visitors: Visitors
12
+ title_visits: Visits
13
+ title_average_time: Average time
14
+ link_analytics_html: "You can view more data on the Google Analitycs site : <a href='https://www.google.com/analytics/'>https://www.google.com/analytics/</a><br/>."
15
+ login_analytics_html: "You need access to your Google Analytics data for this site.<br/>The code of your site for Google Analytics is : %{analytics_page_code}.<br/>You can change this code in <a href='/refinery/settings?search=analytics_page_code'>your settings</a>."
16
+ button_login_text: "Validate"
@@ -0,0 +1,16 @@
1
+ fr:
2
+ plugins:
3
+ stats:
4
+ title: Statistiques
5
+ admin:
6
+ stats:
7
+ index:
8
+ title_keywords: Mot clés
9
+ title_page_views: Pages Vues
10
+ title_source: Sources
11
+ title_visitors: Visiteurs
12
+ title_visits: Visites
13
+ title_average_time: Temps moyen
14
+ link_analytics_html: "Vous pouvez consulter plus de données sur le site de Google Analitycs : <a href='https://www.google.com/analytics/'>https://www.google.com/analytics/</a><br/>."
15
+ login_analytics_html: "Vous devez autoriser l'accés à vos données Google Analytics pour ce site.<br/>Le code de votre site pour Google Analytics est : %{analytics_page_code}.<br/>Vous pouvez modifier ce code dans <a href='/refinery/settings?search=analytics_page_code'>vos paramètres</a>."
16
+ button_login_text: "Valider"
@@ -0,0 +1,11 @@
1
+ ::Refinery::Application.routes.draw do
2
+ resources :stats, :only => [:index, :show]
3
+
4
+ scope(:path => 'refinery', :as => 'admin', :module => 'admin') do
5
+ resources :stats, :except => :show do
6
+ collection do
7
+ post :update_positions
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,6 @@
1
+ class RefinerycmsStats < Refinery::Generators::EngineInstaller
2
+
3
+ source_root File.expand_path('../../../', __FILE__)
4
+ engine_name "stats"
5
+
6
+ end
@@ -0,0 +1,20 @@
1
+ require 'refinerycms-base'
2
+
3
+ module Refinery
4
+ module Stats
5
+ class Engine < Rails::Engine
6
+ initializer "static assets" do |app|
7
+ app.middleware.insert_after ::ActionDispatch::Static, ::ActionDispatch::Static, "#{root}/public"
8
+ end
9
+
10
+ config.after_initialize do
11
+ Refinery::Plugin.register do |plugin|
12
+ plugin.name = "stats"
13
+ plugin.activity = {
14
+ :class => Stat
15
+ }
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,13 @@
1
+ namespace :refinery do
2
+
3
+ namespace :stats do
4
+
5
+ # call this task my running: rake refinery:stats:my_task
6
+ # desc "Description of my task below"
7
+ # task :my_task => :environment do
8
+ # # add your logic here
9
+ # end
10
+
11
+ end
12
+
13
+ end
@@ -0,0 +1,33 @@
1
+ var I18n = I18n || {};
2
+ I18n.translations = {
3
+ "en":{
4
+ "admin":{
5
+ "stats":{
6
+ "title":"Title",
7
+ "visits":"Visits",
8
+ "visitors":"Visitors",
9
+ "page_views": "Page Views",
10
+ "keywords": "Keywords",
11
+ "date": "Date",
12
+ "average_time": "Average time",
13
+ "source": "Source",
14
+ "path": "Path"
15
+ }
16
+ }
17
+ },
18
+ "fr":{
19
+ "admin":{
20
+ "stats":{
21
+ "title":"Titre",
22
+ "visits":"Visites",
23
+ "visitors":"Visiteurs",
24
+ "page_views": "Pages Vues",
25
+ "keywords": "Mots clés",
26
+ "date": "Date",
27
+ "average_time": "Temps moyen",
28
+ "source": "Source",
29
+ "path": "Chemin"
30
+ }
31
+ }
32
+ }
33
+ };
@@ -0,0 +1,446 @@
1
+ // Copyright 2009 Google Inc. All Rights Reserved.
2
+
3
+ /* Licensed under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License.
5
+ * You may obtain a copy of the License at
6
+ *
7
+ * http://www.apache.org/licenses/LICENSE-2.0
8
+ *
9
+ * Unless required by applicable law or agreed to in writing, software
10
+ * distributed under the License is distributed on an "AS IS" BASIS,
11
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ * See the License for the specific language governing permissions and
13
+ * limitations under the License.
14
+ */
15
+ /**
16
+ * @fileoverview A very simple demo showing how easy it is to visualize
17
+ * GA data in the Google Visualization API. In this demo we show the
18
+ * top 10 tracked pages tiles and page URIs by pageviews in a
19
+ * Gviz Table, Pie Chart and Column Chart.
20
+ */
21
+
22
+ var myService;
23
+ var dataTable;
24
+ var pageViewsTable;
25
+ var pageViewsChart;
26
+ var pageViewsColumnChart;
27
+ var visitsLineChart;
28
+ var visitsTable;
29
+ var timesOnSiteLineChart;
30
+ var timesOnSiteTable;
31
+ var sourcePieChart;
32
+ var sourceTable;
33
+ var keywordPieChart;
34
+ var keywordTable;
35
+ var scope = 'https://www.google.com/analytics/feeds';
36
+ var profileId;
37
+ var pageCode;
38
+
39
+ /**
40
+ * Initialize all the objects from the Google AJAX Apis once they
41
+ * have been loaded and are ready to use.
42
+ */
43
+ function collectStatsData(pageCodeArg) {
44
+ var divLogin = document.getElementById('login');
45
+ var divLogged = document.getElementById('logged');
46
+ divLogin.style.visibility = 'hidden';
47
+ divLogged.style.visibility = 'hidden';
48
+
49
+ if (google.accounts.user.checkLogin(scope)) {
50
+ divLogin.style.visibility = 'hidden';
51
+ divLogged.style.visibility = 'visible';
52
+ divLogged.style.position = 'relative';
53
+ divLogged.style.position = "relative";
54
+ divLogged.style.top = -divLogin.offsetHeight+"px";
55
+
56
+ pageCode = pageCodeArg;
57
+ myService = new google.gdata.analytics.AnalyticsService('gaExportAPI_gViz_v1.0');
58
+ pageViewsTable = new google.visualization.Table(document.getElementById('pageViewsTableDiv'));
59
+ pageViewsChart = new google.visualization.PieChart(document.getElementById('pageViewsChartDiv'));
60
+ pageViewsColumnChart = new google.visualization.ColumnChart(document.getElementById('pageViewsColumnChartDiv'));
61
+
62
+
63
+ sourcePieChart = new google.visualization.PieChart(document.getElementById('sourcePieChartDiv'));
64
+ sourceTable = new google.visualization.Table(document.getElementById('sourceTableDiv'));
65
+
66
+ keywordPieChart = new google.visualization.PieChart(document.getElementById('keywordPieChartDiv'));
67
+ keywordTable = new google.visualization.Table(document.getElementById('keywordTableDiv'));
68
+
69
+ visitsLineChart = new google.visualization.LineChart(document.getElementById('visitsLineChartDiv'));
70
+ visitsTable = new google.visualization.Table(document.getElementById('visitsTableDiv'));
71
+
72
+ visitorsLineChart = new google.visualization.LineChart(document.getElementById('visitorsLineChartDiv'));
73
+ visitorsTable = new google.visualization.Table(document.getElementById('visitorsTableDiv'));
74
+
75
+ timesOnSiteLineChart = new google.visualization.LineChart(document.getElementById('timesOnSiteLineChartDiv'));
76
+ timesOnSiteTable = new google.visualization.Table(document.getElementById('timesOnSiteTableDiv'));
77
+
78
+ getWebPropertyFeed();
79
+ } else {
80
+ divLogin.style.visibility = 'visible';
81
+ divLogged.style.visibility = 'hidden';
82
+ document.getElementById('buttonLogin').onclick = handleLogin;
83
+ }
84
+ }
85
+
86
+ function handleLogin() {
87
+ google.accounts.user.login(scope);
88
+ }
89
+
90
+ function getWebPropertyFeed() {
91
+ var webPropertyFeedUri = [scope, '/datasources/ga/accounts/',pageCode.split('-')[1],'/webproperties/',pageCode,'/profiles'].join('');
92
+
93
+ // Send asynchronous request to the Management API.
94
+ myService.getManagementFeed(webPropertyFeedUri, printWebPropertyFeed,handleError);
95
+ }
96
+
97
+ function printWebPropertyFeed(result) {
98
+ var feed = result.feed;
99
+ var entries = feed.getEntries();
100
+ var GAProfileId;
101
+ if (entries.length) {
102
+ for (var i = 0, entry; entry = entries[i]; ++i) {
103
+ GAProfileId = entry.getPropertyValue('ga:profileId');
104
+ }
105
+ }
106
+ profileId = GAProfileId;
107
+ getPageViewsDataFeed();
108
+ getVisitsDataFeed();
109
+ getVisitorsDataFeed();
110
+ getTimeOnSiteDataFeed();
111
+ getSourceDataFeed();
112
+ getKeywordDataFeed();
113
+ }
114
+
115
+ function getDateConditions() {
116
+ var toDay = new Date();
117
+ var lastMonth = new Date (toDay.getFullYear(), toDay.getMonth()-1, toDay.getDate());
118
+
119
+ var lastMonthStr;
120
+ if ((lastMonth.getMonth() + 1) < 10) {
121
+ lastMonthStr = '0'+(lastMonth.getMonth() + 1);
122
+ } else {
123
+ lastMonthStr = (lastMonth.getMonth() + 1);
124
+ }
125
+
126
+ var lastMonthDayStr;
127
+ if (lastMonth.getDate() < 10) {
128
+ lastMonthDayStr = '0'+(lastMonth.getDate());
129
+ } else {
130
+ lastMonthDayStr = (lastMonth.getDate());
131
+ }
132
+
133
+ var currentMonthStr;
134
+ if ((toDay.getMonth() + 1) < 10) {
135
+ currentMonthStr = '0'+(toDay.getMonth() + 1);
136
+ } else {
137
+ currentMonthStr = (toDay.getMonth() + 1);
138
+ }
139
+
140
+ var currentMonthDayStr;
141
+ if (toDay.getDate() < 10) {
142
+ currentMonthDayStr = '0'+(toDay.getDate());
143
+ } else {
144
+ currentMonthDayStr = (toDay.getDate());
145
+ }
146
+
147
+ var conditions = '?start-date='+ lastMonth.getFullYear() + '-' + lastMonthStr + '-' + lastMonthDayStr + '&end-date='+ toDay.getFullYear() + '-' + currentMonthStr + '-' + currentMonthDayStr
148
+
149
+ return conditions;
150
+ }
151
+
152
+ /**
153
+ * Request data from GA Export API
154
+ */
155
+ function getPageViewsDataFeed() {
156
+ var myFeedUri = scope + '/data' + getDateConditions() +
157
+ '&dimensions=ga:pageTitle,ga:pagePath' +
158
+ '&metrics=ga:pageviews' +
159
+ '&sort=-ga:pageviews' +
160
+ '&max-results=10' +
161
+ '&ids=ga:' + profileId;
162
+
163
+ myService.getDataFeed(myFeedUri, handlePageViewsDataFeed, handleError);
164
+ }
165
+
166
+ /**
167
+ * Request data from GA Export API
168
+ */
169
+ function getVisitsDataFeed() {
170
+ var myFeedUri = scope + '/data' + getDateConditions() +
171
+ '&dimensions=ga:day,ga:year,ga:month,ga:date' +
172
+ '&metrics=ga:visits' +
173
+ '&sort=ga:date' +
174
+ '&ids=ga:' + profileId;
175
+
176
+ myService.getDataFeed(myFeedUri, handleVisitsDataFeed, handleError);
177
+ }
178
+
179
+ /**
180
+ * Request data from GA Export API
181
+ */
182
+ function getVisitorsDataFeed() {
183
+ var myFeedUri = scope + '/data' + getDateConditions() +
184
+ '&dimensions=ga:day,ga:year,ga:month,ga:date' +
185
+ '&metrics=ga:visitors' +
186
+ '&sort=ga:date' +
187
+ '&ids=ga:' + profileId;
188
+
189
+ myService.getDataFeed(myFeedUri, handleVisitorsDataFeed, handleError);
190
+ }
191
+
192
+ /**
193
+ * Request data from GA Export API
194
+ */
195
+ function getTimeOnSiteDataFeed() {
196
+ var myFeedUri = scope + '/data' + getDateConditions() +
197
+ '&dimensions=ga:day,ga:year,ga:month,ga:date' +
198
+ '&metrics=ga:timeOnSite,ga:visits' +
199
+ '&sort=ga:date' +
200
+ '&ids=ga:' + profileId;
201
+
202
+ myService.getDataFeed(myFeedUri, handleTimeOnSiteDataFeed, handleError);
203
+ }
204
+
205
+ /**
206
+ * Request data from GA Export API
207
+ */
208
+ function getSourceDataFeed() {
209
+ var myFeedUri = scope + '/data' + getDateConditions() +
210
+ '&dimensions=ga:source' +
211
+ '&metrics=ga:visits' +
212
+ '&sort=-ga:visits' +
213
+ '&max-results=20' +
214
+ '&ids=ga:' + profileId;
215
+
216
+ myService.getDataFeed(myFeedUri, handleSourceDataFeed, handleError);
217
+ }
218
+
219
+ /**
220
+ * Request data from GA Export API
221
+ */
222
+ function getKeywordDataFeed() {
223
+ var myFeedUri = scope + '/data' + getDateConditions() +
224
+ '&dimensions=ga:keyword' +
225
+ '&metrics=ga:visits' +
226
+ '&sort=-ga:visits' +
227
+ '&max-results=20' +
228
+ '&ids=ga:' + profileId;
229
+
230
+ myService.getDataFeed(myFeedUri, handleKeywordDataFeed, handleError);
231
+ }
232
+
233
+ /**
234
+ * Handle and display any error that occurs from the API request.
235
+ * @param {Object} e The error object returned by the Analytics API.
236
+ */
237
+ function handleError(e) {
238
+ var msg = e.cause ? e.cause.statusText : e.message;
239
+ msg = 'ERROR: ' + msg;
240
+ alert(msg);
241
+ }
242
+
243
+ /**
244
+ * Handle all the data returned by GA Export API.
245
+ * Delete existing GViz dataTable before creating a new one.
246
+ * @param {Object} myResultsFeedRoot the feed object
247
+ * retuned by the data feed.
248
+ */
249
+ function handlePageViewsDataFeed(resultsFeedRoot) {
250
+ dataTable = new google.visualization.DataTable();
251
+ fillPageViewsDataTable(dataTable, resultsFeedRoot);
252
+ pageViewsTable.draw(dataTable);
253
+
254
+ // remove the URI column to only graph 1 dimension
255
+ dataTable.removeColumn(0);
256
+ pageViewsChart.draw(dataTable, {width: 950, height: 400});
257
+ pageViewsColumnChart.draw(dataTable, {width: 950, height: 300, legend: 'none'});
258
+ }
259
+
260
+ /**
261
+ * Handle all the data returned by GA Export API.
262
+ * Delete existing GViz dataTable before creating a new one.
263
+ * @param {Object} myResultsFeedRoot the feed object
264
+ * retuned by the data feed.
265
+ */
266
+ function handleVisitsDataFeed(resultsFeedRoot) {
267
+ dataTable = new google.visualization.DataTable();
268
+ fillVisitsDataTable(dataTable, resultsFeedRoot);
269
+ visitsLineChart.draw(dataTable, {width: 750, height: 500, legend: 'none'});
270
+ visitsTable.draw(dataTable);
271
+ }
272
+
273
+ function handleVisitorsDataFeed(resultsFeedRoot) {
274
+ dataTable = new google.visualization.DataTable();
275
+ fillVisitorsDataTable(dataTable, resultsFeedRoot);
276
+ visitorsLineChart.draw(dataTable, {width: 750, height: 500, legend: 'none'});
277
+ visitorsTable.draw(dataTable);
278
+ }
279
+
280
+ function handleTimeOnSiteDataFeed(resultsFeedRoot) {
281
+ dataTable = new google.visualization.DataTable();
282
+ fillTimesOnSiteDataTable(dataTable, resultsFeedRoot);
283
+ timesOnSiteLineChart.draw(dataTable, {width: 750, height: 500, legend: 'none'});
284
+ timesOnSiteTable.draw(dataTable);
285
+ }
286
+
287
+ function handleSourceDataFeed(resultsFeedRoot) {
288
+ dataTable = new google.visualization.DataTable();
289
+ fillSourceDataTable(dataTable, resultsFeedRoot);
290
+ sourcePieChart.draw(dataTable, {width: 600, height: 400, legend: 'none'});
291
+ sourceTable.draw(dataTable);
292
+ }
293
+
294
+ function handleKeywordDataFeed(resultsFeedRoot) {
295
+ dataTable = new google.visualization.DataTable();
296
+ fillKeywordDataTable(dataTable, resultsFeedRoot);
297
+ keywordPieChart.draw(dataTable, {width: 600, height: 400, legend: 'none'});
298
+ keywordTable.draw(dataTable);
299
+ }
300
+
301
+ /**
302
+ * Put the feed result into a GViz Data Table.
303
+ * @param {Object} dataTable the GViz dataTable
304
+ dataTable.setCell(0, 1, '0'); object to put data into.
305
+ * @param {Object} myResultsFeedRoot the feed returned by the GA Export API.
306
+ * @return {Objcet} GViz DataTable object.
307
+ */
308
+ function fillPageViewsDataTable(dataTable, myResultsFeedRoot) {
309
+ var entries = myResultsFeedRoot.feed.getEntries();
310
+
311
+ var datas = getGADatasInTable(entries, ['pageTitle','pagePath','pageviews']);
312
+ fillDataTable(entries, dataTable, [['string', I18n.t('admin.stats.title'), datas[0]],['string', I18n.t('admin.stats.path'), datas[1]],['number', I18n.t('admin.stats.page_views'), datas[2]]]);
313
+ }
314
+
315
+ function fillKeywordDataTable(dataTable, myResultsFeedRoot) {
316
+ var entries = myResultsFeedRoot.feed.getEntries();
317
+ var keywords = new Array();
318
+ var visits = new Array();
319
+
320
+ for (var i = 0, entry; entry = entries[i]; ++i) {
321
+
322
+ if (entry.getValueOf('ga:keyword') != '(not set)') {
323
+ keywords.push(entry.getValueOf('ga:keyword'));
324
+ visits.push(entry.getValueOf('ga:visits'));
325
+ }
326
+ }
327
+
328
+ fillDataTable(entries, dataTable, [['string', I18n.t('admin.stats.keywords'), keywords],['number', I18n.t('admin.stats.visits'), visits]]);
329
+ dataTable.removeRow(dataTable.getNumberOfRows()-1);
330
+ }
331
+
332
+ function fillSourceDataTable(dataTable, myResultsFeedRoot) {
333
+ var entries = myResultsFeedRoot.feed.getEntries();
334
+ var dates = new Array();
335
+
336
+ var datas = getGADatasInTable(entries, ['source', 'visits']);
337
+ fillDataTable(entries, dataTable, [['string', I18n.t('admin.stats.source'), datas[0]],['number', I18n.t('admin.stats.visits'), datas[1]]]);
338
+ }
339
+
340
+ function fillVisitsDataTable(dataTable, myResultsFeedRoot) {
341
+ var entries = myResultsFeedRoot.feed.getEntries();
342
+ var dates = new Array();
343
+
344
+ var datas = getGADatasInTable(entries, ['visits'], dates);
345
+ fillDataTable(entries, dataTable, [['string', I18n.t('admin.stats.date'), dates],['number', I18n.t('admin.stats.visits'), datas[0]]]);
346
+ }
347
+
348
+ function fillVisitorsDataTable(dataTable, myResultsFeedRoot) {
349
+ var entries = myResultsFeedRoot.feed.getEntries();
350
+ var dates = new Array();
351
+
352
+ var datas = getGADatasInTable(entries, ['visitors'], dates);
353
+ fillDataTable(entries, dataTable, [['string',I18n.t('admin.stats.date'), dates],['number', I18n.t('admin.stats.visitors'), datas[0]]]);
354
+ }
355
+
356
+ function fillTimesOnSiteDataTable(dataTable, myResultsFeedRoot) {
357
+ var entries = myResultsFeedRoot.feed.getEntries();
358
+ var timesOnSite = new Array();
359
+ var dates = new Array();
360
+
361
+ for (var i = 0, entry; entry = entries[i]; ++i) {
362
+ fillDate(entry, timesOnSite, dates);
363
+
364
+ if (entry.getValueOf('ga:visits') != 0) {
365
+ timesOnSite.push(entry.getValueOf('ga:timeOnSite') / entry.getValueOf('ga:visits'));
366
+ } else {
367
+ timesOnSite.push(0);
368
+ }
369
+ }
370
+
371
+ for (var i = 0; i < timesOnSite.length ; ++i) {
372
+ timesOnSite[i] = Math.round(timesOnSite[i] / 60);
373
+ }
374
+
375
+ convertDates(dates);
376
+
377
+ fillDataTable(entries, dataTable, [['string',I18n.t('admin.stats.date'), dates],['number', I18n.t('admin.stats.average_time'), timesOnSite]]);
378
+ }
379
+
380
+ function fillDate(entry, dataTable, dateTable) {
381
+ var date = new Date(entry.getValueOf('ga:year'), entry.getValueOf('ga:month')-1, entry.getValueOf('ga:day'));
382
+
383
+ // At the beginning of each day, check if data was missing for previous
384
+ // day. Insert "0" in appropriate visitor's array as necessary, using
385
+ // fillToSameSize helper method.
386
+ var lastDate = dateTable[dateTable.length - 1];
387
+ if(lastDate) {
388
+ while (Date.parse(date) != Date.parse(lastDate)) {
389
+ lastDate = new Date (lastDate.getFullYear(), lastDate.getMonth(), lastDate.getDate() + 1);
390
+ if (Date.parse(date) != Date.parse(lastDate)) {
391
+ dataTable.push(0);
392
+ dateTable.push(lastDate);
393
+ }
394
+ }
395
+ }
396
+
397
+ dateTable.push(date);
398
+ }
399
+
400
+ function fillDataTable(entries, dataTable, datas) {
401
+ for (var i = 0; i < datas.length; i++) {
402
+ dataTable.addColumn(datas[i][0], datas[i][1]);
403
+ }
404
+
405
+ dataTable.addRows(entries.length);
406
+
407
+ for (var idx = 0; idx < entries.length; idx++) {
408
+ var entry = entries[idx];
409
+ for (var i = 0; i < datas.length; i++) {
410
+ dataTable.setCell(idx, i, datas[i][2][idx]);
411
+ }
412
+ }
413
+ }
414
+
415
+ function getGADatasInTable(entries, datas, dates) {
416
+ var results = new Array();
417
+
418
+ for (var idx = 0; idx < entries.length; idx++) {
419
+ var entry = entries[idx];
420
+ for (var i = 0; i <datas.length; i++) {
421
+ results.push(new Array());
422
+ var GAData = entry.getValueOf('ga:'+datas[i]);
423
+ if (dates) {
424
+ fillDate(entry, results[i], dates);
425
+ }
426
+ results[i].push(GAData);
427
+ }
428
+ }
429
+
430
+ convertDates(dates);
431
+ return results
432
+ }
433
+
434
+ function convertDates(dates) {
435
+ if (dates) {
436
+ for (var i = 0; i < dates.length; i++) {
437
+ dates[i] = dates[i].toLocaleString().substr(0,10);
438
+ }
439
+ }
440
+ }
441
+
442
+ // Load the Google Visualization API client Libraries
443
+ google.load('visualization', '1', {packages: ['piechart', 'table', 'columnchart', 'linechart']});
444
+
445
+ // Load the Google data JavaScript client library
446
+ google.load('gdata', '2.x', {packages: ['analytics']});
@@ -0,0 +1,14 @@
1
+ div.stat {
2
+ width: 958px;
3
+ opacity: 1;
4
+ border-bottom-left-radius: 5px;
5
+ border-bottom-right-radius: 5px;
6
+ border-top-right-radius: 5px;
7
+ background: none repeat scroll 0 0 #FFFFFF;
8
+ border: 1px solid #CCCCCC;
9
+ padding: 5px 5px 0;
10
+ }
11
+
12
+ .ui-tabs-nav {
13
+ padding: 0px;
14
+ }
metadata ADDED
@@ -0,0 +1,65 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: refinerycms-stats
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: "0.1"
6
+ platform: ruby
7
+ authors:
8
+ - Guirec CORBEL
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-06-26 00:00:00 Z
14
+ dependencies: []
15
+
16
+ description: Ruby on Rails Stats engine for Refinery CMS
17
+ email: guirec.corbel@gmail.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - lib/generators/refinerycms_stats_generator.rb
26
+ - lib/refinerycms-stats.rb
27
+ - lib/tasks/stats.rake
28
+ - config/locales/en.yml
29
+ - config/locales/fr.yml
30
+ - config/routes.rb
31
+ - app/controllers/admin/stats_controller.rb
32
+ - app/models/stat.rb
33
+ - app/views/admin/stats/index.html.erb
34
+ - public/javascripts/refinerycms-stat-translate.js
35
+ - public/javascripts/refinerycms-stat.js
36
+ - public/stylesheets/stat.css
37
+ homepage: http://www.guirec-corbel.com
38
+ licenses: []
39
+
40
+ post_install_message:
41
+ rdoc_options: []
42
+
43
+ require_paths:
44
+ - lib
45
+ required_ruby_version: !ruby/object:Gem::Requirement
46
+ none: false
47
+ requirements:
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: "0"
51
+ required_rubygems_version: !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: "0"
57
+ requirements: []
58
+
59
+ rubyforge_project:
60
+ rubygems_version: 1.8.5
61
+ signing_key:
62
+ specification_version: 3
63
+ summary: Stats engine for Refinery CMS
64
+ test_files: []
65
+