logo

[ELMA3] Кастомные формы задач

Любые задачи в системе ELMA имеют форму представления по умолчанию. Она генерируется автоматически. В большинстве случаев стандартные формы представления бывают удобны. К тому же при внедрении системы не требуется тратить время на их создание. Однако иногда требуется отображать задачи иным образом, когда необходима разметка страницы, отличная от стандартной. В этом случае используются кастомные формы задач. Кастомные формы могут быть созданы не только для задач, но и для документов, объектов CRM и других объектов системы.

В этой статье мы подробно остановимся на том, как можно создать свою собственную форму задачи в бизнес-процессе.

Для начала необходимо создать файл *.cshtml в папке ...\ELMA3-Standart(Express)\UserConfig\WebApplication. Более подробно о создании и месторасположении файла описано здесь.

Теперь открываем файл в любом текстовом редакторе.

Так как формы создаются с помощью разметки .Net Razor, мы можем использовать HTML-разметку при создании формы.

Чтобы создать новую форму задачи в процессе необходимо ввести следующее пространство имён:

@using EleWise.ELMA.BPM.Web.Tasks.Models 
@using (var data = new ObjectViewData(this, Model.Entity)) { }

где:

@using EleWise.ELMA.BPM.Web.Tasks.Models – необходимо для отображения задачи в процессе 
@using (var data = new ObjectViewData(this, Model.Entity)) – необходимо для правильного отображения переменных и корректной работы скриптов в ELMA

Вся остальная разметка выполнятся между фигурных скобок.

Рассмотрим основные примеры отображения контекстных переменных на форму:

@Html.Caption – название добавляемого поля 
@Html.EditorOrDisplay – добавление редактируемого поля 
@Html.Display – добавление нередактируемого поля 
@Html.EditableProperty – вывод атрибута с названием 
@Html.Property – вывод переменной в режиме «Только для чтения» 
@Html.Editor - вывод поля редактирования (без названия). 
("Entity.<название атрибута>", a => {}) – добавление самого поля

Переменная типа "блок" отображается так же, как и остальные контекстные переменные:

@Html.EditableProperty("Entity.blok")

При этом можно выводить не все свойства блока, а только добавленные в контекст этой задачи, делается это так:

@Html.TableFormStart()
	@Html.Property("Entity.blok", a => { 
		a.TablePartParentId = Model.Entity.Id; 
		a.ViewProviderUid = EleWise.ELMA.Workflow.Web.Integration.WorkflowTaskObjectViewItemProvider.UID;
		a.ViewItemId = Model.Task.Id.ToString(); 
	}) 
@Html.TableFormEnd()

Ниже приведён пример кастомной формы задачи:

Рис. 1. Пример кастомной формы задачи

В этом примере реализованы:

  1. Раскрывающийся список.
  2. Разметка полей и названия атрибутов.
  3. Таблица, при заполнении которой динамически подсчитывается итог.
  • Раскрывающийся список:
@(Html.CollapsiblePanel() // добавляем раскрывающийся список 
	.Id(ViewData.TemplateInfo.GetFullHtmlFieldId("FIO")) // присваиваем ей ID ("FIO")
	.Header(SR.T("ФИО")) //указываем название панели, а так же будет ли сохраняться раскрытие панели или нет .SaveState(false) 
	.Class("Gray_Input_Separator") // указываем цвет панели
	.Expanded(true)
	.Content(@<text> 
	</text>).Render()) // закрывающие теги раскрывающегося списка

    Внимание!

    Для того чтобы автоматически получить Итог (использовано в нашем примере на рисунке 1 выше), достаточно написать сценарий в ELMA и в дальнейшем указать его на свойствах, при изменении которых будет срабатывать метод.

    public virtual void OnChangeItog (Context context, EleWise.ELMA.Model.Views.FormViewBuilder<Context> form)
    {
       context.I1 = context.K1*context.S1; 
       context.I2 = context.K2*context.S2; 
       context.Itog= context.I1+context.I2;
    }
    
    

    То есть те сценарии, которые работают в стандартной форме, будут работать и с разметкой Razor при условии, что добавлено:

    @using (var data = new ObjectViewData(this, Model.Entity))

    Окончательный вариант выглядит так:

    @using EleWise.ELMA.BPM.Web.Tasks.Models 
    @using EleWise.ELMA.Web.Mvc.Html.Forms
    
    @{
    	var onChangeScriptName = "OnChangeItog(EleWise.ELMA.Model.Entities.ProcessContext.P_111,
    EleWise.ELMA.Model.Views.FormViewBuilder`1[[EleWise.ELMA.Model.Entities.ProcessContext.P_111]]) - OnChangeItog(Context context, FormViewBuilder<Context> form)";
    }
    @using (var data = new ObjectViewData(this, Model.Entity))
    {
    	
        @(Html.CollapsiblePanel()
            .Id(ViewData.TemplateInfo.GetFullHtmlFieldId("FIO"))
            .Header(SR.T("ФИО"))
            .SaveState(false)
            .Class("Gray_Input_Separator")
            .Expanded(true)
            .Content(@<text> 
            
      		<table width="100%" border="0" cellpadding="0" cellspacing="0">
    			<tbody>
    				<tr>
    					<td style="width: 50%;">
    						<div class="table-form-container" >
    							<table class="table-form table-ColumnItem">
    								<tbody>
    									<tr hidecount="0">
    										<td class="table-SingleColumnItem" colspan="2">
    											@Html.TableFormStart()
    										       	@Html.EditableProperty("Entity.Familiya")
    										       	@Html.EditableProperty("Entity.Imya")
    										       	@Html.EditableProperty("Entity.Otchestvo")
    										    @Html.TableFormEnd()
    										</td>
    									</tr>
    								</tbody>
    							</table>
    						</div>
    					</td>
    					<td style="width: 50%;">
    						<div class="table-form-container">
    							<table class="table-form table-ColumnItem">
    								<tbody>
    									<tr hidecount="0">
    										<td class="table-SingleColumnItem" colspan="2">
    											@Html.TableFormStart()
    										       	@Html.EditableProperty("Entity.Blok")
    										   @Html.TableFormEnd()
    										</td>
    									</tr>
    								</tbody>
    							</table>
    						</div>
    					</td>
    				</tr>
    			</tbody>
    		</table>                
           
        </text>).Render())
      
        @(Html.CollapsiblePanel()
            .Id(ViewData.TemplateInfo.GetFullHtmlFieldId("Table"))
            .Header(SR.T("Таблица"))
            .SaveState(true)
            .Class("Gray_Input_Separator")
            .Expanded(false)
            .Content(@<text>
            <div style="padding: 10px;">
                <table id="@(ViewData.TemplateInfo.GetFullHtmlFieldId("TableComponent"))">
                <tbody>
                    <tr>
                        <td class="table-title">
                        </td>
                        <td class="table-title">
                            <P>Количество</P>
                        </td>
                        <td class="table-title">
                            <P>Сумма</P>
                        </td>
                        <td class="table-title">
                            <P>Итог</P>
                        </td>
                    </tr>
                    <tr>
                        <td class="table-title">
                            <P>1</P>
                        </td>
                        <td>
                            @Html.Editor("Entity.K1", a => {
                            	a.OnChangeScriptName = onChangeScriptName;
                            })
                        </td>
                        <td>
                        	@Html.Editor("Entity.S1", a => {
                            	a.OnChangeScriptName = onChangeScriptName;
                            })
                        </td>
                        <td id="@(ViewData.TemplateInfo.GetFullHtmlFieldId("Entity.I1"))_ValueContainer">
                            @Html.Editor("Entity.I1", a => {})
                        </td>
                    </tr>
                    <tr>
                        <td class="table-title">
                           <P>2</P>
                        </td>
                        <td>
                        	@Html.Editor("Entity.K2", a => {
                            	a.Container("div");
                            	a.OnChangeScriptName = onChangeScriptName;
                            })
                        </td>
                        <td>
                        	@Html.Editor("Entity.S2", a => {
                            	a.Container("div");
                            	a.OnChangeScriptName = onChangeScriptName;
                            })
                        </td>
                        <td id="@(ViewData.TemplateInfo.GetFullHtmlFieldId("Entity.I2"))_ValueContainer">
                            @Html.Editor("Entity.I2", a => {}) 
                        </td>
                    </tr>
                    <tr>
                        <td align="right" colspan="3" class="itog-td">
                            <b>Итог:</b>
                        </td>
                        <td id="@(ViewData.TemplateInfo.GetFullHtmlFieldId("Entity.Itog"))_ValueContainer">
                           @Html.Editor("Entity.Itog", a => { })
                        </td>
                    </tr>
          		</tbody>
                </table>
    			
             </div>
        </text>).Render())
    }
    
    <style>
    #TableComponent .itog-td {
    	vertical-align: middle;
        padding-right: 6px;
    }
    
    #TableComponent, 
    #TableComponent th, 
    #TableComponent td {
      border: 1px solid #d0d5da;
    }
    
    #TableComponent .table-title {
        background: #cbe2ff;
        padding: 8px 6px;
    }
    
    
    </style>