User Preferences module¶
Module description¶
Module name - GR.UserPreferences
This module is created for store and get user preferences values from another modules with a custom configuration for each key, there is a web API that is responsible for all keys, there is validation at values and each key can be registered by several types such as list or text or something else, only the behavior in the UI remains and the configuration at values and validation
Abstractions¶
IUserPreferencesContext
- it contains abstractions to the entities with which the given module worksIUserPreferencesService
- represent the abstraction with that another modules or service can workGetValueByKeyAsync
- get the value of user preference by key name, the value is provided for currently logged userTask<ResultModel<string>> GetValueByKeyAsync(string key);
AddOrUpdatePreferenceSettingAsync
- set value for some key on user preferenceTask<ResultModel> AddOrUpdatePreferenceSettingAsync(string key, string value);
GetPreferenceConfigurationAsync
- get configuration of preference item with user selected optionTask<BaseBuildResponse<object>> GetPreferenceConfigurationAsync(string key);
GetAvailableKeys
- get registered keys
API¶
The api with docs can be found on swagger, for that, you can write in url: http://you_gear_app_url/swagger , the category is UserPreferencesApi
Integration¶
Registration of module¶
Here we have a standard recording of the module with default configurations
//---------------------------------User preferences Module --------------------------------
config.GearServices
.AddUserPreferencesModule<UserPreferencesService>()
.RegisterPreferencesProvider<DefaultUserPreferenceProvider>()
.AddUserPreferencesModuleStorage<UserPreferencesDbContext>(options =>
{
options.GetDefaultOptions(Configuration);
options.EnableSensitiveDataLogging();
});
Register of key¶
For do this is need to bind module extension on startup configuration with interface IServiceCollection
- key need to be unique and not empty
- TPreferenceItem can be anything class that inherit the PreferenceItem class and implement all parent class methods
- The Func is used for set and customize key configurations
/// <summary>
/// Register user preferences key
/// </summary>
/// <typeparam name="TPreferenceItem"></typeparam>
/// <param name="services"></param>
/// <param name="key"></param>
/// <param name="options"></param>
/// <returns></returns>
public static IServiceCollection RegisterUserPreferenceKey<TPreferenceItem>(this IServiceCollection services, string key, Func<TPreferenceItem, TPreferenceItem> options)
where TPreferenceItem : PreferenceItem, new()
{
var provider = IoC.Resolve<DefaultUserPreferenceProvider>("PreferencesProvider_Instance");
provider.RegisterPreferenceItem(key, options(new TPreferenceItem
{
Key = key
}));
return services;
}
Examples¶
List Type¶
Here is an example of register the user time zone preference with key: UserPreferencesResources.UserTimeZoneKey
//Register timeZone
services.RegisterUserPreferenceKey<ListPreferenceItem>(UserPreferencesResources.UserTimeZoneKey, options =>
{
options.IsRequired = true;
options.IsValidValue = value =>
{
var response = new ResultModel();
if (value.IsNullOrEmpty()) return response;
try
{
TimeZoneInfo.FindSystemTimeZoneById(value);
response.IsSuccess = true;
return response;
}
catch (Exception e)
{
response.AddError(e.Message);
}
return response;
};
options.ResolveListItems = selectedZone =>
{
//$"({zone.StandardName}) {zone.Id}"
var data = TimeZoneInfo.GetSystemTimeZones()
.Select(zone =>
new DisplayItem
{
Id = zone.Id,
Label = zone.DisplayName,
Selected = selectedZone == zone.Id
}).ToList();
return Task.FromResult<IEnumerable<DisplayItem>>(data);
};
return options;
});
Text Type¶
here a simple key named someKey
that the value of is required and on save the value must be equal with 5
services.RegisterUserPreferenceKey<TextPreferenceItem>("someKey", options =>
{
options.IsRequired = true;
options.IsValidValue = value =>
{
var response = new ResultModel();
if (value == "5")
{
response.IsSuccess = true;
}
else
{
response.AddError("Value is not equal at 5");
}
return response;
};
return options;
});
Extend¶
To add new preference class, you must inherit from abstract class PreferenceItem and implement the methods, also you can extend current types as ListPreferenceItem and TextPreferenceItem
The implementation of list type
public class ListPreferenceItem : PreferenceItem
{
/// <summary>
/// Type
/// </summary>
public override string Type => "List";
/// <summary>
/// Get configuration
/// </summary>
/// <param name="currentValue"></param>
/// <returns></returns>
public override async Task<BaseBuildResponse<object>> GetConfigurationAsync(string currentValue)
{
var data = await GetListValuesAsync(currentValue);
return new BaseBuildResponse<object>
{
IsSuccess = true,
Result = data,
Type = Type
};
}
/// <summary>
/// Check if is valid
/// </summary>
/// <returns></returns>
public override bool Validate()
{
var isValid = ResolveListItems != null;
return isValid;
}
/// <summary>
/// Task for resolve list of items
/// </summary>
public Func<string, Task<IEnumerable<DisplayItem>>> ResolveListItems = null;
/// <summary>
/// Get list of items
/// </summary>
/// <param name="selected"></param>
/// <returns></returns>
public virtual async Task<IEnumerable<DisplayItem>> GetListValuesAsync(string selected)
{
var items = await ResolveListItems(selected);
return items;
}
}