v9: Implement telemetry levels (#12267)
* Add initial classes * Add TelemetryProviders * Add new NodeCountService.cs and NodeTelemetryProvider * Add data contract attribute to UsageInformation Otherwise it wont serialize correctly * Implement more providers * Fix builders and propertyEditorTelemetry * Add MediaTelemetryProvider * Add MediaTelemetryProvider * Fix doubling of media telemetry * Move contentCount from NodeCountTelemetryProvider and move to ContentTelemetryProvider * Revert ContentTelemetryProvider changes * Add detailed information to TelemetryService * Add integration tests * Add more tests and todos for tests * Fix stylecop warnings * Use yield return instead of instantiating local list * Implement Macro test * Inject interface instead of implementation in TelemetryService * Fix TelemetryServiceTests.cs * Implement media tests * Implement propertyTypeTests * Implement constants instead of hardcoded strings * Add SystemInformationTelemetryProvider * Use SystemInformationTableDataProvider in UserDataService * Implement more properties * Add UsageInformation * Replace UserDataService with SystemInformationTelemetryProvider * Undo changes to UserDataService and obsolete it * Remove ISystemInformationTableDataProvider * Register SystemInformationTelemetryProvider as telemetry provider * Use constants for telemetry names * Make UserDataServiceTests test SystemInformationTelemetryProvider instead * Update UserDataServiceTests to cover new data * Add unit tests * Add integration test testing expected data is returned * Implement Analytics dashboard * Improve assertion message * Add text and styling to analyticspage * Rename consent to analytic * implement save button for consent level * Implement save button * Fix system information test * Add TelemetryResource * Move telemetry providers to infrastructure * Add database provider to system information * Set startvalue for slider * Fix unit tests * Implement MetricsConsentService using KeyValueService * Return void hen setting the telemetry level * fix startposition when not reloading * Add a couple tests * Update src/Umbraco.Core/Services/MetricsConsentService.cs * Rename ConsentLevel.cs * Use direct Enum instead of parsing * rename consent resource * add lazy database * refactor slider * Implement ng-if and propers pips * Make classes internal * Fix slider not loading when navigating to tab * Add telemetry level check to TelemetryService.cs * Add Consent for analytics text * Fix build errors for unit tests * Fix TelemetryServiceTests * revert package-lock.json * Fix integration test * Update slider * Update TelemetryService.cs * Apply suggestions from code review Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> Co-authored-by: Nikolaj Geisle <niko737@edu.ucl.dk> Co-authored-by: nikolajlauridsen <nikolajlauridsen@protonmail.ch>
This commit is contained in:
@@ -13,7 +13,7 @@ For extra details about options and events take a look here: https://refreshless
|
||||
<pre>
|
||||
<div ng-controller="My.Controller as vm">
|
||||
|
||||
<umb-range-slider
|
||||
<umb-range-slider
|
||||
ng-model="vm.value"
|
||||
on-end="vm.slideEnd(values)">
|
||||
</umb-range-slider>
|
||||
@@ -229,11 +229,13 @@ For extra details about options and events take a look here: https://refreshless
|
||||
var origins = slider.noUiSlider.getOrigins();
|
||||
|
||||
// Move tooltips into the origin element. The default stylesheet handles this.
|
||||
if(tooltips && tooltips.length !== 0){
|
||||
tooltips.forEach(function (tooltip, index) {
|
||||
if (tooltip) {
|
||||
origins[index].appendChild(tooltip);
|
||||
}
|
||||
if (tooltip) {
|
||||
origins[index].appendChild(tooltip);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
slider.noUiSlider.on('update', function (values, handle, unencoded, tap, positions) {
|
||||
|
||||
@@ -283,7 +285,7 @@ For extra details about options and events take a look here: https://refreshless
|
||||
offset = (textIsRtl && !isVertical ? 100 : 0) + (offset / handlesInPool) - lastOffset;
|
||||
|
||||
// Filter to unique values
|
||||
var tooltipValues = poolValues[poolIndex].filter((v, i, a) => a.indexOf(v) === i);
|
||||
var tooltipValues = poolValues[poolIndex].filter((v, i, a) => a.indexOf(v) === i);
|
||||
|
||||
// Center this tooltip over the affected handles
|
||||
tooltips[handleNumber].innerHTML = tooltipValues.join(separator);
|
||||
|
||||
@@ -20,7 +20,8 @@ Umbraco.Sys.ServerVariables = {
|
||||
"updateCheckApiBaseUrl": "/umbraco/Api/UpdateCheck/",
|
||||
"relationApiBaseUrl": "/umbraco/UmbracoApi/Relation/",
|
||||
"rteApiBaseUrl": "/umbraco/UmbracoApi/RichTextPreValue/",
|
||||
"iconApiBaseUrl": "/umbraco/UmbracoApi/Icon/"
|
||||
"iconApiBaseUrl": "/umbraco/UmbracoApi/Icon/",
|
||||
"analyticsApiBaseUrl": "/umbraco/UmbracoApi/Consent/"
|
||||
},
|
||||
umbracoSettings: {
|
||||
"umbracoPath": "/umbraco",
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* @ngdoc service
|
||||
* @name umbraco.resources.consentResource
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* Used by the health check dashboard to get checks and send requests to fix checks.
|
||||
*/
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
function analyticResource($http, umbRequestHelper) {
|
||||
|
||||
function getConsentLevel () {
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"analyticsApiBaseUrl",
|
||||
"GetConsentLevel")),
|
||||
'Server call failed for getting current consent level');
|
||||
}
|
||||
|
||||
function getAllConsentLevels () {
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"analyticsApiBaseUrl",
|
||||
"GetAllLevels")),
|
||||
'Server call failed for getting current consent level');
|
||||
}
|
||||
|
||||
function saveConsentLevel (value) {
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.post(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"analyticsApiBaseUrl",
|
||||
"SetConsentLevel"),
|
||||
{ telemetryLevel : value }
|
||||
),
|
||||
'Server call failed for getting current consent level');
|
||||
}
|
||||
|
||||
var resource = {
|
||||
getConsentLevel: getConsentLevel,
|
||||
getAllConsentLevels : getAllConsentLevels,
|
||||
saveConsentLevel : saveConsentLevel
|
||||
};
|
||||
|
||||
return resource;
|
||||
|
||||
}
|
||||
|
||||
|
||||
angular.module('umbraco.resources').factory('analyticResource', analyticResource);
|
||||
|
||||
|
||||
})();
|
||||
@@ -200,6 +200,10 @@ angular.module('umbraco.services')
|
||||
* localizationService.localizeMany(["speechBubbles_templateErrorHeader", "speechBubbles_templateErrorText"]).then(function(data){
|
||||
* var header = data[0];
|
||||
* var message = data[1];
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* notificationService.error(header, message);
|
||||
* });
|
||||
* </pre>
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
function AnalyticsController($q, analyticResource, localizationService, notificationsService) {
|
||||
|
||||
let sliderRef = null;
|
||||
|
||||
var vm = this;
|
||||
vm.getConsentLevel = getConsentLevel;
|
||||
vm.getAllConsentLevels = getAllConsentLevels;
|
||||
vm.saveConsentLevel = saveConsentLevel;
|
||||
vm.sliderChange = sliderChange;
|
||||
vm.setup = setup;
|
||||
vm.loading = true;
|
||||
vm.consentLevel = '';
|
||||
vm.consentLevels = [];
|
||||
vm.val = 1;
|
||||
vm.sliderOptions =
|
||||
{
|
||||
"start": 1,
|
||||
"step": 1,
|
||||
"tooltips": [false],
|
||||
"range": {
|
||||
"min": 1,
|
||||
"max": 3
|
||||
},
|
||||
pips: {
|
||||
mode: 'values',
|
||||
density: 50,
|
||||
values: [1, 2, 3],
|
||||
format: {
|
||||
to: function (value) {
|
||||
return vm.consentLevels[value - 1];
|
||||
},
|
||||
from: function (value) {
|
||||
return Number(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
$q.all(
|
||||
[getConsentLevel(),
|
||||
getAllConsentLevels()
|
||||
]).then( () => {
|
||||
vm.startPos = calculateStartPositionForSlider();
|
||||
vm.sliderVal = vm.consentLevels[vm.startPos - 1];
|
||||
vm.sliderOptions.start = vm.startPos;
|
||||
vm.val = vm.startPos;
|
||||
vm.sliderOptions.pips.format = {
|
||||
to: function (value) {
|
||||
return vm.consentLevels[value - 1];
|
||||
},
|
||||
from: function (value) {
|
||||
return Number(value);
|
||||
}
|
||||
}
|
||||
vm.loading = false;
|
||||
if (sliderRef) {
|
||||
sliderRef.noUiSlider.set(vm.startPos);
|
||||
}
|
||||
|
||||
});
|
||||
function setup(slider) {
|
||||
sliderRef = slider;
|
||||
}
|
||||
|
||||
function getConsentLevel() {
|
||||
return analyticResource.getConsentLevel().then(function (response) {
|
||||
vm.consentLevel = response;
|
||||
})
|
||||
}
|
||||
function getAllConsentLevels(){
|
||||
return analyticResource.getAllConsentLevels().then(function (response) {
|
||||
vm.consentLevels = response;
|
||||
})
|
||||
}
|
||||
function saveConsentLevel(){
|
||||
analyticResource.saveConsentLevel(vm.sliderVal);
|
||||
localizationService.localize("analytics_analyticsLevelSavedSuccess").then(function(value) {
|
||||
notificationsService.success(value);
|
||||
});
|
||||
}
|
||||
|
||||
function sliderChange(values) {
|
||||
const result = Number(values[0]);
|
||||
vm.sliderVal = vm.consentLevels[result - 1];
|
||||
}
|
||||
|
||||
function calculateStartPositionForSlider(){
|
||||
let startPosition = vm.consentLevels.indexOf(vm.consentLevel) + 1;
|
||||
if(startPosition === 0){
|
||||
return 2;// Default start value
|
||||
}
|
||||
return startPosition;
|
||||
}
|
||||
}
|
||||
angular.module("umbraco").controller("Umbraco.Dashboard.AnalyticsController", AnalyticsController);
|
||||
})();
|
||||
@@ -0,0 +1,59 @@
|
||||
<div ng-controller="Umbraco.Dashboard.AnalyticsController as vm">
|
||||
<umb-box>
|
||||
<umb-box-content>
|
||||
<h3 class="bold">
|
||||
<localize key="analytics_consentForAnalytics">Consent for analytics</localize>
|
||||
</h3>
|
||||
<div class="umb-healthcheck-help-text">
|
||||
<p>In order to improve Umbraco and add new functionality based on as relevant information as possible,
|
||||
<br>we would like to collect system- and usage information from your installation.
|
||||
<br>We will NOT collect any personal data like content, code or users, and all data will be fully anonymous.
|
||||
<br>
|
||||
<br>We will on a regular basis share some of the overall learnings from these metrics.
|
||||
Hopefully, you'll help us collect some valuable data.</p>
|
||||
<div ng-if="!vm.loading" style="padding-left: 12px;padding-top: 50px; padding-bottom: 50px; width: 25%">
|
||||
<umb-range-slider
|
||||
ng-model="vm.val"
|
||||
on-setup="vm.setup(slider)"
|
||||
options="vm.sliderOptions"
|
||||
on-update="vm.sliderChange(values)">
|
||||
</umb-range-slider>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
<div ng-if="vm.sliderVal === 'Minimal'">
|
||||
<b>{{vm.sliderVal}}</b>
|
||||
<br>We'll only send an anonymous site ID to let us know that the site exists.
|
||||
</div>
|
||||
<div ng-if="vm.sliderVal === 'Basic'">
|
||||
<b>{{vm.sliderVal}}</b>
|
||||
<br>We'll send site ID, umbraco version and packages installed
|
||||
</div>
|
||||
<div ng-if="vm.sliderVal === 'Detailed'">
|
||||
<b>{{vm.sliderVal}}</b>
|
||||
|
||||
<br> We'll send:
|
||||
<br>- Site ID, umbraco version and packages installed
|
||||
<br>- System information like Server OS and Webserver
|
||||
<br>- Statistics, like number of content nodes and number of media items
|
||||
<br>- Configuration settings, like modelsbuilder mode and used languages
|
||||
<br>
|
||||
<br>We might change/extend what we send on the detailed level in the future, but if so, it will be listed in
|
||||
this view.
|
||||
By choosing "detailed" I accept these future changes
|
||||
</div>
|
||||
</p>
|
||||
</div>
|
||||
<div class="umb-panel-group__details-status-actions">
|
||||
<umb-button type="button"
|
||||
button-style="success"
|
||||
label="Save"
|
||||
action="vm.saveConsentLevel()"
|
||||
ng-model="vm.sliderVal" ng-if="vm.consentLevel">
|
||||
</umb-button>
|
||||
</div>
|
||||
</umb-box-content>
|
||||
</umb-box>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user