Preview document template pdf

Renders document template pdfs to an image which is displayed in the
configuration ui.
This commit is contained in:
Gary Sharp
2016-09-21 19:55:57 +10:00
parent 85425d2a1f
commit 489a5df7cc
7 changed files with 1159 additions and 858 deletions
+1 -1
View File
@@ -261,7 +261,7 @@
<Compile Include="Documents\AttachmentImport\ImportDirectoryMonitor.cs" /> <Compile Include="Documents\AttachmentImport\ImportDirectoryMonitor.cs" />
<Compile Include="Documents\AttachmentImport\ImportPage.cs" /> <Compile Include="Documents\AttachmentImport\ImportPage.cs" />
<Compile Include="Documents\DocumentsLog.cs" /> <Compile Include="Documents\DocumentsLog.cs" />
<Compile Include="Documents\DocumentTemplateActionExtensions.cs" /> <Compile Include="Documents\DocumentTemplateExtensions.cs" />
<Compile Include="Documents\DocumentTemplateDataStoreExtensions.cs" /> <Compile Include="Documents\DocumentTemplateDataStoreExtensions.cs" />
<Compile Include="Documents\DocumentTemplateExpressionExtensions.cs" /> <Compile Include="Documents\DocumentTemplateExpressionExtensions.cs" />
<Compile Include="Documents\DocumentUniqueIdentifier.cs" /> <Compile Include="Documents\DocumentUniqueIdentifier.cs" />
@@ -1,15 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.Services
{
public static class DocumentTemplateActionExtensions
{
}
}
@@ -0,0 +1,90 @@
using Disco.Data.Repository;
using Disco.Models.Repository;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.Services
{
public static class DocumentTemplateActionExtensions
{
public static Bitmap GenerateTemplatePreview(this DocumentTemplate DocumentTemplate, DiscoDataContext Database, int Width, int PageGapHeight, bool DrawPageBorder)
{
string filename = DocumentTemplate.RepositoryFilename(Database);
if (File.Exists(filename))
{
using (var fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read))
{
using (var pdfDocument = PdfiumViewer.PdfDocument.Load(fileStream))
{
var pageMaxWidth = (int)pdfDocument.PageSizes.Max(s => s.Width);
var pageScale = (float)(Width + (DrawPageBorder ? -2 : 0)) / pageMaxWidth;
var previewTotalHeight = pdfDocument.PageSizes
.Take(40)
.Select(s => (int)(pageScale * s.Height))
.Sum() +
(DrawPageBorder ? (Math.Min(40, pdfDocument.PageCount) * 2) : 0) +
((Math.Min(40, pdfDocument.PageCount) - 1) * PageGapHeight);
var result = new Bitmap(Width, previewTotalHeight);
result.SetResolution(72, 72);
using (var graphics = Graphics.FromImage(result))
{
var yPosition = 0;
for (int pageIndex = 0; pageIndex < Math.Min(40, pdfDocument.PageCount); pageIndex++)
{
var pageSize = pdfDocument.PageSizes[pageIndex];
var previewWidth = Math.Floor(pageScale * pageSize.Width);
var previewHeight = Math.Floor(pageScale * pageSize.Height);
// Calculate box
var destination = new Rectangle(
x: (int)((Width - previewWidth) / 2),
y: yPosition + (DrawPageBorder ? 1 : 0),
width: (int)previewWidth,
height: (int)previewHeight
);
// Fill white background
graphics.FillRectangle(Brushes.White, destination);
using (var image = pdfDocument.Render(pageIndex, (int)previewWidth, (int)previewHeight, 72F, 72F, false))
{
graphics.DrawImage(image, destination.X, destination.Y);
}
if (DrawPageBorder)
{
destination.X -= 1;
destination.Y -= 1;
destination.Width += 1;
destination.Height += 1;
graphics.DrawRectangle(Pens.LightGray, destination);
}
yPosition += destination.Height + PageGapHeight;
}
}
return result;
}
}
}
return null;
}
}
}
@@ -11,6 +11,7 @@ using Disco.Services.Users;
using Disco.Services.Web; using Disco.Services.Web;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq; using System.Linq;
using System.Web; using System.Web;
using System.Web.Mvc; using System.Web.Mvc;
@@ -36,10 +37,10 @@ namespace Disco.Web.Areas.API.Controllers
throw new ArgumentNullException("id"); throw new ArgumentNullException("id");
if (string.IsNullOrEmpty(key)) if (string.IsNullOrEmpty(key))
throw new ArgumentNullException("key"); throw new ArgumentNullException("key");
ScheduledTaskStatus resultTask = null; ScheduledTaskStatus resultTask = null;
var documentTemplate = Database.DocumentTemplates.Find(id); var documentTemplate = Database.DocumentTemplates.Find(id);
if (documentTemplate != null) if (documentTemplate != null)
{ {
switch (key.ToLower()) switch (key.ToLower())
@@ -140,6 +141,29 @@ namespace Disco.Web.Areas.API.Controllers
} }
} }
[DiscoAuthorize(Claims.Config.DocumentTemplate.Show), HttpGet]
public virtual ActionResult TemplatePreview(string id)
{
if (string.IsNullOrEmpty(id))
throw new ArgumentNullException("id");
var documentTemplate = Database.DocumentTemplates.Find(id);
if (documentTemplate == null)
throw new ArgumentException("Invalid Document Template Id", "id");
var imageStream = new MemoryStream();
using (var previewImage = documentTemplate.GenerateTemplatePreview(Database, 450, 8, true))
{
if (previewImage == null)
{
throw new InvalidOperationException("Template not found");
}
previewImage.SavePng(imageStream);
}
imageStream.Position = 0;
return File(imageStream, "image/png");
}
#region Update Shortcut Methods #region Update Shortcut Methods
[DiscoAuthorize(Claims.Config.DocumentTemplate.Configure)] [DiscoAuthorize(Claims.Config.DocumentTemplate.Configure)]
public virtual ActionResult UpdateDescription(string id, string Description = null, bool redirect = false) public virtual ActionResult UpdateDescription(string id, string Description = null, bool redirect = false)
@@ -265,7 +289,7 @@ namespace Disco.Web.Areas.API.Controllers
#endregion #endregion
#region Update Properties #region Update Properties
private void UpdateDescription(Disco.Models.Repository.DocumentTemplate documentTemplate, string Description) private void UpdateDescription(DocumentTemplate documentTemplate, string Description)
{ {
if (!string.IsNullOrWhiteSpace(Description)) if (!string.IsNullOrWhiteSpace(Description))
{ {
@@ -275,9 +299,9 @@ namespace Disco.Web.Areas.API.Controllers
} }
throw new Exception("Invalid Description"); throw new Exception("Invalid Description");
} }
private ScheduledTaskStatus UpdateScope(Disco.Models.Repository.DocumentTemplate documentTemplate, string Scope) private ScheduledTaskStatus UpdateScope(DocumentTemplate documentTemplate, string Scope)
{ {
if (string.IsNullOrWhiteSpace(Scope) || !Disco.Models.Repository.DocumentTemplate.DocumentTemplateScopes.ToList().Contains(Scope)) if (string.IsNullOrWhiteSpace(Scope) || !DocumentTemplate.DocumentTemplateScopes.ToList().Contains(Scope))
throw new ArgumentException("Invalid Scope", "Scope"); throw new ArgumentException("Invalid Scope", "Scope");
Database.Configuration.LazyLoadingEnabled = true; Database.Configuration.LazyLoadingEnabled = true;
@@ -287,7 +311,7 @@ namespace Disco.Web.Areas.API.Controllers
documentTemplate.Scope = Scope; documentTemplate.Scope = Scope;
if (documentTemplate.Scope != Disco.Models.Repository.DocumentTemplate.DocumentTemplateScopes.Job && if (documentTemplate.Scope != DocumentTemplate.DocumentTemplateScopes.Job &&
documentTemplate.JobSubTypes != null) documentTemplate.JobSubTypes != null)
{ {
foreach (var st in documentTemplate.JobSubTypes.ToArray()) foreach (var st in documentTemplate.JobSubTypes.ToArray())
@@ -308,7 +332,7 @@ namespace Disco.Web.Areas.API.Controllers
return null; return null;
} }
private void UpdateFilterExpression(Disco.Models.Repository.DocumentTemplate documentTemplate, string FilterExpression) private void UpdateFilterExpression(DocumentTemplate documentTemplate, string FilterExpression)
{ {
if (string.IsNullOrWhiteSpace(FilterExpression)) if (string.IsNullOrWhiteSpace(FilterExpression))
{ {
@@ -323,7 +347,7 @@ namespace Disco.Web.Areas.API.Controllers
Database.SaveChanges(); Database.SaveChanges();
} }
private void UpdateOnGenerateExpression(Disco.Models.Repository.DocumentTemplate documentTemplate, string OnGenerateExpression) private void UpdateOnGenerateExpression(DocumentTemplate documentTemplate, string OnGenerateExpression)
{ {
if (string.IsNullOrWhiteSpace(OnGenerateExpression)) if (string.IsNullOrWhiteSpace(OnGenerateExpression))
{ {
@@ -338,7 +362,7 @@ namespace Disco.Web.Areas.API.Controllers
Database.SaveChanges(); Database.SaveChanges();
} }
private void UpdateOnImportAttachmentExpression(Disco.Models.Repository.DocumentTemplate documentTemplate, string OnImportAttachmentExpression) private void UpdateOnImportAttachmentExpression(DocumentTemplate documentTemplate, string OnImportAttachmentExpression)
{ {
if (string.IsNullOrWhiteSpace(OnImportAttachmentExpression)) if (string.IsNullOrWhiteSpace(OnImportAttachmentExpression))
{ {
@@ -353,7 +377,7 @@ namespace Disco.Web.Areas.API.Controllers
Database.SaveChanges(); Database.SaveChanges();
} }
private void UpdateFlattenForm(Disco.Models.Repository.DocumentTemplate documentTemplate, string FlattenForm) private void UpdateFlattenForm(DocumentTemplate documentTemplate, string FlattenForm)
{ {
if (string.IsNullOrWhiteSpace(FlattenForm)) if (string.IsNullOrWhiteSpace(FlattenForm))
{ {
@@ -370,7 +394,7 @@ namespace Disco.Web.Areas.API.Controllers
Database.SaveChanges(); Database.SaveChanges();
} }
private void UpdateJobSubTypes(Disco.Models.Repository.DocumentTemplate documentTemplate, List<string> JobSubTypes) private void UpdateJobSubTypes(DocumentTemplate documentTemplate, List<string> JobSubTypes)
{ {
Database.Configuration.LazyLoadingEnabled = true; Database.Configuration.LazyLoadingEnabled = true;
@@ -384,7 +408,7 @@ namespace Disco.Web.Areas.API.Controllers
// Add New // Add New
if (JobSubTypes != null && JobSubTypes.Count > 0) if (JobSubTypes != null && JobSubTypes.Count > 0)
{ {
var subTypes = new List<Disco.Models.Repository.JobSubType>(); var subTypes = new List<JobSubType>();
foreach (var stId in JobSubTypes) foreach (var stId in JobSubTypes)
{ {
var typeId = stId.Substring(0, stId.IndexOf("_")); var typeId = stId.Substring(0, stId.IndexOf("_"));
@@ -48,76 +48,93 @@
<table> <table>
<tbody> <tbody>
<tr> <tr>
<th>Id: <th>
Id:
</th> </th>
<td>@Html.DisplayFor(model => model.DocumentTemplate.Id) <td>
@Html.DisplayFor(model => model.DocumentTemplate.Id)
</td> </td>
</tr> </tr>
<tr> <tr>
<th>Statistics: <th>
Statistics:
</th> </th>
<td> <td>
<strong>@Model.StoredInstanceCount.ToString("n0")</strong> Stored Instance@(Model.StoredInstanceCount == 1 ? null : "s") <strong>@Model.StoredInstanceCount.ToString("n0")</strong> Stored Instance@(Model.StoredInstanceCount == 1 ? null : "s")
</td> </td>
</tr> </tr>
<tr> <tr>
<th>Description: <th>
Description:
</th> </th>
<td>@if (canConfig) <td>
@if (canConfig)
{ {
@Html.TextBoxFor(model => model.DocumentTemplate.Description) @Html.TextBoxFor(model => model.DocumentTemplate.Description)
@AjaxHelpers.AjaxSave() @AjaxHelpers.AjaxSave()
@AjaxHelpers.AjaxLoader() @AjaxHelpers.AjaxLoader()
<script type="text/javascript"> <script type="text/javascript">
$(function () { $(function () {
document.DiscoFunctions.PropertyChangeHelper( document.DiscoFunctions.PropertyChangeHelper(
$('#DocumentTemplate_Description'), $('#DocumentTemplate_Description'),
'Description', 'Description',
'@Url.Action(MVC.API.DocumentTemplate.UpdateDescription(Model.DocumentTemplate.Id))', '@Url.Action(MVC.API.DocumentTemplate.UpdateDescription(Model.DocumentTemplate.Id))',
'Description' 'Description'
); );
}); });
</script> </script>
} }
else else
{ {
if (string.IsNullOrEmpty(Model.DocumentTemplate.Description)) if (string.IsNullOrEmpty(Model.DocumentTemplate.Description))
{ {
<span class="smallMessage">&lt;None Specified&gt;</span> <span class="smallMessage">&lt;None Specified&gt;</span>
} }
else else
{ {
@Model.DocumentTemplate.Description @Model.DocumentTemplate.Description
} }
} }
</td> </td>
</tr> </tr>
<tr> <tr>
<th>Always Flatten Form: <th>
&nbsp;
</th> </th>
<td>@if (canConfig) <td>
{ <div>
<input id="DocumentTemplate_FlattenForm" type="checkbox" @(Model.DocumentTemplate.FlattenForm ? new MvcHtmlString("checked=\"checked\" ") : new MvcHtmlString(string.Empty))/> @if (canConfig)
@AjaxHelpers.AjaxLoader() {
<script type="text/javascript"> <input id="DocumentTemplate_FlattenForm" type="checkbox" @(Model.DocumentTemplate.FlattenForm ? new MvcHtmlString("checked=\"checked\" ") : new MvcHtmlString(string.Empty)) />
$(function () { <label for="DocumentTemplate_FlattenForm">Flatten Form</label>
document.DiscoFunctions.PropertyChangeHelper( @AjaxHelpers.AjaxLoader()
$('#DocumentTemplate_FlattenForm'), <script type="text/javascript">
null, $(function () {
'@Url.Action(MVC.API.DocumentTemplate.UpdateFlattenForm(Model.DocumentTemplate.Id))', document.DiscoFunctions.PropertyChangeHelper(
'FlattenForm' $('#DocumentTemplate_FlattenForm'),
); null,
}); '@Url.Action(MVC.API.DocumentTemplate.UpdateFlattenForm(Model.DocumentTemplate.Id))',
</script> 'FlattenForm'
} );
else });
{ </script>
<input id="DocumentTemplate_FlattenForm" type="checkbox" @(Model.DocumentTemplate.FlattenForm ? new MvcHtmlString("checked=\"checked\" ") : new MvcHtmlString(string.Empty)) disabled="disabled" /> }
} else
{
<input id="DocumentTemplate_FlattenForm" type="checkbox" @(Model.DocumentTemplate.FlattenForm ? new MvcHtmlString("checked=\"checked\" ") : new MvcHtmlString(string.Empty)) disabled="disabled" />
<label for="DocumentTemplate_FlattenForm">Flatten Form</label>
}
</div>
<div class="info-box">
<p class="fa-p">
<i class="fa fa-info-circle"></i>If selected when a document is generated all form elements will be removed and their content written in place.
</p>
</div>
</td> </td>
</tr> </tr>
<tr> <tr>
<th>Scope: <th>
Scope:
</th> </th>
<td> <td>
<h4>@Model.DocumentTemplate.Scope Scope</h4> <h4>@Model.DocumentTemplate.Scope Scope</h4>
@@ -130,7 +147,7 @@
<button id="Config_DocumentTemplates_Scope_Button" class="button small">Change Scope</button> <button id="Config_DocumentTemplates_Scope_Button" class="button small">Change Scope</button>
</div> </div>
@if (canConfig) @if (canConfig)
{ {
<div id="Config_DocumentTemplates_Scope_Dialog" title="Change Document Template Scope" class="dialog"> <div id="Config_DocumentTemplates_Scope_Dialog" title="Change Document Template Scope" class="dialog">
@using (Html.BeginForm(MVC.API.DocumentTemplate.UpdateScope(Model.DocumentTemplate.Id, redirect: true))) @using (Html.BeginForm(MVC.API.DocumentTemplate.UpdateScope(Model.DocumentTemplate.Id, redirect: true)))
{ {
@@ -139,7 +156,7 @@
<select id="Config_DocumentTemplates_Scope_Scope" name="Scope"> <select id="Config_DocumentTemplates_Scope_Scope" name="Scope">
@foreach (var scope in Model.Scopes) @foreach (var scope in Model.Scopes)
{ {
<option value="@scope" selected="@(scope == Model.DocumentTemplate.Scope ? "selected" : null)">@scope</option> <option value="@scope" selected="@(scope == Model.DocumentTemplate.Scope ? "selected" : null)">@scope</option>
} }
</select> </select>
</div> </div>
@@ -192,7 +209,7 @@
</script> </script>
} }
@if (Model.DocumentTemplate.Scope == DocumentTemplate.DocumentTemplateScopes.Job) @if (Model.DocumentTemplate.Scope == DocumentTemplate.DocumentTemplateScopes.Job)
{ {
<hr /> <hr />
<h4>Job Type Filters:</h4> <h4>Job Type Filters:</h4>
<div id="Config_DocumentTemplates_JobSubTypes" @(Model.DocumentTemplate.Scope != DocumentTemplate.DocumentTemplateScopes.Job ? "style=\"display: none;\" " : null)> <div id="Config_DocumentTemplates_JobSubTypes" @(Model.DocumentTemplate.Scope != DocumentTemplate.DocumentTemplateScopes.Job ? "style=\"display: none;\" " : null)>
@@ -213,7 +230,7 @@
{ {
foreach (var jobSubType in jobType) foreach (var jobSubType in jobType)
{ {
<li>@jobSubType.Description</li> <li>@jobSubType.Description</li>
} }
} }
</ul> </ul>
@@ -235,14 +252,15 @@
var selectedTypes = Model.DocumentTemplate.JobSubTypes.Select(jst => jst.JobType).Distinct().ToList(); var selectedTypes = Model.DocumentTemplate.JobSubTypes.Select(jst => jst.JobType).Distinct().ToList();
foreach (var jt in Model.JobTypes) foreach (var jt in Model.JobTypes)
{ {
<div class="jobTypes"> <div class="jobTypes">
<h4> <h4>
<input id="Types_@(jt.Id)" class="jobType" type="checkbox" value="@(jt.Id)" @(selectedTypes.Contains(jt) ? "checked=\"checked\"" : null) /><label for="Types_@(jt.Id)">@jt.Description</label></h4> <input id="Types_@(jt.Id)" class="jobType" type="checkbox" value="@(jt.Id)" @(selectedTypes.Contains(jt) ? "checked=\"checked\"" : null) /><label for="Types_@(jt.Id)">@jt.Description</label>
<div id="SubTypes_@(jt.Id)" class="jobSubTypes"> </h4>
@CommonHelpers.CheckboxBulkSelect(string.Format("CheckboxBulkSelect_{0}", jt.Id), "div") <div id="SubTypes_@(jt.Id)" class="jobSubTypes">
@CommonHelpers.CheckBoxList("JobSubTypes", jt.JobSubTypes.OrderBy(jst => jst.Description).ToSelectListItems(Model.DocumentTemplate.JobSubTypes), 2) @CommonHelpers.CheckboxBulkSelect(string.Format("CheckboxBulkSelect_{0}", jt.Id), "div")
@CommonHelpers.CheckBoxList("JobSubTypes", jt.JobSubTypes.OrderBy(jst => jst.Description).ToSelectListItems(Model.DocumentTemplate.JobSubTypes), 2)
</div>
</div> </div>
</div>
} }
} }
</div> </div>
@@ -313,147 +331,149 @@
} }
</td> </td>
</tr> </tr>
</tbody>
</table>
</div>
<div class="form Config_DocumentTemplates_Template" style="width: 650px; margin: 0 auto 20px;">
<h2>PDF Template</h2>
<table>
<tbody>
<tr> <tr>
<th>PDF Template
</th>
<td> <td>
@Html.ActionLinkSmallButton("Download Template", MVC.API.DocumentTemplate.Template(Model.DocumentTemplate.Id)) <div style="margin: -8px -5px; max-height: 350px; overflow-y: scroll; text-align: center;">
@if (canConfig && Authorization.Has(Claims.Config.DocumentTemplate.Upload)) <img style="margin: 8px 5px;" src="@Url.Action(MVC.API.DocumentTemplate.TemplatePreview(Model.DocumentTemplate.Id))" />
{ </div>
<button class="button small" id="Config_DocumentTemplates_TemplatePdf_Button">Replace Template</button>
<div id="Config_DocumentTemplates_TemplatePdf_Dialog" title="Replace Document PDF Template" class="dialog">
<h4>Select a PDF Template to upload:</h4>
<div>
@using (Html.BeginForm(MVC.API.DocumentTemplate.Template(Model.DocumentTemplate.Id, true, null), FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<input type="file" name="Template" id="Config_DocumentTemplates_TemplatePdf_Template" style="width: 250px;" />
}
</div>
</div>
<script type="text/javascript">
$(function () {
var dialog, template;
function showDialog() {
if (dialog == null) {
template = $('#Config_DocumentTemplates_TemplatePdf_Template');
dialog = $('#Config_DocumentTemplates_TemplatePdf_Dialog').dialog({
width: 350,
resizable: false,
modal: true,
autoOpen: false,
buttons: {
'Upload': function () {
if (template.val() == '') {
alert('A template file is required to upload.');
} else {
dialog.dialog('option', 'buttons', null);
dialog.dialog('disable');
template.closest('form').submit();
}
},
'Cancel': function () {
dialog.dialog('close');
}
}
});
}
dialog.dialog('open');
return false;
}
$('#Config_DocumentTemplates_TemplatePdf_Button').click(showDialog);
});
</script>
}
</td> </td>
</tr> </tr>
@if (hideAdvanced) @if (canConfig)
{ {
<tr> <tr>
<td colspan="2" style="text-align: right;"> <td style="text-align: right;">
<button id="Config_HideAdvanced_Show" class="button small">Show Advanced Options</button> @Html.ActionLinkSmallButton("Download Template", MVC.API.DocumentTemplate.Template(Model.DocumentTemplate.Id))
<script> @if (canConfig && Authorization.Has(Claims.Config.DocumentTemplate.Upload))
$(function () { {
$('#Config_HideAdvanced_Show').click(function () { <button class="button small" id="Config_DocumentTemplates_TemplatePdf_Button">Replace Template</button>
var $this = $(this); <div id="Config_DocumentTemplates_TemplatePdf_Dialog" title="Replace Document PDF Template" class="dialog">
$this.closest('.Config_HideAdvanced').removeClass('Config_HideAdvanced'); <h4>Select a PDF Template to upload:</h4>
$this.closest('tr').remove(); <div>
@using (Html.BeginForm(MVC.API.DocumentTemplate.Template(Model.DocumentTemplate.Id, true, null), FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<input type="file" name="Template" id="Config_DocumentTemplates_TemplatePdf_Template" style="width: 250px;" />
}
</div>
</div>
<script type="text/javascript">
$(function () {
var dialog, template;
function showDialog() {
if (dialog == null) {
template = $('#Config_DocumentTemplates_TemplatePdf_Template');
dialog = $('#Config_DocumentTemplates_TemplatePdf_Dialog').dialog({
width: 350,
resizable: false,
modal: true,
autoOpen: false,
buttons: {
'Upload': function () {
if (template.val() == '') {
alert('A template file is required to upload.');
} else {
dialog.dialog('option', 'buttons', null);
dialog.dialog('disable');
template.closest('form').submit();
}
},
'Cancel': function () {
dialog.dialog('close');
}
}
});
}
dialog.dialog('open');
return false;
}
$('#Config_DocumentTemplates_TemplatePdf_Button').click(showDialog);
}); });
}); </script>
</script> }
</td> </td>
</tr> </tr>
} }
</tbody> </tbody>
</table> </table>
</div> </div>
<div class="form Config_HideAdvanced_Item" style="width: 650px;"> <div class="form Config_HideAdvanced_Item" style="width: 650px;">
<h2>Advanced Options</h2> <h2>Advanced Options</h2>
<table> <table>
<tbody> <tbody>
<tr> <tr>
<th>Filter Expression: <th>
Filter Expression:
</th> </th>
<td>@if (canConfig && Authorization.Has(Claims.Config.DocumentTemplate.ConfigureFilterExpression)) <td>
@if (canConfig && Authorization.Has(Claims.Config.DocumentTemplate.ConfigureFilterExpression))
{ {
@Html.EditorFor(model => model.DocumentTemplate.FilterExpression) @Html.EditorFor(model => model.DocumentTemplate.FilterExpression)
@AjaxHelpers.AjaxRemove() @AjaxHelpers.AjaxRemove()
@AjaxHelpers.AjaxSave() @AjaxHelpers.AjaxSave()
@AjaxHelpers.AjaxLoader() @AjaxHelpers.AjaxLoader()
<script type="text/javascript"> <script type="text/javascript">
$(function () { $(function () {
var field = $('#DocumentTemplate_FilterExpression'); var field = $('#DocumentTemplate_FilterExpression');
var fieldRemove = field.next('.ajaxRemove'); var fieldRemove = field.next('.ajaxRemove');
var fieldOriginalWidth, fieldOriginalHeight; var fieldOriginalWidth, fieldOriginalHeight;
document.DiscoFunctions.PropertyChangeHelper( document.DiscoFunctions.PropertyChangeHelper(
field, field,
'None', 'None',
'@Url.Action(MVC.API.DocumentTemplate.UpdateFilterExpression(Model.DocumentTemplate.Id))', '@Url.Action(MVC.API.DocumentTemplate.UpdateFilterExpression(Model.DocumentTemplate.Id))',
'FilterExpression' 'FilterExpression'
); );
field.focus(function () {
fieldOriginalWidth = field.width();
fieldOriginalHeight = field.height();
field.css('overflow', 'visible').animate({ width: field.parent().width() - 42, height: 75 }, 200);
}).blur(function () {
field.css('overflow', 'hidden').animate({ width: fieldOriginalWidth, height: fieldOriginalHeight }, 200);
}).change(function () {
if (!!field.val()) {
fieldRemove.show();
} else {
fieldRemove.hide();
}
}).attr('placeholder', 'None').attr('spellcheck', 'false');
fieldRemove.click(function () {
field.val('').change();
});
field.focus(function () {
fieldOriginalWidth = field.width();
fieldOriginalHeight = field.height();
field.css('overflow', 'visible').animate({ width: field.parent().width() - 42, height: 75 }, 200);
}).blur(function () {
field.css('overflow', 'hidden').animate({ width: fieldOriginalWidth, height: fieldOriginalHeight }, 200);
}).change(function () {
if (!!field.val()) { if (!!field.val()) {
fieldRemove.show(); fieldRemove.show();
} else { } else {
fieldRemove.hide(); fieldRemove.hide();
} }
}).attr('placeholder', 'None').attr('spellcheck', 'false');
fieldRemove.click(function () {
field.val('').change();
}); });
</script>
if (!!field.val()) {
fieldRemove.show();
} else {
fieldRemove.hide();
}
});
</script>
} }
else else
{ {
if (string.IsNullOrWhiteSpace(Model.DocumentTemplate.FilterExpression)) if (string.IsNullOrWhiteSpace(Model.DocumentTemplate.FilterExpression))
{ {
<span class="smallMessage">&lt;None Specified&gt;</span> <span class="smallMessage">&lt;None Specified&gt;</span>
} }
else else
{ {
<div class="code"> <div class="code">
@Model.DocumentTemplate.FilterExpression @Model.DocumentTemplate.FilterExpression
</div> </div>
} }
} }
<div class="info-box"> <div class="info-box">
@@ -464,64 +484,66 @@
</td> </td>
</tr> </tr>
<tr> <tr>
<th>On Generated Expression: <th>
On Generated Expression:
</th> </th>
<td>@if (canConfig && Authorization.Has(Claims.Config.DocumentTemplate.ConfigureFilterExpression)) <td>
{ @if (canConfig && Authorization.Has(Claims.Config.DocumentTemplate.ConfigureFilterExpression))
@Html.EditorFor(model => model.DocumentTemplate.OnGenerateExpression) {
@AjaxHelpers.AjaxRemove() @Html.EditorFor(model => model.DocumentTemplate.OnGenerateExpression)
@AjaxHelpers.AjaxSave() @AjaxHelpers.AjaxRemove()
@AjaxHelpers.AjaxLoader() @AjaxHelpers.AjaxSave()
<script type="text/javascript"> @AjaxHelpers.AjaxLoader()
$(function () { <script type="text/javascript">
var field = $('#DocumentTemplate_OnGenerateExpression'); $(function () {
var fieldRemove = field.next('.ajaxRemove'); var field = $('#DocumentTemplate_OnGenerateExpression');
var fieldOriginalWidth, fieldOriginalHeight; var fieldRemove = field.next('.ajaxRemove');
var fieldOriginalWidth, fieldOriginalHeight;
document.DiscoFunctions.PropertyChangeHelper( document.DiscoFunctions.PropertyChangeHelper(
field, field,
'None', 'None',
'@Url.Action(MVC.API.DocumentTemplate.UpdateOnGenerateExpression(Model.DocumentTemplate.Id))', '@Url.Action(MVC.API.DocumentTemplate.UpdateOnGenerateExpression(Model.DocumentTemplate.Id))',
'OnGenerateExpression' 'OnGenerateExpression'
); );
field.focus(function () {
fieldOriginalWidth = field.width();
fieldOriginalHeight = field.height();
field.css('overflow', 'visible').animate({ width: field.parent().width() - 42, height: 75 }, 200);
}).blur(function () {
field.css('overflow', 'hidden').animate({ width: fieldOriginalWidth, height: fieldOriginalHeight }, 200);
}).change(function () {
if (!!field.val()) {
fieldRemove.show();
} else {
fieldRemove.hide();
}
}).attr('placeholder', 'None').attr('spellcheck', 'false');
fieldRemove.click(function () {
field.val('').change();
});
field.focus(function () {
fieldOriginalWidth = field.width();
fieldOriginalHeight = field.height();
field.css('overflow', 'visible').animate({ width: field.parent().width() - 42, height: 75 }, 200);
}).blur(function () {
field.css('overflow', 'hidden').animate({ width: fieldOriginalWidth, height: fieldOriginalHeight }, 200);
}).change(function () {
if (!!field.val()) { if (!!field.val()) {
fieldRemove.show(); fieldRemove.show();
} else { } else {
fieldRemove.hide(); fieldRemove.hide();
} }
}).attr('placeholder', 'None').attr('spellcheck', 'false');
fieldRemove.click(function () {
field.val('').change();
}); });
</script>
if (!!field.val()) {
fieldRemove.show();
} else {
fieldRemove.hide();
}
});
</script>
} }
else else
{ {
if (string.IsNullOrWhiteSpace(Model.DocumentTemplate.OnGenerateExpression)) if (string.IsNullOrWhiteSpace(Model.DocumentTemplate.OnGenerateExpression))
{ {
<span class="smallMessage">&lt;None Specified&gt;</span> <span class="smallMessage">&lt;None Specified&gt;</span>
} }
else else
{ {
<div class="code"> <div class="code">
@Model.DocumentTemplate.OnGenerateExpression @Model.DocumentTemplate.OnGenerateExpression
</div> </div>
} }
} }
<div class="info-box"> <div class="info-box">
@@ -532,64 +554,66 @@
</td> </td>
</tr> </tr>
<tr> <tr>
<th>On Import Expression: <th>
On Import Expression:
</th> </th>
<td>@if (canConfig && Authorization.Has(Claims.Config.DocumentTemplate.ConfigureFilterExpression)) <td>
@if (canConfig && Authorization.Has(Claims.Config.DocumentTemplate.ConfigureFilterExpression))
{ {
@Html.EditorFor(model => model.DocumentTemplate.OnImportAttachmentExpression) @Html.EditorFor(model => model.DocumentTemplate.OnImportAttachmentExpression)
@AjaxHelpers.AjaxRemove() @AjaxHelpers.AjaxRemove()
@AjaxHelpers.AjaxSave() @AjaxHelpers.AjaxSave()
@AjaxHelpers.AjaxLoader() @AjaxHelpers.AjaxLoader()
<script type="text/javascript"> <script type="text/javascript">
$(function () { $(function () {
var field = $('#DocumentTemplate_OnImportAttachmentExpression'); var field = $('#DocumentTemplate_OnImportAttachmentExpression');
var fieldRemove = field.next('.ajaxRemove'); var fieldRemove = field.next('.ajaxRemove');
var fieldOriginalWidth, fieldOriginalHeight; var fieldOriginalWidth, fieldOriginalHeight;
document.DiscoFunctions.PropertyChangeHelper( document.DiscoFunctions.PropertyChangeHelper(
field, field,
'None', 'None',
'@Url.Action(MVC.API.DocumentTemplate.UpdateOnImportAttachmentExpression(Model.DocumentTemplate.Id))', '@Url.Action(MVC.API.DocumentTemplate.UpdateOnImportAttachmentExpression(Model.DocumentTemplate.Id))',
'OnImportAttachmentExpression' 'OnImportAttachmentExpression'
); );
field.focus(function () {
fieldOriginalWidth = field.width();
fieldOriginalHeight = field.height();
field.css('overflow', 'visible').animate({ width: field.parent().width() - 42, height: 75 }, 200);
}).blur(function () {
field.css('overflow', 'hidden').animate({ width: fieldOriginalWidth, height: fieldOriginalHeight }, 200);
}).change(function () {
if (!!field.val()) {
fieldRemove.show();
} else {
fieldRemove.hide();
}
}).attr('placeholder', 'None').attr('spellcheck', 'false');
fieldRemove.click(function () {
field.val('').change();
});
field.focus(function () {
fieldOriginalWidth = field.width();
fieldOriginalHeight = field.height();
field.css('overflow', 'visible').animate({ width: field.parent().width() - 42, height: 75 }, 200);
}).blur(function () {
field.css('overflow', 'hidden').animate({ width: fieldOriginalWidth, height: fieldOriginalHeight }, 200);
}).change(function () {
if (!!field.val()) { if (!!field.val()) {
fieldRemove.show(); fieldRemove.show();
} else { } else {
fieldRemove.hide(); fieldRemove.hide();
} }
}).attr('placeholder', 'None').attr('spellcheck', 'false');
fieldRemove.click(function () {
field.val('').change();
}); });
</script>
if (!!field.val()) {
fieldRemove.show();
} else {
fieldRemove.hide();
}
});
</script>
} }
else else
{ {
if (string.IsNullOrWhiteSpace(Model.DocumentTemplate.OnImportAttachmentExpression)) if (string.IsNullOrWhiteSpace(Model.DocumentTemplate.OnImportAttachmentExpression))
{ {
<span class="smallMessage">&lt;None Specified&gt;</span> <span class="smallMessage">&lt;None Specified&gt;</span>
} }
else else
{ {
<div class="code"> <div class="code">
@Model.DocumentTemplate.OnImportAttachmentExpression @Model.DocumentTemplate.OnImportAttachmentExpression
</div> </div>
} }
} }
<div class="info-box"> <div class="info-box">
@@ -600,28 +624,29 @@
</td> </td>
</tr> </tr>
<tr> <tr>
<th>Linked Groups: <th>
Linked Groups:
</th> </th>
<td> <td>
<div> <div>
@Html.Partial(MVC.Config.Shared.Views.LinkedGroupInstance, new LinkedGroupModel() @Html.Partial(MVC.Config.Shared.Views.LinkedGroupInstance, new LinkedGroupModel()
{ {
CanConfigure = canConfig, CanConfigure = canConfig,
CategoryDescription = DocumentTemplateUsersManagedGroup.GetCategoryDescription(Model.DocumentTemplate), CategoryDescription = DocumentTemplateUsersManagedGroup.GetCategoryDescription(Model.DocumentTemplate),
Description = DocumentTemplateUsersManagedGroup.GetDescription(Model.DocumentTemplate), Description = DocumentTemplateUsersManagedGroup.GetDescription(Model.DocumentTemplate),
ManagedGroup = Model.UsersLinkedGroup, ManagedGroup = Model.UsersLinkedGroup,
UpdateUrl = Url.Action(MVC.API.DocumentTemplate.UpdateUsersLinkedGroup(Model.DocumentTemplate.Id, redirect: true)) UpdateUrl = Url.Action(MVC.API.DocumentTemplate.UpdateUsersLinkedGroup(Model.DocumentTemplate.Id, redirect: true))
}) })
@Html.Partial(MVC.Config.Shared.Views.LinkedGroupInstance, new LinkedGroupModel() @Html.Partial(MVC.Config.Shared.Views.LinkedGroupInstance, new LinkedGroupModel()
{ {
CanConfigure = canConfig, CanConfigure = canConfig,
CategoryDescription = DocumentTemplateDevicesManagedGroup.GetCategoryDescription(Model.DocumentTemplate), CategoryDescription = DocumentTemplateDevicesManagedGroup.GetCategoryDescription(Model.DocumentTemplate),
Description = DocumentTemplateDevicesManagedGroup.GetDescription(Model.DocumentTemplate), Description = DocumentTemplateDevicesManagedGroup.GetDescription(Model.DocumentTemplate),
ManagedGroup = Model.DevicesLinkedGroup, ManagedGroup = Model.DevicesLinkedGroup,
UpdateUrl = Url.Action(MVC.API.DocumentTemplate.UpdateDevicesLinkedGroup(Model.DocumentTemplate.Id, redirect: true)) UpdateUrl = Url.Action(MVC.API.DocumentTemplate.UpdateDevicesLinkedGroup(Model.DocumentTemplate.Id, redirect: true))
}) })
@if (canConfig) @if (canConfig)
{ {
@Html.Partial(MVC.Config.Shared.Views.LinkedGroupShared) @Html.Partial(MVC.Config.Shared.Views.LinkedGroupShared)
} }
</div> </div>
@@ -638,8 +663,10 @@
<div id="dialogConfirmDelete" title="Delete this Document Template?"> <div id="dialogConfirmDelete" title="Delete this Document Template?">
<p> <p>
<i class="fa fa-exclamation-triangle fa-lg warning"></i>This item will be permanently deleted and cannot be recovered.<br /> <i class="fa fa-exclamation-triangle fa-lg warning"></i>This item will be permanently deleted and cannot be recovered.<br />
<em>This <strong>will not delete attachments</strong> which have already been imported, <em>
but any generated documents will no longer be automatically imported.</em><br /> This <strong>will not delete attachments</strong> which have already been imported,
but any generated documents will no longer be automatically imported.
</em><br />
Are you sure? Are you sure?
</p> </p>
</div> </div>
@@ -673,6 +700,18 @@
}); });
</script> </script>
<div class="actionBar"> <div class="actionBar">
@if (hideAdvanced)
{
<button id="Config_HideAdvanced_Show" class="button">Show Advanced Options</button>
<script>
$(function () {
$('#Config_HideAdvanced_Show').click(function () {
$('#Config_DocumentTemplates_Show').removeClass('Config_HideAdvanced');
$(this).remove();
});
});
</script>
}
@if (Authorization.Has(Claims.Config.Show)) @if (Authorization.Has(Claims.Config.Show))
{ {
@Html.ActionLinkButton("Expression Browser", MVC.Config.DocumentTemplate.ExpressionBrowser()) @Html.ActionLinkButton("Expression Browser", MVC.Config.DocumentTemplate.ExpressionBrowser())
@@ -685,47 +724,53 @@
@switch (Model.DocumentTemplate.Scope) @switch (Model.DocumentTemplate.Scope)
{ {
case "Device": case "Device":
<div> <div>
Enter multiple <span class="scopeDescBulkGenerate">Device Serial Numbers</span> separated by <code>&lt;new line&gt;</code>, commas (<code>,</code>) or semicolons (<code>;</code>). Enter multiple <span class="scopeDescBulkGenerate">Device Serial Numbers</span> separated by <code>&lt;new line&gt;</code>, commas (<code>,</code>) or semicolons (<code>;</code>).
</div> </div>
<div class="examples clearfix"> <div class="examples clearfix">
<h4>Examples:</h4> <h4>Examples:</h4>
<div class="example1 code">01234567<br /> <div class="example1 code">
ABCD9876<br /> 01234567<br />
8VQ6G2R</div> ABCD9876<br />
<div class="example2 code">01234567,ABCD9876,8VQ6G2R</div> 8VQ6G2R
<div class="example3 code">01234567;ABCD9876;8VQ6G2R</div> </div>
</div> <div class="example2 code">01234567,ABCD9876,8VQ6G2R</div>
<div class="example3 code">01234567;ABCD9876;8VQ6G2R</div>
</div>
break; break;
case "Job": case "Job":
<div> <div>
Enter multiple <span class="scopeDescBulkGenerate">Job Ids</span> separated by <code>&lt;new line&gt;</code>, commas (<code>,</code>) or semicolons (<code>;</code>). Enter multiple <span class="scopeDescBulkGenerate">Job Ids</span> separated by <code>&lt;new line&gt;</code>, commas (<code>,</code>) or semicolons (<code>;</code>).
</div> </div>
<div class="examples clearfix"> <div class="examples clearfix">
<h4>Examples:</h4> <h4>Examples:</h4>
<div class="example1 code">86<br /> <div class="example1 code">
99<br /> 86<br />
44</div> 99<br />
<div class="example2 code">86,99,44</div> 44
<div class="example3 code">86;99;44</div> </div>
</div> <div class="example2 code">86,99,44</div>
<div class="example3 code">86;99;44</div>
</div>
break; break;
case "User": case "User":
<div> <div>
Enter multiple <span class="scopeDescBulkGenerate">User Ids</span> separated by <code>&lt;new line&gt;</code>, commas (<code>,</code>) or semicolons (<code>;</code>). Enter multiple <span class="scopeDescBulkGenerate">User Ids</span> separated by <code>&lt;new line&gt;</code>, commas (<code>,</code>) or semicolons (<code>;</code>).
</div> </div>
<div class="examples clearfix"> <div class="examples clearfix">
<h4>Examples:</h4> <h4>Examples:</h4>
<div class="example1 code">user6<br /> <div class="example1 code">
smi0099<br />@(ActiveDirectory.Context.PrimaryDomain.NetBiosName)\rsmith</div> user6<br />
<div class="example2 code">user6,smi0099,@(ActiveDirectory.Context.PrimaryDomain.NetBiosName)\rsmith</div> smi0099<br />@(ActiveDirectory.Context.PrimaryDomain.NetBiosName)\rsmith
<div class="example3 code">user6;smi0099;@(ActiveDirectory.Context.PrimaryDomain.NetBiosName)\rsmith</div> </div>
</div> <div class="example2 code">user6,smi0099,@(ActiveDirectory.Context.PrimaryDomain.NetBiosName)\rsmith</div>
<div class="example3 code">user6;smi0099;@(ActiveDirectory.Context.PrimaryDomain.NetBiosName)\rsmith</div>
</div>
break; break;
} }
</div> </div>
@using (Html.BeginForm(MVC.API.DocumentTemplate.BulkGenerate(Model.DocumentTemplate.Id), FormMethod.Post)) @using (Html.BeginForm(MVC.API.DocumentTemplate.BulkGenerate(Model.DocumentTemplate.Id), FormMethod.Post))
{ {
<div class="field-validation-valid" data-valmsg-replace="true" data-valmsg-for="DataIds"></div> <div class="field-validation-valid" data-valmsg-replace="true" data-valmsg-for="DataIds"></div>
<textarea id="inputBulkGenerateDataIds" name="DataIds" data-val="true" data-val-required="Identifiers are required"></textarea> <textarea id="inputBulkGenerateDataIds" name="DataIds" data-val="true" data-val-required="Identifiers are required"></textarea>
} }
File diff suppressed because it is too large Load Diff
@@ -71,6 +71,12 @@ namespace Disco.Web.Areas.API.Controllers
} }
[NonAction] [NonAction]
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public virtual System.Web.Mvc.ActionResult TemplatePreview()
{
return new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.TemplatePreview);
}
[NonAction]
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public virtual System.Web.Mvc.ActionResult UpdateDescription() public virtual System.Web.Mvc.ActionResult UpdateDescription()
{ {
return new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.UpdateDescription); return new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.UpdateDescription);
@@ -183,6 +189,7 @@ namespace Disco.Web.Areas.API.Controllers
{ {
public readonly string Update = "Update"; public readonly string Update = "Update";
public readonly string Template = "Template"; public readonly string Template = "Template";
public readonly string TemplatePreview = "TemplatePreview";
public readonly string UpdateDescription = "UpdateDescription"; public readonly string UpdateDescription = "UpdateDescription";
public readonly string UpdateFilterExpression = "UpdateFilterExpression"; public readonly string UpdateFilterExpression = "UpdateFilterExpression";
public readonly string UpdateOnGenerateExpression = "UpdateOnGenerateExpression"; public readonly string UpdateOnGenerateExpression = "UpdateOnGenerateExpression";
@@ -207,6 +214,7 @@ namespace Disco.Web.Areas.API.Controllers
{ {
public const string Update = "Update"; public const string Update = "Update";
public const string Template = "Template"; public const string Template = "Template";
public const string TemplatePreview = "TemplatePreview";
public const string UpdateDescription = "UpdateDescription"; public const string UpdateDescription = "UpdateDescription";
public const string UpdateFilterExpression = "UpdateFilterExpression"; public const string UpdateFilterExpression = "UpdateFilterExpression";
public const string UpdateOnGenerateExpression = "UpdateOnGenerateExpression"; public const string UpdateOnGenerateExpression = "UpdateOnGenerateExpression";
@@ -248,6 +256,14 @@ namespace Disco.Web.Areas.API.Controllers
public readonly string redirect = "redirect"; public readonly string redirect = "redirect";
public readonly string Template = "Template"; public readonly string Template = "Template";
} }
static readonly ActionParamsClass_TemplatePreview s_params_TemplatePreview = new ActionParamsClass_TemplatePreview();
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public ActionParamsClass_TemplatePreview TemplatePreviewParams { get { return s_params_TemplatePreview; } }
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public class ActionParamsClass_TemplatePreview
{
public readonly string id = "id";
}
static readonly ActionParamsClass_UpdateDescription s_params_UpdateDescription = new ActionParamsClass_UpdateDescription(); static readonly ActionParamsClass_UpdateDescription s_params_UpdateDescription = new ActionParamsClass_UpdateDescription();
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public ActionParamsClass_UpdateDescription UpdateDescriptionParams { get { return s_params_UpdateDescription; } } public ActionParamsClass_UpdateDescription UpdateDescriptionParams { get { return s_params_UpdateDescription; } }
@@ -465,6 +481,18 @@ namespace Disco.Web.Areas.API.Controllers
return callInfo; return callInfo;
} }
[NonAction]
partial void TemplatePreviewOverride(T4MVC_System_Web_Mvc_ActionResult callInfo, string id);
[NonAction]
public override System.Web.Mvc.ActionResult TemplatePreview(string id)
{
var callInfo = new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.TemplatePreview);
ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "id", id);
TemplatePreviewOverride(callInfo, id);
return callInfo;
}
[NonAction] [NonAction]
partial void UpdateDescriptionOverride(T4MVC_System_Web_Mvc_ActionResult callInfo, string id, string Description, bool redirect); partial void UpdateDescriptionOverride(T4MVC_System_Web_Mvc_ActionResult callInfo, string id, string Description, bool redirect);