На проекте столкнулись с требованием реализации статистики обращений в разрезе дня и конкретного типа, который реализован через справочник. Статистика должна быть вынесена на виджет. Для выполнения данной задачи была выполнена модификация, позволяющая реализовывать данную функциональность.
В виджетах есть только два типа параметров: Параметр-перечисление и Логический параметр. Для обхода данного ограничения можно использовать Действие, которое доступно для виджетов. Дополнительно понадобится использование прикладного кэша.
Добавляем действие в виджет, устанавливаем тип действия Разрабатываемое
Для реализации выборки по конкретной записи справочника вводим структуру для хранения Id сущности и её отображаемое имя:
/// <summary>
/// Структура для хранения данных персональной настройки для виджета.
/// </summary>
[Public]
partial class WidgetParameterInfo
{
/// <summary>
/// Id сущности.
/// </summary>
public long EntityId { get; set; }
/// <summary>
/// Отображаемое имя.
/// </summary>
public string DisplayValue { get; set; }
}
В клиентском коде вызываем диалог для выбора пользователем сущности, вокруг которой будет организована выборка данных:
public virtual void ExecuteWidgetContextTypeSelectionAction()
{
var typeNames = new List<string>();
var types = /* получение списка сущностей через remote-функцию*/;
foreach (var t in types)
{
// Получение отображаемого имени.
typeNames.Add(t.Name);
}
// Дополнительное значение для всех записей справочника.
typeNames.Add("Все типы");
var contextTypeDialog = Dialogs.CreateInputDialog("Установить тип контекста для виджета");
var contextType = contextTypeDialog.AddSelect("Тип контекста", true).From(typeNames.ToArray<string>());
var buttonApply = contextTypeDialog.Buttons.AddCustom("Применить");
contextTypeDialog.Buttons.AddCancel();
contextTypeDialog.SetOnRefresh((e) =>
{
if (!string.IsNullOrEmpty(contextType.Value))
{
e.AddInformation("Обновите страницу браузера после применения настроек.");
}
});
if (contextTypeDialog.Show() == buttonApply)
{
if (typeNames.Contains(contextType.Value))
{
var result = types.Any(t => t.Name == contextType.Value) ? typeNames.FirstOrDefault(x => x == contextType.Value) : "Все типы";
var clearDate = Calendar.Now.NextDay().NextDay();
var setting = Structures.Module.WidgetParameterInfo.Create();
setting.EntityId = types.Any(t => t.Name == contextType.Value) ? result.Id : 0;
setting.DisplayName = contextType.Value;
var key = string.Format("WidgetConfig~{0}", Users.Current.Id);
Functions.Module.Remote.AddOrUpdateCacheValue(key, setting, clearDate);
}
}
}
В серверном коде добавить отображение значение из кэша для каждого конкретного пользователя:
public virtual string GetWidgetContextTypeSelectionValue()
{
// По умолчанию, виджет выводит данные по всем типам обращений.
var result = "Все типы" ;
Structures.Module.WidgetParameterInfo contextType;
var key = string.Format("WidgetConfig~{0}", Users.Current.Id);
return Cache.TryGetValue(key, out contextType) ? contextType.DisplayValue : result;
}
Если необходимо получить значение из функции выше в коде виджетов ModuleWidgetHandlers.cs
, а для непосредственной обработки в виджетах использовать ключ "WidgetConfig~{0}"
и использовать EntityId для использования в коде:
this.GetWidgetContextTypeSelectionValue()
Также необходимо для обновления данных в кэше создавать фоновый процесс по обновлению данных в кэше:
// Обновление персональных настроек для пользователей.
foreach (var userId in Sungero.CoreEntities.Users.GetAll().Select(e => e.Id))
{
Structures.Module.WidgetParameterInfo contextType;
var key = string.Format("WidgetConfig~{0}", userId);
if (Cache.TryGetValue(key, out contextType))
{
Cache.AddOrUpdate(key, contextType, lifeTime);
}
}
Преимущества | Недостатки |
Возможность использовать справочник в качестве критерия |
Невозможно отследить количество виджетов в одном наборе виджетов, что приводит к одновременному отображению только по одному типу контекста (разные виджеты одного типа используют один и тот же ключ кэша) |
Возможность расширить структуру для добавления Guid сущности (или nameguid) и получения через рефлексию контекстного типа через метаданные .GetProperty().GetValue() для разграничения работы с несколькими свойствами-ссылками и свойствами базового типа (необходимо учитывать ограничения работы структур в кэше) |
При полной перепубликации или дополнительной очистке через свойство "Сбросить прикладной кэш при публикации" кэш настройки для виджетов сбрасывается |
Отпадает необходимость создавать новый виджет для конкретного свойства сущности |
Необходимость обновить страницу с виджетами для обновления выборки |
При добавлении действия становится возможным выбрать контекстную сущность и сделать по ней выборку. Вот как выглядит виджет для нашего примера:
При обновлении страницы будет показана выборка по конкретной сущности:
Для выбора несколько элементов (одной и более записей справочника) необходимо расширить сигнатуру структуры для отображения всех выбранных элементов и поддержать выбор в диалоге через AddSelectMany().
Авторизуйтесь, чтобы написать комментарий