@model Disco.Web.Areas.Config.Models.DocumentTemplate.ShowModel @using Disco.Services.Documents.ManagedGroups; @using Disco.Services.Interop.ActiveDirectory; @using Disco.Web.Areas.Config.Models.Shared; @{ Authorization.Require(Claims.Config.DocumentTemplate.Show); var canConfig = Authorization.Has(Claims.Config.DocumentTemplate.Configure); var hideAdvanced = Model.DocumentTemplate.UsersLinkedGroup == null && Model.DocumentTemplate.DevicesLinkedGroup == null && Model.DocumentTemplate.FilterExpression == null && Model.DocumentTemplate.OnGenerateExpression == null && Model.DocumentTemplate.OnImportAttachmentExpression == null && Model.TemplateExpressions.All(e => e.All(p => !p.ParseError) && !Model.OnImportUserFlagRules.Any()); var canBulkGenerate = false; var canBulkDownload = false; switch (Model.DocumentTemplate.Scope) { case DocumentTemplate.DocumentTemplateScopes.Device: canBulkGenerate = Authorization.Has(Claims.Config.DocumentTemplate.BulkGenerate) && Authorization.Has(Claims.Device.Actions.GenerateDocuments); canBulkDownload = Authorization.Has(Claims.Device.ShowAttachments) && Model.StoredInstanceCount > 0; break; case DocumentTemplate.DocumentTemplateScopes.Job: canBulkGenerate = Authorization.Has(Claims.Config.DocumentTemplate.BulkGenerate) && Authorization.Has(Claims.Job.Actions.GenerateDocuments); canBulkDownload = Authorization.Has(Claims.Job.ShowAttachments) && Model.StoredInstanceCount > 0; break; case DocumentTemplate.DocumentTemplateScopes.User: canBulkGenerate = Authorization.Has(Claims.Config.DocumentTemplate.BulkGenerate) && Authorization.Has(Claims.User.Actions.GenerateDocuments); canBulkDownload = Authorization.Has(Claims.User.ShowAttachments) && Model.StoredInstanceCount > 0; break; default: throw new InvalidOperationException("Invalid DocumentType Scope"); } ViewBag.Title = Html.ToBreadcrumb("Configuration", MVC.Config.Config.Index(), "Document Templates", MVC.Config.DocumentTemplate.Index(null), Model.DocumentTemplate.Description); if (canConfig) { Html.BundleDeferred("~/ClientScripts/Modules/Disco-PropertyChangeHelpers"); } }
Id: @Html.DisplayFor(model => model.DocumentTemplate.Id)
Statistics: @Model.StoredInstanceCount.ToString("n0") Stored Instance@(Model.StoredInstanceCount == 1 ? null : "s")
Description: @if (canConfig) { @Html.TextBoxFor(model => model.DocumentTemplate.Description) @AjaxHelpers.AjaxSave() @AjaxHelpers.AjaxLoader() } else { if (string.IsNullOrEmpty(Model.DocumentTemplate.Description)) { <None Specified> } else { @Model.DocumentTemplate.Description } }
 
@if (canConfig) { @AjaxHelpers.AjaxLoader() } else { }

If selected the template will not appear in the list of documents to generate.

Scope:

@Model.DocumentTemplate.Scope Scope

This template is generated from @(Model.DocumentTemplate.Scope)s. Any expressions within the Template PDF will be evaluated within the @(Model.DocumentTemplate.Scope) Scope.

@if (canConfig) {
@using (Html.BeginForm(MVC.API.DocumentTemplate.UpdateScope(Model.DocumentTemplate.Id, redirect: true))) { @Html.AntiForgeryToken()
}

Expressions within the Template PDF may need to be updated to reflect any changes to the Document Template Scope.

@if (Model.DocumentTemplate.UsersLinkedGroup != null || Model.DocumentTemplate.DevicesLinkedGroup != null) {

Warning: This Document Template contains Linked Groups, these will be automatically updated to reflect the new Document Template Scope which may result in undesired behaviour.

}
} @if (Model.DocumentTemplate.Scope == DocumentTemplate.DocumentTemplateScopes.Job) {

Job Type Filters:

@if (Model.DocumentTemplate.JobSubTypes.Count > 0) {
    @foreach (var jobType in Model.DocumentTemplate.JobSubTypes.GroupBy(jst => jst.JobType).OrderBy(jtg => jtg.Key.Description)) {
  • @jobType.Key.Description
      @if (jobType.Count() == Model.JobTypes.FirstOrDefault(jt => jt.Id == jobType.Key.Id).JobSubTypes.Count) {
    • [All Sub Types]
    • } else { foreach (var jobSubType in jobType) {
    • @jobSubType.Description
    • } }
  • }
} else { <No Filter> }
@if (canConfig) { Update
@using (Html.BeginForm(MVC.API.DocumentTemplate.UpdateJobSubTypes(Model.DocumentTemplate.Id, null, true))) { @Html.AntiForgeryToken() var selectedTypes = Model.DocumentTemplate.JobSubTypes.Select(jst => jst.JobType).Distinct().ToList(); foreach (var jt in Model.JobTypes) {

@CommonHelpers.CheckboxBulkSelect(string.Format("CheckboxBulkSelect_{0}", jt.Id), "div") @CommonHelpers.CheckBoxList("JobSubTypes", jt.JobSubTypes.OrderBy(jst => jst.Description).ToSelectListItems(Model.DocumentTemplate.JobSubTypes), 2)
} }
}
}
 
@if (canConfig) { @AjaxHelpers.AjaxLoader() } else { }

When a document is generated all form elements will be removed and their content written in place if this option is selected.

PDF Template

@if (canConfig) { }
@if (Model.TemplatePagesHaveAttachmentId.Any(i => !i)) {
@for (int i = 0; i < Model.TemplatePagesHaveAttachmentId.Count; i++) { if (!Model.TemplatePagesHaveAttachmentId[i]) {

Note: Page @(i + 1) does not have a DiscoAttachmentId field.

} }

The DiscoAttachmentId field is replaced with a unique QR Code which identifies the page when it is imported back into Disco ICT.

}
@Html.ActionLinkSmallButton("Download Template", MVC.API.DocumentTemplate.Template(Model.DocumentTemplate.Id)) @if (canConfig && Authorization.Has(Claims.Config.DocumentTemplate.Upload)) {

Select a PDF Template to upload:

@using (Html.BeginForm(MVC.API.DocumentTemplate.Template(Model.DocumentTemplate.Id, true, null), FormMethod.Post, new { enctype = "multipart/form-data" })) { @Html.AntiForgeryToken() }
}

Advanced Options

Filter Expression: @if (canConfig && Authorization.Has(Claims.Config.DocumentTemplate.ConfigureFilterExpression)) { @Html.EditorFor(model => model.DocumentTemplate.FilterExpression) @AjaxHelpers.AjaxRemove() @AjaxHelpers.AjaxSave() @AjaxHelpers.AjaxLoader() } else { if (string.IsNullOrWhiteSpace(Model.DocumentTemplate.FilterExpression)) { <None Specified> } else {
@Model.DocumentTemplate.FilterExpression
} }

This expression will be evaluated to determine if this template is shown in the Generate Document drop-down list. If the template is hidden (see above) this expression is ignored.

On Generated Expression: @if (canConfig && Authorization.Has(Claims.Config.DocumentTemplate.ConfigureFilterExpression)) { @Html.EditorFor(model => model.DocumentTemplate.OnGenerateExpression) @AjaxHelpers.AjaxRemove() @AjaxHelpers.AjaxSave() @AjaxHelpers.AjaxLoader() } else { if (string.IsNullOrWhiteSpace(Model.DocumentTemplate.OnGenerateExpression)) { <None Specified> } else {
@Model.DocumentTemplate.OnGenerateExpression
} }

This expression will be evaluated each time a document is generated from this template.

On Import Expression: @if (canConfig && Authorization.Has(Claims.Config.DocumentTemplate.ConfigureFilterExpression)) { @Html.EditorFor(model => model.DocumentTemplate.OnImportAttachmentExpression) @AjaxHelpers.AjaxRemove() @AjaxHelpers.AjaxSave() @AjaxHelpers.AjaxLoader() } else { if (string.IsNullOrWhiteSpace(Model.DocumentTemplate.OnImportAttachmentExpression)) { <None Specified> } else {
@Model.DocumentTemplate.OnImportAttachmentExpression
} }

This expression will be evaluated each time a document is imported (as an attachment) where it is determined the document was based on this template.

On Import
User Flag Rules:
@if (canConfig && Authorization.Has(Claims.Config.UserFlag.Configure)) { @foreach (var rule in Model.OnImportUserFlagRules) { }
Action User Flag Comments  
<None Specified>
@(rule.AddFlag ? "Assign" : "Remove") @if (Authorization.Has(Claims.Config.UserFlag.Configure)) { @Html.ActionLink(rule.UserFlag.Name, MVC.Config.UserFlag.Index(rule.UserFlag.Id)) } else { @rule.UserFlag.Name } @if (string.IsNullOrWhiteSpace(rule.Comments)) {   } else { @rule.Comments }
using (Html.BeginForm(MVC.API.DocumentTemplate.RemoveOnImportUserFlagRule(Model.DocumentTemplate.Id), FormMethod.Post, new { id = "DocumentTemplate_OnImportUserFlagRules_Remove" })) { @Html.AntiForgeryToken() @Html.Hidden("ruleId", "") } Add User Flag Rule
@switch (Model.DocumentTemplate.Scope) { case "Device":
The user flag will be created/removed against the devices assigned user.
break; case "Job":
The user flag will be created/removed against the jobs associated user.
break; case "User":
The user flag will be created/removed against the user.
break; }
@using (Html.BeginForm(MVC.API.DocumentTemplate.AddOnImportUserFlagRule(Model.DocumentTemplate.Id))) { @Html.AntiForgeryToken()
@foreach (var flag in Model.UserFlags) {
}
(added to the assignment; optional)
}
} else { if (!Model.OnImportUserFlagRules.Any()) { <None Specified> } else { @foreach (var rule in Model.OnImportUserFlagRules) { }
Action User Flag Comments
@(rule.AddFlag ? "Assign" : "Remove") @if (Authorization.Has(Claims.Config.UserFlag.Configure)) { @Html.ActionLink(rule.UserFlag.Name, MVC.Config.UserFlag.Index(rule.UserFlag.Id)) } else { @rule.UserFlag.Name } @if (string.IsNullOrWhiteSpace(rule.Comments)) {   } else { @rule.Comments }
} }

These rules will be applied each time a document is imported (as an attachment) where it is determined the document was based on this template. When creating a user flag assignment, if an assignment already exists the rule will be skipped. When removing user flag assignments, if no assignment is present the rule will be skipped.

Linked Groups:
@Html.Partial(MVC.Config.Shared.Views.LinkedGroupInstance, new LinkedGroupModel() { CanConfigure = canConfig, CategoryDescription = DocumentTemplateUsersManagedGroup.GetCategoryDescription(Model.DocumentTemplate), Description = DocumentTemplateUsersManagedGroup.GetDescription(Model.DocumentTemplate), ManagedGroup = Model.UsersLinkedGroup, IncludeFilterBeginDate = true, UpdateUrl = Url.Action(MVC.API.DocumentTemplate.UpdateUsersLinkedGroup(Model.DocumentTemplate.Id, redirect: true)) }) @Html.Partial(MVC.Config.Shared.Views.LinkedGroupInstance, new LinkedGroupModel() { CanConfigure = canConfig, CategoryDescription = DocumentTemplateDevicesManagedGroup.GetCategoryDescription(Model.DocumentTemplate), Description = DocumentTemplateDevicesManagedGroup.GetDescription(Model.DocumentTemplate), ManagedGroup = Model.DevicesLinkedGroup, IncludeFilterBeginDate = true, UpdateUrl = Url.Action(MVC.API.DocumentTemplate.UpdateDevicesLinkedGroup(Model.DocumentTemplate.Id, redirect: true)) }) @if (canConfig) { @Html.Partial(MVC.Config.Shared.Views.LinkedGroupShared) }

Template Expressions

@Html.Partial(MVC.Config.DocumentTemplate.Views._ExpressionsTable, Model.TemplateExpressions)
@using (Html.BeginForm(MVC.API.DocumentTemplate.Delete(Model.DocumentTemplate.Id, true))) { @Html.AntiForgeryToken() }

This item will be permanently deleted and cannot be recovered.
This will not delete attachments which have already been imported, but any generated documents will no longer be automatically imported.
Are you sure?

@if (hideAdvanced) { } @if (Authorization.Has(Claims.Config.Show)) { @Html.ActionLinkButton("Expression Browser", MVC.Config.Expressions.Browser()) } @if (Authorization.Has(Claims.Config.DocumentTemplate.Export)) { @Html.ActionLinkButton("Export Instances", MVC.Config.DocumentTemplate.Export(Model.DocumentTemplate.Id, null)) } @if (canBulkDownload) {
@using (Html.BeginForm(MVC.API.DocumentTemplate.BulkDownload(Model.DocumentTemplate.Id))) { @Html.AntiForgeryToken()

Scope


Threshold

}
} @if (canBulkGenerate) { if (Model.DocumentTemplate.Scope == DocumentTemplate.DocumentTemplateScopes.User || Model.DocumentTemplate.Scope == DocumentTemplate.DocumentTemplateScopes.Device) { @Html.ActionLinkButton("Bulk Generate", MVC.Config.DocumentTemplate.BulkGenerate(Model.DocumentTemplate.Id)) } else {
@switch (Model.DocumentTemplate.Scope) { case "Device":
Enter multiple Device Serial Numbers separated by <new line>, commas (,) or semicolons (;).

Examples:

01234567
ABCD9876
8VQ6G2R
01234567,ABCD9876,8VQ6G2R
01234567;ABCD9876;8VQ6G2R
break; case "Job":
Enter multiple Job Ids separated by <new line>, commas (,) or semicolons (;).

Examples:

86
99
44
86,99,44
86;99;44
break; }
@using (Html.BeginForm(MVC.API.DocumentTemplate.BulkGenerate(Model.DocumentTemplate.Id))) { @Html.AntiForgeryToken()
if (Model.TemplatePageCount > 1 && Model.TemplatePageCount % 2 != 0) {
} }
} } @if (Authorization.Has(Claims.Config.DocumentTemplate.Delete)) { }
@if (Model.BulkGenerateDownloadId.HasValue) {
Download Bulk Documents
}