diff --git a/src/Umbraco.Cms.StaticAssets/umbraco/UmbracoInstall/Index.cshtml b/src/Umbraco.Cms.StaticAssets/umbraco/UmbracoInstall/Index.cshtml index 797c647049..92e458c3b0 100644 --- a/src/Umbraco.Cms.StaticAssets/umbraco/UmbracoInstall/Index.cshtml +++ b/src/Umbraco.Cms.StaticAssets/umbraco/UmbracoInstall/Index.cshtml @@ -11,6 +11,7 @@ Install Umbraco + @@ -30,7 +31,7 @@ ng-animate="'fade'" ng-show="installer.configuring"> -
+

A server error occurred

This is most likely due to an error during application startup

diff --git a/src/Umbraco.Core/EmbeddedResources/Lang/en_us.xml b/src/Umbraco.Core/EmbeddedResources/Lang/en_us.xml index 7ebce617b5..3600ac501b 100644 --- a/src/Umbraco.Core/EmbeddedResources/Lang/en_us.xml +++ b/src/Umbraco.Core/EmbeddedResources/Lang/en_us.xml @@ -2886,7 +2886,7 @@ To manage your website, simply open the Umbraco backoffice and start adding cont We will send an anonymized site ID, umbraco version, and packages installed We will send: + We will send:
- Anonymized site ID, umbraco version, and packages installed.
- Number of: Root nodes, Content nodes, Macros, Media, Document Types, Templates, Languages, Domains, User Group, Users, Members, and Property Editors in use.
- System information: Webserver, server OS, server framework, server OS language, and database provider. diff --git a/src/Umbraco.Core/Install/Models/UserModel.cs b/src/Umbraco.Core/Install/Models/UserModel.cs index 392730b3b6..d294a24c1d 100644 --- a/src/Umbraco.Core/Install/Models/UserModel.cs +++ b/src/Umbraco.Core/Install/Models/UserModel.cs @@ -1,4 +1,5 @@ using System.Runtime.Serialization; +using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Install.Models { @@ -16,5 +17,8 @@ namespace Umbraco.Cms.Core.Install.Models [DataMember(Name = "subscribeToNewsLetter")] public bool SubscribeToNewsLetter { get; set; } + + [DataMember(Name = "telemetryLevel")] + public TelemetryLevel TelemetryLevel { get; set; } } } diff --git a/src/Umbraco.Core/Services/MetricsConsentService.cs b/src/Umbraco.Core/Services/MetricsConsentService.cs index d494dbcf4b..ca64d42810 100644 --- a/src/Umbraco.Core/Services/MetricsConsentService.cs +++ b/src/Umbraco.Core/Services/MetricsConsentService.cs @@ -14,25 +14,44 @@ namespace Umbraco.Cms.Core.Services private readonly IKeyValueService _keyValueService; private readonly ILogger _logger; private readonly IBackOfficeSecurityAccessor _backOfficeSecurityAccessor; + private readonly IUserService _userService; // Scheduled for removal in V12 - [Obsolete("Please use the constructor that takes and ILogger and IBackOfficeSecurity instead")] + [Obsolete("Please use the constructor that takes an ILogger and IBackOfficeSecurity instead")] public MetricsConsentService(IKeyValueService keyValueService) : this( keyValueService, StaticServiceProvider.Instance.GetRequiredService>(), - StaticServiceProvider.Instance.GetRequiredService()) + StaticServiceProvider.Instance.GetRequiredService(), + StaticServiceProvider.Instance.GetRequiredService()) + { + } + + // Scheduled for removal in V12 + [Obsolete("Please use the constructor that takes an IUserService instead")] + public MetricsConsentService( + IKeyValueService keyValueService, + ILogger logger, + IBackOfficeSecurityAccessor backOfficeSecurityAccessor) + : this( + keyValueService, + logger, + backOfficeSecurityAccessor, + StaticServiceProvider.Instance.GetRequiredService()) { } public MetricsConsentService( IKeyValueService keyValueService, ILogger logger, - IBackOfficeSecurityAccessor backOfficeSecurityAccessor) + IBackOfficeSecurityAccessor backOfficeSecurityAccessor, + IUserService userService + ) { _keyValueService = keyValueService; _logger = logger; _backOfficeSecurityAccessor = backOfficeSecurityAccessor; + _userService = userService; } public TelemetryLevel GetConsentLevel() @@ -50,6 +69,11 @@ namespace Umbraco.Cms.Core.Services public void SetConsentLevel(TelemetryLevel telemetryLevel) { var currentUser = _backOfficeSecurityAccessor.BackOfficeSecurity?.CurrentUser; + if (currentUser is null) + { + currentUser = _userService.GetUserById(Constants.Security.SuperUserId); + } + _logger.LogInformation("Telemetry level set to {telemetryLevel} by {username}", telemetryLevel, currentUser?.Username); _keyValueService.SetValue(Key, telemetryLevel.ToString()); } diff --git a/src/Umbraco.Infrastructure/Install/InstallSteps/NewInstallStep.cs b/src/Umbraco.Infrastructure/Install/InstallSteps/NewInstallStep.cs index 4f5dbc3cc2..e21b5d0728 100644 --- a/src/Umbraco.Infrastructure/Install/InstallSteps/NewInstallStep.cs +++ b/src/Umbraco.Infrastructure/Install/InstallSteps/NewInstallStep.cs @@ -1,14 +1,17 @@ using System.Collections.Specialized; using System.Text; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using Newtonsoft.Json; using Umbraco.Cms.Core.Configuration.Models; using Umbraco.Cms.Core.Install.Models; +using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Security; using Umbraco.Cms.Core.Services; using Umbraco.Cms.Core.Web; using Umbraco.Cms.Infrastructure.Migrations.Install; using Umbraco.Cms.Infrastructure.Persistence; +using Umbraco.Cms.Web.Common.DependencyInjection; using Umbraco.Extensions; using Constants = Umbraco.Cms.Core.Constants; @@ -35,6 +38,8 @@ namespace Umbraco.Cms.Infrastructure.Install.InstallSteps private readonly IBackOfficeUserManager _userManager; private readonly IDbProviderFactoryCreator _dbProviderFactoryCreator; private readonly IEnumerable _databaseProviderMetadata; + private readonly ILocalizedTextService _localizedTextService; + private readonly IMetricsConsentService _metricsConsentService; public NewInstallStep( IUserService userService, @@ -46,7 +51,9 @@ namespace Umbraco.Cms.Infrastructure.Install.InstallSteps ICookieManager cookieManager, IBackOfficeUserManager userManager, IDbProviderFactoryCreator dbProviderFactoryCreator, - IEnumerable databaseProviderMetadata) + IEnumerable databaseProviderMetadata, + ILocalizedTextService localizedTextService, + IMetricsConsentService metricsConsentService) { _userService = userService ?? throw new ArgumentNullException(nameof(userService)); _databaseBuilder = databaseBuilder ?? throw new ArgumentNullException(nameof(databaseBuilder)); @@ -58,6 +65,37 @@ namespace Umbraco.Cms.Infrastructure.Install.InstallSteps _userManager = userManager ?? throw new ArgumentNullException(nameof(userManager)); _dbProviderFactoryCreator = dbProviderFactoryCreator ?? throw new ArgumentNullException(nameof(dbProviderFactoryCreator)); _databaseProviderMetadata = databaseProviderMetadata; + _localizedTextService = localizedTextService; + _metricsConsentService = metricsConsentService; + } + + // Scheduled for removal in V12 + [Obsolete("Please use constructor that takes an IMetricsConsentService and ILocalizedTextService instead")] + public NewInstallStep( + IUserService userService, + DatabaseBuilder databaseBuilder, + IHttpClientFactory httpClientFactory, + IOptions passwordConfiguration, + IOptions securitySettings, + IOptionsMonitor connectionStrings, + ICookieManager cookieManager, + IBackOfficeUserManager userManager, + IDbProviderFactoryCreator dbProviderFactoryCreator, + IEnumerable databaseProviderMetadata) + : this( + userService, + databaseBuilder, + httpClientFactory, + passwordConfiguration, + securitySettings, + connectionStrings, + cookieManager, + userManager, + dbProviderFactoryCreator, + databaseProviderMetadata, + StaticServiceProvider.Instance.GetRequiredService(), + StaticServiceProvider.Instance.GetRequiredService()) + { } public override async Task ExecuteAsync(UserModel user) @@ -89,6 +127,8 @@ namespace Umbraco.Cms.Infrastructure.Install.InstallSteps if (!resetResult.Succeeded) throw new InvalidOperationException("Could not reset password: " + string.Join(", ", resetResult.Errors.ToErrorMessage())); + _metricsConsentService.SetConsentLevel(user.TelemetryLevel); + if (user.SubscribeToNewsLetter) { var values = new NameValueCollection { { "name", admin.Name }, { "email", admin.Email } }; @@ -126,7 +166,12 @@ namespace Umbraco.Cms.Infrastructure.Install.InstallSteps minCharLength = _passwordConfiguration.RequiredLength, minNonAlphaNumericLength = _passwordConfiguration.GetMinNonAlphaNumericChars(), quickInstallSettings, - customInstallAvailable = !GetInstallState().HasFlag(InstallState.ConnectionStringConfigured) + customInstallAvailable = !GetInstallState().HasFlag(InstallState.ConnectionStringConfigured), + consentLevels = Enum.GetValues(typeof(TelemetryLevel)).Cast().ToList().Select(level => new + { + level, + description = GetTelemetryLevelDescription(level), + }), }; } } @@ -143,6 +188,14 @@ namespace Umbraco.Cms.Infrastructure.Install.InstallSteps } } + private string GetTelemetryLevelDescription(TelemetryLevel telemetryLevel) => telemetryLevel switch + { + TelemetryLevel.Minimal => _localizedTextService.Localize("analytics", "minimalLevelDescription"), + TelemetryLevel.Basic => _localizedTextService.Localize("analytics", "basicLevelDescription"), + TelemetryLevel.Detailed => _localizedTextService.Localize("analytics", "detailedLevelDescription"), + _ => throw new ArgumentOutOfRangeException(nameof(telemetryLevel), $"Did not expect telemetry level of {telemetryLevel}") + }; + private InstallState GetInstallState() { var installState = InstallState.Unknown; diff --git a/src/Umbraco.Web.UI.Client/src/install.loader.js b/src/Umbraco.Web.UI.Client/src/install.loader.js index 832e28ad34..cd4c2d6452 100644 --- a/src/Umbraco.Web.UI.Client/src/install.loader.js +++ b/src/Umbraco.Web.UI.Client/src/install.loader.js @@ -1,24 +1,25 @@ LazyLoad.js([ - 'lib/jquery/jquery.min.js', + 'lib/jquery/jquery.min.js', - 'lib/angular/angular.min.js', - 'lib/angular-cookies/angular-cookies.min.js', - 'lib/angular-touch/angular-touch.min.js', - 'lib/angular-sanitize/angular-sanitize.min.js', - 'lib/angular-messages/angular-messages.min.js', - 'lib/angular-aria/angular-aria.min.js', - 'lib/underscore/underscore-min.js', - 'lib/angular-ui-sortable/sortable.min.js', + 'lib/angular/angular.min.js', + 'lib/angular-cookies/angular-cookies.min.js', + 'lib/angular-touch/angular-touch.min.js', + 'lib/angular-sanitize/angular-sanitize.min.js', + 'lib/angular-messages/angular-messages.min.js', + 'lib/angular-aria/angular-aria.min.js', + 'lib/underscore/underscore-min.js', + 'lib/angular-ui-sortable/sortable.min.js', + 'lib/nouislider/nouislider.min.js', - 'js/utilities.min.js', + 'js/utilities.min.js', - 'js/installer.app.min.js', - 'js/umbraco.directives.min.js', - 'js/umbraco.installer.min.js' + 'js/installer.app.min.js', + 'js/umbraco.directives.min.js', + 'js/umbraco.installer.min.js' ], function () { - jQuery(document).ready(function () { - angular.bootstrap(document, ['umbraco']); - }); + jQuery(document).ready(function () { + angular.bootstrap(document, ['umbraco']); + }); } ); diff --git a/src/Umbraco.Web.UI.Client/src/installer/steps/user.controller.js b/src/Umbraco.Web.UI.Client/src/installer/steps/user.controller.js index b03282c62e..b4aa8eedf5 100644 --- a/src/Umbraco.Web.UI.Client/src/installer/steps/user.controller.js +++ b/src/Umbraco.Web.UI.Client/src/installer/steps/user.controller.js @@ -1,27 +1,106 @@ -angular.module("umbraco.install").controller("Umbraco.Install.UserController", function($scope, installerService) { +angular.module("umbraco.install").controller("Umbraco.Install.UserController", function ($scope, $sce, installerService) { - $scope.majorVersion = Umbraco.Sys.ServerVariables.application.version; - $scope.passwordPattern = /.*/; - $scope.installer.current.model.subscribeToNewsLetter = false; + $scope.majorVersion = Umbraco.Sys.ServerVariables.application.version; + $scope.passwordPattern = /.*/; + $scope.installer.current.model.subscribeToNewsLetter = $scope.installer.current.model.subscribeToNewsLetter || false; + $scope.installer.current.model.telemetryLevel = $scope.installer.current.model.telemetryLevel || $scope.installer.current.model.consentLevels[1].level; - if ($scope.installer.current.model.minNonAlphaNumericLength > 0) { - var exp = ""; - for (var i = 0; i < $scope.installer.current.model.minNonAlphaNumericLength; i++) { - exp += ".*[\\W].*"; - } - //replace duplicates - exp = exp.replace(".*.*", ".*"); - $scope.passwordPattern = new RegExp(exp); + if ($scope.installer.current.model.minNonAlphaNumericLength > 0) { + var exp = ""; + for (var i = 0; i < $scope.installer.current.model.minNonAlphaNumericLength; i++) { + exp += ".*[\\W].*"; + } + //replace duplicates + exp = exp.replace(".*.*", ".*"); + $scope.passwordPattern = new RegExp(exp); + } + + $scope.consentTooltip = { + show: false, + event: null + }; + + if ('noUiSlider' in window) { + let consentSliderStartLevel = 2; + const initialConsentLevel = $scope.installer.current.model.consentLevels.findIndex(x => x.level === $scope.installer.current.model.telemetryLevel); + if (initialConsentLevel !== -1) { + consentSliderStartLevel = initialConsentLevel + 1; } - $scope.validateAndInstall = function() { - installerService.install(); - }; + const sliderOptions = + { + "start": consentSliderStartLevel, + "step": 1, + "tooltips": [false], + "range": { + "min": 1, + "max": 3 + }, + pips: { + mode: 'values', + density: 50, + values: [1, 2, 3], + "format": { + to: function (value) { + return $scope.installer.current.model.consentLevels[value - 1].level; + }, + from: function (value) { + return Number(value); + } + } + } + }; - $scope.validateAndForward = function(){ - if (this.myForm.$valid) { - installerService.forward(); - } - }; + const consentSlider = document.getElementById("consentSlider"); + if (consentSlider) { + window.noUiSlider.create(consentSlider, sliderOptions); + consentSlider.noUiSlider.on('change', onChangeConsent); + + const pips = consentSlider.querySelectorAll('.noUi-value'); + + $(consentSlider).on('$destroy', function () { + consentSlider.noUiSlider.off(); + }); + + pips.forEach(function (pip) { + pip.addEventListener('mouseenter', function (e) { + $scope.$apply(function () { + const value = pip.getAttribute('data-value'); + $scope.consentTooltip.show = true; + $scope.consentTooltip.event = e; + $scope.consentTooltip.description = $sce.trustAsHtml($scope.installer.current.model.consentLevels[value - 1].description); + }); + }); + + pip.addEventListener('mouseleave', function () { + $scope.$apply(function () { + $scope.consentTooltip.show = false; + $scope.consentTooltip.event = null; + $scope.consentTooltip.description = ''; + }); + }); + + pip.addEventListener('click', function () { + const value = pip.getAttribute('data-value'); + consentSlider.noUiSlider.set(value); + }); + }); + } + } + + $scope.validateAndInstall = function () { + installerService.install(); + }; + + $scope.validateAndForward = function () { + if (this.myForm.$valid) { + installerService.forward(); + } + }; + + function onChangeConsent(values) { + const result = Number(values[0]); + $scope.installer.current.model.telemetryLevel = $scope.installer.current.model.consentLevels[result - 1].level; + }; }); diff --git a/src/Umbraco.Web.UI.Client/src/installer/steps/user.html b/src/Umbraco.Web.UI.Client/src/installer/steps/user.html index 44ee16c840..9049512c8c 100644 --- a/src/Umbraco.Web.UI.Client/src/installer/steps/user.html +++ b/src/Umbraco.Web.UI.Client/src/installer/steps/user.html @@ -1,85 +1,88 @@

Install Umbraco

-

Enter your name, email and password for this Umbraco installation.

+ +

Enter your name, email and password to install Umbraco with its default settings, alternatively you can customize + your installation

+
+
- +
+
- + Your email will be used as your login
+
- + At least {{installer.current.model.minCharLength}} characters long + - At least {{installer.current.model.minNonAlphaNumericLength}} symbol{{installer.current.model.minNonAlphaNumericLength > 1 ? 's' : ''}} + At least {{installer.current.model.minNonAlphaNumericLength}} + symbol{{installer.current.model.minNonAlphaNumericLength > 1 ? 's' : ''}}
+ +
+ +
+
+
+ + +
+
+
+
+
+
-
-
-
-
- Database Configuration -
-
-
-
- -
-
{{installer.current.model.quickInstallSettings.displayName}}
-
-
-
- -
-
{{installer.current.model.quickInstallSettings.defaultDatabaseName}}
-
-
-
-
-
-
- -
-
-
-
-
- -
-
-
-
+
- - + + + +
+
+
diff --git a/src/Umbraco.Web.UI.Client/src/less/installer.less b/src/Umbraco.Web.UI.Client/src/less/installer.less index 114aa6f498..61895ff793 100644 --- a/src/Umbraco.Web.UI.Client/src/less/installer.less +++ b/src/Umbraco.Web.UI.Client/src/less/installer.less @@ -17,146 +17,155 @@ // Umbraco Components @import "components/umb-loader.less"; +@import "components/tooltip/umb-tooltip.less"; -[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak { - display: none !important; +[ng\:cloak], +[ng-cloak], +[data-ng-cloak], +[x-ng-cloak], +.ng-cloak, +.x-ng-cloak { + display: none !important; } html { - background: url('../img/installer.svg') no-repeat center center fixed; - background-size: cover; + background: url('../img/installer.svg') no-repeat center center fixed; + background-size: cover; } body { - margin: 0; - padding: 0; - height: 100%; - width: 100%; - font-family: @baseFontFamily; - font-size: @baseFontSize; - line-height: @baseLineHeight; - color: @textColor; - vertical-align: middle; - text-align: center; - // better font rendering - -webkit-font-smoothing: antialiased; - font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; + margin: 0; + padding: 0; + height: 100%; + width: 100%; + font-family: @baseFontFamily; + font-size: @baseFontSize; + line-height: @baseLineHeight; + color: @textColor; + vertical-align: middle; + text-align: center; + // better font rendering + -webkit-font-smoothing: antialiased; + font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; } #logo { - position: absolute; - top: 20px; - left: 20px; - opacity: 0.8; - z-index: 777; + position: absolute; + top: 20px; + left: 20px; + opacity: 0.8; + z-index: 777; } + #installer { - margin: auto; - background: @white; - width: 80%; - max-width: 750px; - height: 640px; - text-align: left; - padding: 30px; - z-index: 667; - border-radius: 6px; - box-shadow: 0 2px 4px rgba(0,0,0,0.16); + margin: auto; + background: @white; + width: 80%; + max-width: 750px; + height: 640px; + text-align: left; + padding: 30px; + z-index: 667; + border-radius: 6px; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.16); } #overlay { - position: absolute; - top: 0; - right: 0; - left: 0; - bottom: 0; - background: @purple-d2; - z-index: 666; + position: absolute; + top: 0; + right: 0; + left: 0; + bottom: 0; + background: @purple-d2; + z-index: 666; } .loading #overlay { - opacity: 0.5; - display: block !important; + opacity: 0.5; + display: block !important; } #fact { + color: @white; + text-shadow: 0px 0px 4px @black; + font-size: 25px; + text-align: left; + line-height: 35px; + z-index: 667; + height: 600px; + width: 750px; + + h2 { + font-size: 35px; + border-bottom: 1px solid @white; + padding-bottom: 10px; + margin-bottom: 20px; color: @white; - text-shadow: 0px 0px 4px @black; - font-size: 25px; - text-align: left; - line-height: 35px; - z-index: 667; - height: 600px; - width: 750px; + } - h2 { - font-size: 35px; - border-bottom: 1px solid @white; - padding-bottom: 10px; - margin-bottom: 20px; - color: @white; - } - - a { - color: @white; - } + a { + color: @white; + } } #feedback { - color: @white; - text-shadow: 0px 0px 4px @black; - font-size: 14px; - text-align: center; - line-height: 20px; - z-index: 667; - bottom: 20px; - right: 0; - left: 0; - height: 25px; - position: absolute; + color: @white; + text-shadow: 0px 0px 4px @black; + font-size: 14px; + text-align: center; + line-height: 20px; + z-index: 667; + bottom: 20px; + right: 0; + left: 0; + height: 25px; + position: absolute; } h1 { - border-bottom: 1px solid @gray-10; - padding-bottom: 10px; - color: @gray-2; + border-bottom: 1px solid @gray-10; + padding-bottom: 10px; + color: @gray-2; } -.error h1, .error .message, span.error { - color: @red; +.error h1, +.error .message, +span.error { + color: @red; } legend { - font-size: 14px; - font-weight: bold + font-size: 14px; + font-weight: bold } input.ng-dirty.ng-invalid { - border-color: @pink; - color: @pink; + border-color: @pink; + color: @pink; } .disabled { - opacity: 0.6; + opacity: 0.6; } #installer label.control-label, #installer .constrol-label { - padding-top: 5px !important; + padding-top: 5px !important; } .controls { - text-align: left; + text-align: left; - small { - display: block; - color: @gray-3; - } + small { + display: block; + color: @gray-3; + } } #installer .input-readonly-text { @@ -168,101 +177,153 @@ input.ng-dirty.ng-invalid { } .absolute-center { - margin: auto; - position: absolute; - top: 0; - left: 0; - bottom: 0; - right: 0; + margin: auto; + position: absolute; + top: 0; + left: 0; + bottom: 0; + right: 0; } .fade-hide, .fade-show { - transition: all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s; + transition: all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s; } .fade-hide { - opacity: 1; + opacity: 1; } .fade-hide.fade-hide-active { - opacity: 0; + opacity: 0; } .fade-show { - opacity: 0; + opacity: 0; } .fade-show.fade-show-active { - opacity: 1; + opacity: 1; } .umb-installer-loader { - margin: 0; - width: 0; - z-index: 777; + margin: 0; + width: 0; + z-index: 777; - .umb-loader { - background-color: @white; - height: 5px; - } + .umb-loader { + background-color: @white; + height: 5px; + } } .permissions-report { - overflow: auto; - height: 320px; - margin: 0; - display: block; - padding: 0; + overflow: auto; + height: 320px; + margin: 0; + display: block; + padding: 0; } -.permissions-report > li { - list-style: none; +.permissions-report>li { + list-style: none; } .permissions-report h4 { - margin: 7px; + margin: 7px; } .upgrade-report { - overflow: auto; - height: 280px; - display: block; + overflow: auto; + height: 280px; + display: block; } select { - width: 320px; + width: 320px; } #ysod { - height: 500px; - width: 100%; - overflow: auto; - border: none; + height: 500px; + width: 100%; + overflow: auto; + border: none; } #starterKits { - .thumbnails { - min-height: 128px; - padding-left: 0; + .thumbnails { + min-height: 128px; + padding-left: 0; + } + + .thumbnail { + position: relative; + cursor: pointer; + + small { + padding: 10px 10px 5px; + display: inline-block; } - .thumbnail { - position: relative; - cursor: pointer; - - small { - padding: 10px 10px 5px; - display: inline-block; - } - - img { - position: relative; - z-index: 100; - } + img { + position: relative; + z-index: 100; } + } - .btn-link { - padding-left: 0; - } + .btn-link { + padding-left: 0; + } +} + +.umb-tooltip { + border: 1px solid @ui-action-border; + max-width: 500px; +} + +#consentSliderWrapper { + margin-bottom: 40px; +} + +#consentSlider { + .noUi-target { + background: linear-gradient(to bottom, @grayLighter 0%, @grayLighter 100%); + box-shadow: none; + border-radius: 20px; + height: 8px; + border: 1px solid @inputBorder; + + &:focus, + &:focus-within { + border-color: @inputBorderFocus; + } + } + + .noUi-handle { + cursor: grab; + border-radius: 100px; + border: none; + box-shadow: none; + width: 20px !important; + height: 20px !important; + right: -10px !important; // half the handle width + top: -1px; + background-color: @blueExtraDark; + } + + .noUi-handle::before { + display: none; + } + + .noUi-handle::after { + display: none; + } + + .noUi-value { + cursor: pointer; + } + + .noUi-pips-horizontal { + height: 40px; + } } diff --git a/src/Umbraco.Web.UI.Client/src/views/dashboard/settings/analytics.html b/src/Umbraco.Web.UI.Client/src/views/dashboard/settings/analytics.html index ad798dc613..10438a4565 100644 --- a/src/Umbraco.Web.UI.Client/src/views/dashboard/settings/analytics.html +++ b/src/Umbraco.Web.UI.Client/src/views/dashboard/settings/analytics.html @@ -37,9 +37,9 @@
{{vm.sliderVal}} - +
-
We will send: + We will send:
- Anonymized site ID, umbraco version, and packages installed.
- Number of: Root nodes, Content nodes, Macros, Media, Document Types, Templates, Languages, Domains, User Group, Users, Members, and Property Editors in use.
- System information: Webserver, server OS, server framework, server OS language, and database provider.