logo

[ELMA3] Создание портлета в модуле

Перед созданием портлета необходимо ознакомиться со статьёй Создание веб-модуля для приложения.

Итак, у нас есть модуль EleWise.ELMA.CRMExtension. Там уже есть созданные страницы и контроллеры, в этом примере они нам понадобятся.

В первую очередь, нужно создать папку для портлета. Папку создаем в веб-части модуля и называем её Portlets.

Теперь создаем сам портлет. Нажимаем правой кнопкой мыши по папке Portlets – Add – New Item – Веб портлет Elma 3.

В результате у нас должно получиться следующее:

У нас сразу создалось несколько объектов:

  1. Представление CompanyPortlet.cshtml.
  2. Класс CompanyPortlet.cshtml.cs, содержащий в себе 3 класса для настройки портлета.

Созданное представление содержит простенький код и отображает простую информацию:

@model EleWise.ELMA.CRMExtension.Web.Portlets.CompanyPortletPersonalization
<p>@EleWise.ELMA.SR.T("Добро пожаловать в портлет!")</p>
<p style="font-weight: bold">@EleWise.ELMA.SR.T("Ваш текст"):</p>
<p>@Model.Text</p>

В нашем примере мы отобразим табличку с компаниями, которые отображаются на представлении Index.cshtml.

Для этого в CompanyController добавляем новое действие:

        [CustomGridAction]
        public  ActionResult GridForPortlet(GridCommand command, [Bind(Prefix = "DataFilter")]ICompanyFilter filter)
        {
            if (filter == null)
            {
                filter = InterfaceActivator.Create<ICompanyFilter>();
            }

            var data = CreateGridData(command, filter);

            return GridView<ICompanyFilter>(data);
        }

И создаем представление GridForPortlet.cshtml, на котором отобразим четыре поля объекта Company:

  • Имя;
  • Автор создания;
  • Дату создания;
  • ИНН.
@using EleWise.ELMA.CRMExtension.Models;
@inherits EleWise.ELMA.Web.Mvc.DynamicViewControl<EleWise.ELMA.Web.Mvc.Models.Grids.GridData<ICompany, ICompanyFilter>>

@(DynamicGrid("Companies", Model)
        .Columns(c =>
        {
            c.For(m => m.Name).Link(m => Url.Action("Details", "Company", new { id = m.Id }));
            c.For(m => m.CreationAuthor);
            c.For(m => m.CreationDate);
            c.For(m => m.INN);
        })
            .Action("GridForPortlet"))

Теперь переходим к настройкам портлета. Открываем файл CompanyPortlet.chhtml.cs, ищем функцию Content в классе CompanyPortlet. Имеющуюся там строку return html.Partial("/Modules/EleWise.ELMA.CRMExtension.Web/Portlets/CompanyPortlet.cshtml", data); нужно заменить на return RenderContentAction(html, "GridForPortlet", "Company", RouteProvider.AreaName, data);

Данная строчка вызовет действие GridForPortlet с контроллера Company.

Настройки портлета

Переходим к настройкам портлета. В первую очередь, нужно изменить отображаемое имя и описание нашего портлета. За отображаемое имя отвечает свойство Name в классе CompanyPortlet, за описание – свойство Description. Назовём наш портлет Созданные компании, а описание к нему – «Портлет для отображения всех созданных компаний»

Примечание. Не забывайте про локализацию. Чтобы строка локализировалась и была переведена на другие языки, используйте функцию EleWise.ELMA.SR.T(“тут строка для локализации”);

 /// <summary>
        /// Описание портлета
        /// </summary>
        public override string Description
        {
            get { return SR.T("Портлет для отображения всех созданных компаний"); }
        }

        /// <summary>
        /// Текст заголовка
        /// </summary>
        public override string Name
        {
            get { return SR.T("Созданные компании");}
        }

Изменим картинку, которая отображается в левом верхнем углу портлета. Для этого перейдем в конструктор класса CompanyPortlet(), и изменим существующий путь до картинки _profile.ImageUrl = "#x16/Unk16.gif"; на следующий _profile.ImageUrl = "#x16/company.png";

Примечание
Все картинки лежал по пути «~Web\Content\Images». Конструкция «#x16», отвечающая за размер картинки,означает, что картинка будет лежать в папке «~Web\Content\Images\x16». Кроме этого есть еще несколько доступных вариантов: x10, x12, x24, x32, x64, x120.

Также вы можете расширить всплывающее окно Настройки портлета в веб-приложении, расширив его собственными полями. Для этого перейдем к классу CompanyPortletPersonalization и добавим туда следующие два свойства:

[EleWise.ELMA.Web.Mvc.Portlets.Personalization(EleWise.ELMA.Web.Mvc.Portlets.PersonalizationScope.User)]
        [System.ComponentModel.Category("Отображение моего портлета")]
        [EleWise.ELMA.Model.Attributes.DisplayName(typeof(CompanyPortletPersonalization_SR), "P_CustomUser")]
        public IUser CustomUser{ get; set; }

        [EleWise.ELMA.Web.Mvc.Portlets.Personalization(EleWise.ELMA.Web.Mvc.Portlets.PersonalizationScope.User)]
        [System.ComponentModel.Category("Отображение моего портлета 2")]
        [EleWise.ELMA.Model.Attributes.DisplayName(typeof(CompanyPortletPersonalization_SR), "P_CustomUserAnotherCategory")]
        public IUser CustomUserAnotherCategory { get; set; }

А также в классе CompanyPortletPersonalization_SR добавим:

        public static string P_CustomUser
        {
            get { return EleWise.ELMA.SR.T("Произвольный пользователь"); }
        }

        public static string P_CustomUserAnotherCategory
        {
            get { return EleWise.ELMA.SR.T("Произвольный пользователь в другой категории"); }
        }

Эти два добавленные свойства отвечают за отображаемое имя в настройках портлета. Но чтобы они применились к нужному вам свойству, нужно добавить атрибут DisplayName, а в конструктор атрибута передать тип класса и имя свойство (см. выше пример).

Атрибут Category создает в настройках портлета новую категорию для каждого нового имени. Таким образом, вы можете либо расширить уже существующие категории, либо добавить новые.

Атрибут Personalization отвечает за настройку уровня персонализации. Здесь может быть только два случая: User (уровень одного пользователя) и Shared (уровень всех пользователей).

Едем дальше. Переопределим ещё часть свойств портлета.

 	  /// <summary>
        /// Автор (имя компании)
        /// </summary>
        public override string Author
        {
            get { return @"ООО ""Рога и копыта"" "; }
        }
        
        /// <summary>
        /// Категория
        /// </summary>
        public override string Category
        {
            get { return SR.T("Проверка категории"); }
        }
        
        /// <summary>
        /// Модуль (идентификатор модуля, в котором лежит портлет)
        /// </summary>
        public override string Module
        {
            get { return "EleWise.ELMA.CRMExtension"; }
        }

        /// <summary>
        /// Веб-сайт (тут должен быть веб-сайт компании-разработчика)
        /// </summary>
        public override string WebSite
        {
            get { return "http://roga-kopita.ru"; }
 }

Данные свойства отображаются в Администрирование – Портал – Портлеты.

Если не переопределять эти свойства, то будут возвращены стандартные для них значения:

  • для свойства Автор вернется EleWise;
  • для свойства Сайт вернется https://www.elma-bpm.ru;
  • для свойства Модуль вернется полное имя модуля;
  • для свойства Категория вернется отображаемое имя модуля (можно посмотреть\изменить в файле Module.txt)

Чтобы можно было на одной странице отображать несколько экземпляров одного портлета переопределите свойство AllowMultipleInstance

        /// <summary>
        /// Разрешено отображать несколько экземпляров на одной странице
        /// </summary>
        public override bool AllowMultipleInstance
        {
            get { return true; }
        }

Портлеты можно отображать в сторонних системах. Для этого нужно переопределить следующие два свойства: AllowGadget и GoodExternalSupported.

        /// <summary>
        /// Разрешить показывать в сторонней системе
        /// </summary>
        public override bool AllowGadget
        {
            get { return true; }
        }

        /// <summary>
        /// Рекомендованный для сторонней системы
        /// </summary>
        public override bool GoodExternalSupported
        {
            get { return true; }
        }

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

        /// <summary>
        /// Можно ли в текущем контексте изменять свойство настроек портлета
        /// Используется при отображении кнопок закрытия, диалога настроек
        /// </summary>
        /// <param name="portletPersonalization">Персонализация</param>
        /// <param name="name"></param>
        /// <param name="path"></param>
        /// <returns></returns>
        public override bool CanChangeProperty(PortletPersonalization portletPersonalization, string name, string path)
        {
            if (name == "Text")
            {
                return false;
            }
            return base.CanChangeProperty(portletPersonalization, name, path);
        }

Можно добавить портлет на страницу с уже заполненными настройками. Для этого нужно переопределить функцию CreateDefaultSettings.

/// <summary>
        /// Создать объект настроек по умолчанию
        /// </summary>
        /// <returns></returns>
        public override PortletPersonalization CreateDefaultSettings(string path)
        {
            var personalization = base.CreateDefaultSettings(path) as CompanyPortletPersonalization;
            personalization.Text = "Тестовый текст";
            return personalization;
        }

Теперь каждый портлет по умолчанию будет создаваться с текстом "Тестовый текст".

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

        /// <summary>
        /// Вернуть разметку формы настройки портлета
        /// </summary>
        /// <param name="html">Html helper</param>
        /// <param name="data"></param>
        /// <param name="path"></param>
        /// <returns></returns>
        public override MvcHtmlString Settings(HtmlHelper html, CompanyPortletPersonalization data, string path)
        {
            return RenderSettingsPartialView(html, "CompanyPortlet/CompanyPortletSettings", data);
        }

Добавить свойства в класс CompanyPortletPersonalization. Добавляемые свойства должны быть помечены атрибутом HiddenInput с параметром DisplayValue = false.

        [Personalization(PersonalizationScope.User)]
        [HiddenInput(DisplayValue = false)]
        public string TestText { get; set; }

        [Personalization(PersonalizationScope.User)]
        [HiddenInput(DisplayValue = false)]
        public string TestText2 { get; set; }

И добавить свой файл с разметкой. Данная разметка хранится в файле CompanyPortletSettings.cshtml.

@using EleWise.ELMA
@model EleWise.ELMA.CRMExtension.Web.Portlets.CompanyPortletPersonalization

<table cellpadding="5" style="width:570px">
    <tr>
        <td style="white-space:nowrap">@(SR.T("Тестовый текст:"))</td>
        <td>
            @Html.Editor(m => m.TestText)
        </td>
    </tr>
    
    <tr>
        <td style="white-space:nowrap">@(SR.T("Тестовый текст 2:"))</td>
        <td>
            @Html.Editor(m => m.TestText2)
        </td>
    </tr>
</table>

На заголовок портлета можно повесить гиперссылку. Ссылка по умолчанию устанавливается функцией GetNameUrl. В данном примере ссылка по умолчанию переходит на представление Index.

        /// <summary>
        /// Ссылка текста заголовка
        /// </summary>
        public override string GetNameUrl(UrlHelper urlHelper, CompanyPortletPersonalization data)
        {
            return urlHelper.Action("Index", "Company", new { area = RouteProvider.AreaName });
        }

Установить свою URL-ссылку можно в настройках портлета, заполним поле URL-адрес названия

Функции BeforeRender и BeforeEditRender позволяют вам выполнять определённую логику перед разрисовкой окна настроек портлета. Функция BeforeRender вызывается при редактировании настроек портлета в режиме просмотра главной страницы, BeforeEditRender – в режиме редактирования главной страницы.

Чтобы установить собственную логику для проверки привилегий доступа к портлету, используйте переопределение функции HasPermission().

Пример модуля можно скачать отсюда.

Смотри также: