From ff471bce1fd10cf97b2ad42751e3df5c37a062fb Mon Sep 17 00:00:00 2001 From: MusikAnimal Date: Tue, 10 May 2016 13:19:08 -0400 Subject: [PATCH] add unique devices option to Siteviews, better interapp links --- javascripts/siteviews/config.js | 1 + javascripts/siteviews/siteviews.js | 65 +++++++- messages/en.json | 10 +- messages/qqq.json | 10 +- public_html/_footer.php | 4 +- public_html/index.php | 13 +- public_html/siteviews/application.js | 4 +- public_html/siteviews/faq/index.php | 15 ++ public_html/siteviews/index.php | 40 +++-- public_html/siteviews/siteviews.js | 147 +++++++++++++----- public_html/siteviews/url_structure/index.php | 4 + views/_footer.haml | 4 +- views/index.haml | 9 +- views/siteviews/faq.haml | 10 ++ views/siteviews/index.haml | 32 ++-- views/siteviews/url_structure.haml | 3 + 16 files changed, 283 insertions(+), 88 deletions(-) diff --git a/javascripts/siteviews/config.js b/javascripts/siteviews/config.js index b28e272f9..c9e2986e0 100644 --- a/javascripts/siteviews/config.js +++ b/javascripts/siteviews/config.js @@ -99,6 +99,7 @@ const config = { circularCharts: ['Pie', 'Doughnut', 'PolarArea'], colors: ['rgba(171, 212, 235, 1)', 'rgba(178, 223, 138, 1)', 'rgba(251, 154, 153, 1)', 'rgba(253, 191, 111, 1)', 'rgba(202, 178, 214, 1)', 'rgba(207, 182, 128, 1)', 'rgba(141, 211, 199, 1)', 'rgba(252, 205, 229, 1)', 'rgba(255, 247, 161, 1)', 'rgba(217, 217, 217, 1)'], cookieExpiry: 30, // num days + dataSourceSelector: '#data-source-select', defaults: { autocomplete: 'autocomplete', chartType: 'Line', diff --git a/javascripts/siteviews/siteviews.js b/javascripts/siteviews/siteviews.js index 1940c6b90..931faa631 100644 --- a/javascripts/siteviews/siteviews.js +++ b/javascripts/siteviews/siteviews.js @@ -52,6 +52,7 @@ class SiteViews extends Pv { this.setupSiteSelector(); this.setupSettingsModal(); this.setupSelect2Colors(); + this.setupDataSourceSelector(); this.popParams(); this.setupListeners(); } @@ -176,7 +177,7 @@ class SiteViews extends Pv { let edgeCase = date.isSame(config.maxDate) || date.isSame(moment(config.maxDate).subtract(1, 'days')); data.items.push({ timestamp: date.format(config.timestampFormat), - views: edgeCase ? null : 0 + [this.isPageviews() ? 'views' : 'devices']: edgeCase ? null : 0 }); } } @@ -192,7 +193,7 @@ class SiteViews extends Pv { * @returns {object} - ready for chart rendering */ getCircularData(data, site, index) { - const values = data.items.map(elem => elem.views), + const values = data.items.map(elem => this.isPageviews() ? elem.views : elem.devices), color = config.colors[index]; return Object.assign( @@ -232,7 +233,7 @@ class SiteViews extends Pv { * @returns {object} - ready for chart rendering */ getLinearData(data, site, index) { - const values = data.items.map(elem => elem.views), + const values = data.items.map(elem => this.isPageviews() ? elem.views : elem.devices), color = config.colors[index % 10]; return Object.assign( @@ -337,8 +338,16 @@ class SiteViews extends Pv { this.setSpecialRange(config.defaults.dateRange); } + $(config.dataSourceSelector).val(params.source || 'pageviews'); + + this.setupDataSourceSelector(); + $(config.platformSelector).val(params.platform || 'all-access'); - $(config.agentSelector).val(params.agent || 'user'); + if (params.source === 'pageviews') { + $(config.agentSelector).val(); + } else { + $(config.dataSourceSelector).trigger('change'); + } this.resetSiteSelector(); @@ -361,9 +370,13 @@ class SiteViews extends Pv { getParams(specialRange = true) { let params = { platform: $(config.platformSelector).val(), - agent: $(config.agentSelector).val() + source: $(config.dataSourceSelector).val() }; + if (this.isPageviews()) { + params.agent = $(config.agentSelector).val(); + } + /** * Override start and end with custom range values, if configured (set by URL params or setupDateRangeSelector) * Valid values are those defined in config.specialRanges, constructed like `{range: 'last-month'}`, @@ -379,6 +392,10 @@ class SiteViews extends Pv { return params; } + isPageviews() { + return $(config.dataSourceSelector).val() === 'pageviews'; + } + /** * Push relevant class properties to the query string * Called whenever we go to update the chart @@ -626,6 +643,35 @@ class SiteViews extends Pv { }); } + setPlatformOptionValues() { + $(config.platformSelector).find('option').each((index, el) => { + $(el).prop('value', this.isPageviews() ? $(el).data('value') : $(el).data('ud-value')); + }); + } + + setupDataSourceSelector() { + this.setPlatformOptionValues(); + + $(config.dataSourceSelector).on('change', e => { + if (this.isPageviews()) { + $('.platform-select--mobile-web').show(); + $(config.agentSelector).prop('disabled', false); + } else { + $('.platform-select--mobile-web').hide(); + $(config.agentSelector).val('user').prop('disabled', true); + } + + this.setPlatformOptionValues(); + + /** reset to all-access if currently on mobile-app for unique-devices (not pageviews) */ + if ($(config.platformSelector).val() === 'mobile-app' && !this.isPageviews()) { + $(config.platformSelector).val('all-sites'); // chart will automatically re-render + } else { + this.updateChart(); + } + }); + } + /** * General place to add page-wide listeners * @returns {null} - nothing @@ -728,12 +774,17 @@ class SiteViews extends Pv { */ sites.forEach((site, index) => { const uriEncodedSite = encodeURIComponent(site); + /** @type {String} Url to query the API. */ - const url = ( + const url = this.isPageviews() ? ( `https://wikimedia.org/api/rest_v1/metrics/pageviews/aggregate/${uriEncodedSite}` + `/${$(config.platformSelector).val()}/${$(config.agentSelector).val()}/daily` + `/${startDate.format(config.timestampFormat)}/${endDate.format(config.timestampFormat)}` + ) : ( + `https://wikimedia.org/api/rest_v1/metrics/unique-devices/${uriEncodedSite}/${$(config.platformSelector).val()}/daily` + + `/${startDate.format(config.timestampFormat)}/${endDate.format(config.timestampFormat)}` ); + const promise = $.ajax({ url: url, dataType: 'json' @@ -742,7 +793,7 @@ class SiteViews extends Pv { promise.success(data => { // FIXME: these needs fixing too, sometimes doesn't show zero - this.fillInZeros(data, startDate, endDate); + if (this.isPageviews()) this.fillInZeros(data, startDate, endDate); /** Build the site's dataset. */ if (config.linearCharts.includes(this.chartType)) { diff --git a/messages/en.json b/messages/en.json index dc333354f..ec14c24f7 100644 --- a/messages/en.json +++ b/messages/en.json @@ -108,6 +108,9 @@ "language": "Language", "badges": "Badges", "pageviews": "Pageviews", + "langviews": "Langviews", + "topviews": "Topviews", + "siteviews": "Siteviews", "average": "Average", "submit": "Submit", "hover-to-exclude": "Hover over entires and click the ✖ to exclude from view", @@ -143,6 +146,9 @@ "faq-topviews-false-positive-title": "Why do some random pages have such high view counts?", "faq-topviews-false-positive-body1": "These are false positives, and unfortunately they are unavoidable. These could surface because someone used an automated program to scrape the page, for instance. One tactic to identify false positives is to compare desktop views with mobile web. Mobile web views should be comprabale if not higher than desktop, so if mobile web views are very low, it might be a false positive.", "faq-topviews-false-positive-body2": "You can also open a page in the Pageviews app for further analysis. Just click on the view count on the right side. The data you see here is accurate. If there's an unusual spike in traffic, the Wikimedia Analytics team might be able to explain it.", + "faq-source-title": "What are the \"Data sources\"?", + "faq-source-pageviews": "is the total number of pageviews the project received.", + "faq-source-unique-devices": "is the number of unique devices that visited the site.", "url-structure-example": "To get the latest data on a given article on your wiki, with default options, use:\n$1\nreplacing $2 with a valid $3. $4 will resolve to the page the link is placed on", "url-structure-example-siteviews": "To get the latest data on a given article on your wiki, with default options, use:\n$1", "url-structure-topviews-example": "To show the default list of top viewed pages on your wiki, use:\n$1\nreplacing $2 with a valid $3. You can also use $4 to exclude certain pages from view, such as the Main Page.", @@ -165,6 +171,7 @@ "url-structure-agent": "One of $1 (human viewer, default), $2 (search engine crawlers), $3 (WMF bots) or $4 (user, spider and bot)", "url-structure-sort": "Which column to sort. One of $1, $2, $3 or $4", "url-structure-sort-direction": "The sort direction. $1 for descending, $2 for ascending", + "url-structure-source": "Either $1 (total page views) or $2 (number of unique devices that viewed the page)", "default": "Default", "all-languages": "All languages", "history": "History", @@ -178,5 +185,6 @@ "statistics": "Statistics", "most-viewed-pages": "Most viewed pages", "topviews-data-approx": "All topviews data is approximate.", - "topviews-false-positive": "Some pages listed may be false positives." + "topviews-false-positive": "Some pages listed may be false positives.", + "unique-devices": "Unique devices" } diff --git a/messages/qqq.json b/messages/qqq.json index e72ba8caf..7d30e8535 100644 --- a/messages/qqq.json +++ b/messages/qqq.json @@ -114,7 +114,10 @@ "another-query": "Link to run a new query on the Langviews application", "language": "Header of the language column in the Langviews application\n{{Identical|Language}}", "badges": "Header of the badges column in the Langviews application. Badges are special recognized articles, such as 'good articles' or 'featured articles'\n{{Identical|Badge}}", - "pageviews": "Header of the pageviews column in the Langviews application.", + "pageviews": "The word 'pageviews'. Used as the link for the Pageviews application in the footer, and as the label of the column for the view counts in Langviews\n{{Identical|Pageviews}}", + "langviews": "Abbreviated name of the Langviews application. This is used in the inter-app links in the footer", + "topviews": "Abbreviated name of the Topviews application. This is used in the inter-app links in the footer", + "siteviews": "Abbreviated name of the Siteviews application. This is used in the inter-app links in the footer", "average": "Header of the average pageviews per day column in the Langviews application.\n{{Identical|Average}}", "submit": "The text for the button to submit the form in the Langviews application.\n{{Identical|Submit}}", "hover-to-exclude": "Placeholder in the input of the Topviews application, instructing to hover over entries and click on the X to exclude them from view", @@ -150,6 +153,9 @@ "faq-topviews-false-positive-title": "FAQ - title of the section explaning that there could be false positives in the Topviews report.", "faq-topviews-false-positive-body1": "FAQ - body of the section explaining that there could be false positives in the Topviews report.", "faq-topviews-false-positive-body2": "FAQ - an additional body of text explaining that there could be false positives in the Topviews report.", + "faq-source-title": "FAQ - title of the section explaining what the 'source' options are.", + "faq-source-pageviews": "FAQ - body of the section explaining what the 'source' options are.", + "faq-source-unique-devices": "is the number of unique devices that visited the site.", "url-structure-example": "Example of how to link to Pageviews Analysis on a wiki. $1 is the example link, $2 is the example project, $3 is the link to the site matrix, $4 is {{FULLPAGENAMEE}}", "url-structure-example-siteviews": "Example of how to link to Siteviews Analysis on a wiki. $1 is the example link. This message is the same as the first sentence of 'url-structure-example'", "url-structure-topviews-example": "Example of how to link to Topviews Analysis on a wiki. $1 is the example link, $2 is the example project, $3 is the link to the site matrix, and $4 is the 'excludes' parameter", @@ -172,6 +178,7 @@ "url-structure-agent": "States the 'agent' parameter can have one of the values 'user' ($1), 'spider' ($2), 'bot' ($3), or 'all-agents' ($4)", "url-structure-sort": "Documentation for the 'sort' parameter. $1, $2, $3 and $4 are the valid values", "url-structure-sort-direction": "Documentation for the 'direction' parameter. $1 is the value for descending, $2 is the value for ascending", + "url-structure-source": "Documentation for the 'source' parameter. $1 and $2 are valid values", "default": "Default\n{{Identical|Default}}", "all-languages": "A link to show the article in the multilingual pageviews tool. This appears in the 'info tiles' on Pageviews Analysis", "history": "A link to the wiki revision history page of the article. This appears in the 'info tiles' on Pageviews Analysis\n{{Identical|History}}", @@ -186,4 +193,5 @@ "most-viewed-pages": "Link to view the most viewed pages of a project", "topviews-data-approx": "Text that shows above the list of pages on Topviews that explains the data is approximate. This links to the relevant FAQ section. Please do not alter the link.", "topviews-false-positive": "Text that shows above the list of pages on Topviews that explains there might be false positives. This links to the relevant FAQ section. Please do not alter the link.", + "unique-devices": "Label for option to view statistics for unique devices only (as opposed to all page views)" } diff --git a/public_html/_footer.php b/public_html/_footer.php index 8ca8a35da..793ab0456 100644 --- a/public_html/_footer.php +++ b/public_html/_footer.php @@ -33,9 +33,9 @@ - msg( $i18nName . 'title' ); ?> + msg( $app ); ?> - {$I18N->msg( $i18nName . 'title' )}"; ?> + {$I18N->msg( $app )}"; ?> diff --git a/public_html/index.php b/public_html/index.php index ba9b4f060..a2e31365b 100644 --- a/public_html/index.php +++ b/public_html/index.php @@ -111,13 +111,16 @@