Base solution for your next web application
Open Closed

Dark Mode: Can we make dark mode user specific? #11178


User avatar
0
qstamps created

Prerequisites

Please answer the following questions before submitting an issue. YOU MAY DELETE THE PREREQUISITES SECTION.

  • What is your product version?
  • v11.2.1
  • What is your product type (Angular or MVC)?
  • Angular
  • What is product framework type (.net framework or .net core)?
  • .net core

If issue is about UI

  • Which theme are you using?
  • Default
  • What are the theme settings?
  • Default

Can we make dark mode user specific? My application is a single tanent application. I want to make the dark mode and light mode user specific not tanent specific. Could you please help me with that?

Thank You :)


3 Answer(s)
  • User Avatar
    0
    qstamps created
    Yeah! I am able to solve that challenge.

    I am sharing the step, hope it will help someone else.

    File 1: MyProject/aspnet-core/src/MyProject.Web.Core/UiCustomization/Metronic/UiThemeCustomizerBase.cs

        protected async Task<T> GetSettingValueForUserAsync<T>(string settingName, int? tenantId, long userId) where T : struct
    
    {
        return (await SettingManager.GetSettingValueForUserAsync(ThemeName + "." + settingName, tenantId ,userId)).To<T>();
    }
    protected async Task<string> GetSettingValueForUserAsync(string settingName, int? tenantId, long userId)
    {
        return await SettingManager.GetSettingValueForUserAsync(ThemeName + "." + settingName, tenantId, userId);
    }
    

    File 2: MyProject/aspnet-core/src/MyProject.Web.Core/UiCustomization/Metronic/ThemeDefaultUiCustomizer.cs N.B: Need to done for every Theme--UiCustomizer.cs

        public async Task<UiCustomizationSettingsDto> GetUiSettings(int? tenantId, long? userId)
    
    {
        var settings = new UiCustomizationSettingsDto
        {
            BaseSettings = new ThemeSettingsDto
            {
                Layout = new ThemeLayoutSettingsDto
                {
                    //DarkMode = await GetSettingValueAsync<bool>(AppSettings.UiManagement.DarkMode)
                    DarkMode = await GetSettingValueForUserAsync<bool>(AppSettings.UiManagement.DarkMode, tenantId, userId > 0 ? (long) userId : 0)
                },
                SubHeader = new ThemeSubHeaderSettingsDto
                {
                    FixedSubHeader = true,
                    //SubheaderStyle = await GetSettingValueAsync(AppSettings.UiManagement.SubHeader.Style),
                   SubheaderStyle = await GetSettingValueForUserAsync(AppSettings.UiManagement.SubHeader.Style, tenantId, userId 0 ? (long)userId : 0),
                    ContainerStyle = "subheader py-2 py-lg-4 subheader-solid toolbar"
                },
                ....
        return settings;
    }
    

    File 3: MyProject/aspnet-core/src/MyProject.Application/UiCustomization/IUiCustomizer.cs

        Task<UiCustomizationSettingsDto> GetUiSettings(***int? tenantId, long? userId***);
    

    File 4: MyProject/aspnet-core/src/MyProject.Application/Configuration/UiCustomizationSettingsAppService.cs

        public async Task<List<ThemeSettingsDto>> GetUiManagementSettings()
    
    {
        var settings = new List<ThemeSettingsDto>();
        var themeCustomizers = _iocResolver.ResolveAll<IUiCustomizer>();
    
        foreach (var themeUiCustomizer in themeCustomizers)
        {
            var themeSettings = await themeUiCustomizer.GetUiSettings(***AbpSession.TenantId, AbpSession.UserId***);
            settings.Add(themeSettings.BaseSettings);
        }
    
        return settings;
    }
    

    File 5: MyProject/aspnet-core/src/MyProject.Application/Sessions/SessionAppService.cs

        public async Task<GetCurrentLoginInformationsOutput> GetCurrentLoginInformations()
    
    {
        .....
            var uiCustomizer = await _uiThemeCustomizerFactory.GetCurrentUiCustomizer();
            output.Theme = await uiCustomizer.GetUiSettings(***AbpSession.TenantId, AbpSession.UserId***);
            ......
    }
    
  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi,

    Thank you for sharing the changes you have made. This setting is actually user based, see https://github.com/aspnetzero/aspnet-zero-core/blob/dev/aspnet-core/src/MyCompanyName.AbpZeroTemplate.Core/Configuration/AppSettingProvider.cs#L213. It's scope is SettingScopes.All which means this setting can be configured for App, Host, Tenant and Users.

    The dark mode button changes the setting for tenant based if the logged in user has permission for visual settings page. If user doesn't have permission for visual settings page, then this button changes the dark mode setting only for the logged in user.

  • User Avatar
    0
    marble68 created

    For anyone coming across this - since anyone who has permissions to set the visual settings for a tenant site, or as a host, site wide, does not have the ability to set their own personal theme - here's a dead simple way to do it. My project is jQuery based.

    In the UiCustomizationViewModel.cs file, add a boolean for personal settings, as I've added PersonalSettings below.

        public class UiCustomizationViewModel
        {
            public string Theme { get; set; }
    
            public List<ThemeSettingsDto> Settings { get; set; }
    
            public bool HasUiCustomizationPagePermission { get; set; }
            public bool PersonalSettings { get; set; }
    
            public ThemeSettingsDto GetThemeSettings(string themeName)
            {
                return Settings.First(s => s.Theme == themeName);
            }
        }
    

    Next, in your UiCustomizationController, you'll want a flag for if the user is setting their personal settings. This could likely be done in reverse, but this is how I did it. Note the new personal parameter with the default value and how it's set on the view model.

            public async Task<ActionResult> Index(bool personal = false)
            {
                var model = new UiCustomizationViewModel
                {
                    Theme = await SettingManager.GetSettingValueAsync(AppSettings.UiManagement.Theme),
                    Settings = await _uiCustomizationAppService.GetUiManagementSettings(),
                    HasUiCustomizationPagePermission = await PermissionChecker.IsGrantedAsync(AppPermissions.Pages_Administration_UiCustomization),
                    PersonalSettings = personal
                };
    
                return View(model);
            }
    

    Then, in the index.cshtml under UiCustomization, you'll need to modify which of the buttons are shown based on the personal settings, like so:

    Change the line that reads:

    @if (Model.HasUiCustomizationPagePermission)
    

    to read

    @if (Model.PersonalSettings==false && Model.HasUiCustomizationPagePermission)
    

    Lastly, you'll want to modify the dropdown menu html in the file Default.cshtml under AppUserMenu.

    In that file, you remove or comment out the if statement that hides visual settings if the user has permission to visual settings. Comment out this if statement:

    @if (!Model.HasUiCustomizationPagePermission)
    

    Then, modify the action to pass the parameter personal=true so the controller / page knows you're wanting to edit your personal settings.

    It should look like this:

    @Url.Action("Index", "UiCustomization",new {personal=true})
    

    That's it!

    Now, an admin can set a system default, but use another theme for themselves. Users without a custom theme will get the default.

    I've tested at host and tenant level and haven't seen any issues with it.

    This allows for a better admin user experience.