Настройка виджетов. Параметр-справочник через "Действие"

3 0

На проекте столкнулись с требованием реализации статистики обращений в разрезе дня и конкретного типа, который реализован через справочник. Статистика должна быть вынесена на виджет. Для выполнения данной задачи была выполнена модификация, позволяющая реализовывать данную функциональность.

Контекст

В виджетах есть только два типа параметров: Параметр-перечисление и Логический параметр. Для обхода данного ограничения можно использовать Действие, которое доступно для виджетов. Дополнительно понадобится использование прикладного кэша.

Реализация

Введение действия

Добавляем действие в виджет, устанавливаем тип действия Разрабатываемое

 

Добавление логики

Для реализации выборки по конкретной записи справочника вводим структуру для хранения 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(). 

3
Авторизуйтесь, чтобы оценить материал.
2
Пока комментариев нет.

Авторизуйтесь, чтобы написать комментарий