feature: bulk generating user documents

This commit is contained in:
Gary Sharp
2022-12-04 13:43:13 +11:00
parent 4c19a1ef63
commit be99083d6a
13 changed files with 2969 additions and 26 deletions
@@ -8,6 +8,8 @@ using Disco.Services.Documents.ManagedGroups;
using Disco.Services.Expressions;
using Disco.Services.Plugins.Features.UIExtension;
using Disco.Services.Web;
using Disco.Web.Areas.Config.Models.DocumentTemplate;
using Disco.Web.Areas.Config.Views.DocumentTemplate;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -214,6 +216,63 @@ namespace Disco.Web.Areas.Config.Controllers
return View(model);
}
[DiscoAuthorizeAll(Claims.Config.DocumentTemplate.BulkGenerate, Claims.User.Actions.GenerateDocuments)]
public virtual ActionResult BulkGenerate(string id)
{
var m = new BulkGenerateModel()
{
DocumentTemplate = Database.DocumentTemplates.FirstOrDefault(at => at.Id == id),
};
if (m.DocumentTemplate == null)
throw new ArgumentException("Invalid Document Template Id", nameof(id));
if (m.DocumentTemplate.Scope != DocumentTemplate.DocumentTemplateScopes.User)
throw new NotSupportedException("Only user-scoped document templates can be bulk generated using this method");
m.TemplatePageCount = m.DocumentTemplate.PdfPageHasAttachmentId(Database).Count;
m.UserFlags = Database.UserFlags.Select(f => new BulkGenerateModel.ItemWithCount<UserFlag>()
{
Item = f,
Count = f.UserFlagAssignments.Where(a => a.RemovedDate == null).Count(),
}).ToList();
m.DeviceProfiles = Database.DeviceProfiles.Select(p => new BulkGenerateModel.ItemWithCount<DeviceProfile>()
{
Item = p,
Count = p.Devices.Where(d => d.AssignedUserId != null).Count(),
}).ToList();
m.DeviceBatches = Database.DeviceBatches.Select(p => new BulkGenerateModel.ItemWithCount<DeviceBatch>()
{
Item = p,
Count = p.Devices.Where(d => d.AssignedUserId != null).Count(),
}).ToList();
m.DocumentTemplates = Database.DocumentTemplates.Select(dt => new BulkGenerateModel.ItemWithCount<DocumentTemplate>()
{
Item = dt,
}).ToList();
foreach (var record in m.DocumentTemplates)
{
switch (record.Item.AttachmentType)
{
case AttachmentTypes.Device:
record.Count = Database.DeviceAttachments.Where(a => a.DocumentTemplateId == record.Item.Id).Select(a => a.Device.AssignedUser).Distinct().Count();
break;
case AttachmentTypes.Job:
record.Count = Database.JobAttachments.Where(a => a.DocumentTemplateId == record.Item.Id).Select(a => a.Job.User).Distinct().Count();
break;
case AttachmentTypes.User:
record.Count = Database.UserAttachments.Where(a => a.DocumentTemplateId == record.Item.Id).Select(a => a.User).Distinct().Count();
break;
default:
throw new NotSupportedException();
}
}
// UI Extensions
UIExtensions.ExecuteExtensions<ConfigDocumentTemplateBulkGenerate>(ControllerContext, m);
return View(MVC.Config.DocumentTemplate.Views.BulkGenerate, m);
}
[DiscoAuthorize(Claims.Config.Show)]
public virtual ActionResult ExpressionBrowser(string type, bool StaticDeclaredMembersOnly = false)
{
@@ -0,0 +1,21 @@
using Disco.Models.UI.Config.DocumentTemplate;
using System.Collections.Generic;
namespace Disco.Web.Areas.Config.Models.DocumentTemplate
{
public class BulkGenerateModel : ConfigDocumentTemplateBulkGenerate
{
public Disco.Models.Repository.DocumentTemplate DocumentTemplate { get; set; }
public int TemplatePageCount { get; set; }
public List<ItemWithCount<Disco.Models.Repository.UserFlag>> UserFlags { get; set; }
public List<ItemWithCount<Disco.Models.Repository.DeviceProfile>> DeviceProfiles { get; set; }
public List<ItemWithCount<Disco.Models.Repository.DeviceBatch>> DeviceBatches { get; set; }
public List<ItemWithCount<Disco.Models.Repository.DocumentTemplate>> DocumentTemplates { get; set; }
public class ItemWithCount<T>
{
public T Item { get; set; }
public int Count { get; set; }
}
}
}
@@ -0,0 +1,209 @@
@model Disco.Web.Areas.Config.Models.DocumentTemplate.BulkGenerateModel
@using Disco.Services.Interop.ActiveDirectory;
@{
Authorization.RequireAll(Claims.Config.DocumentTemplate.BulkGenerate, Claims.User.Actions.GenerateDocuments);
ViewBag.Title = Html.ToBreadcrumb("Configuration", MVC.Config.Config.Index(), "Document Templates", MVC.Config.DocumentTemplate.Index(null), Model.DocumentTemplate.Description, MVC.Config.DocumentTemplate.Index(Model.DocumentTemplate.Id), "Bulk Generate");
Html.BundleDeferred("~/ClientScripts/Modules/Disco-DocumentBulkGenerate");
}
<div id="DocumentTemplate_BulkGenerate">
<div class="actions">
@using (Html.BeginForm(MVC.API.DocumentTemplate.BulkGenerate(Model.DocumentTemplate.Id), FormMethod.Post))
{
if (Model.TemplatePageCount > 1 && Model.TemplatePageCount % 2 != 0)
{
<input id="DocumentTemplate_BulkGenerate_InsertBlankPage" type="checkbox" name="InsertBlankPage" value="True" checked /><label for="DocumentTemplate_BulkGenerate_InsertBlankPage">Insert Blank Pages for Double-Sided Printing</label>
}
<input id="DocumentTemplate_BulkGenerate_DataIds" name="DataIds" type="hidden" />
<button id="BulkGenerate" class="button" disabled>Bulk Generate</button>
@Html.AntiForgeryToken()
}
<br />
<button id="AddUsers" class="button small">Add Users</button>
<button id="AddGroupMembers" class="button small">Add Group Members</button>
@if (Model.UserFlags.Any(f => f.Count > 0))
{
<button id="AddUserFlag" class="button small">Add With User Flag</button>
}
@if (Model.DeviceProfiles.Any(b => b.Count > 0))
{
<button id="AddDeviceProfile" class="button small">Add With Device Profile</button>
}
@if (Model.DeviceBatches.Any(b => b.Count > 0))
{
<button id="AddDeviceBatch" class="button small">Add With Device Batch</button>
}
@if (Model.DocumentTemplates.Any(b => b.Count > 0))
{
<button id="AddDocumentAttachment" class="button small">Add With Document Attachment</button>
}
</div>
<table class="genericData">
<thead>
<tr>
<th>&nbsp;</th>
<th>Username</th>
<th>Name</th>
<th>Scope</th>
</tr>
</thead>
<tbody>
<tr class="when-none">
<td colspan="4">Add Users</td>
</tr>
</tbody>
</table>
</div>
<div id="DocumentTemplate_BulkGenerate_Dialog_AddUsers" class="dialog dialog-bulk-generate" title="@(Model.DocumentTemplate.Description): Add Users">
<div class="brief">
<div>
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>
Security Groups can also be included. Members will be resolved and added.
</div>
<div class="examples clearfix">
<h4>Examples:</h4>
<div class="example1 code">
user6<br />
smi0099<br />
@(ActiveDirectory.Context.PrimaryDomain.NetBiosName)\rsmith<br />
Domain Admins
</div>
<div class="example2 code">user6,smi0099,@(ActiveDirectory.Context.PrimaryDomain.NetBiosName)\rsmith,Domain Admins</div>
<div class="example3 code">user6;smi0099;@(ActiveDirectory.Context.PrimaryDomain.NetBiosName)\rsmith;Domain Admins</div>
</div>
</div>
@using (Html.BeginForm(MVC.API.DocumentTemplate.BulkGenerateAddUsers(), FormMethod.Post))
{
<div class="field-validation-valid" data-valmsg-replace="true" data-valmsg-for="userIds"></div>
<textarea id="inputBulkGenerateDataIds" name="userIds" data-val="true" data-val-required="Identifiers are required" required></textarea>
@Html.AntiForgeryToken()
}
</div>
<div id="DocumentTemplate_BulkGenerate_Dialog_AddGroupMembers" class="dialog dialog-bulk-generate" title="@(Model.DocumentTemplate.Description): Add Group Members">
<div class="brief">
<div>
Add all members of a group (including recursive members) to the bulk generation.
</div>
</div>
@using (Html.BeginForm(MVC.API.DocumentTemplate.BulkGenerateAddGroupMembers(), FormMethod.Post))
{
<table class="input">
<tbody>
<tr>
<th>
<label for="DocumentTemplate_BulkGenerate_Dialog_AddGroupMembers_Group">Group:</label>
</th>
<td>
<input id="DocumentTemplate_BulkGenerate_Dialog_AddGroupMembers_Group" type="text" name="groupId" data-autocomplete-src="@(Url.Action(MVC.API.System.SearchGroupSubjects()))" required />
</td>
</tr>
</tbody>
</table>
@Html.AntiForgeryToken()
}
</div>
@if (Model.UserFlags.Any(f => f.Count > 0))
{
<div id="DocumentTemplate_BulkGenerate_Dialog_AddUserFlag" class="dialog dialog-bulk-generate" title="@(Model.DocumentTemplate.Description): Add User Flag Assignments">
<div class="brief">
<div>
Add all users associated with the flag to the bulk generation.
</div>
</div>
@using (Html.BeginForm(MVC.API.DocumentTemplate.BulkGenerateAddUserFlag(), FormMethod.Post))
{
<input name="flagId" type="hidden" required />
<div class="dialog-item-picker">
@foreach (var flag in Model.UserFlags)
{
<div class="item @(flag.Count == 0 ? "disabled" : null)" data-userflagid="@flag.Item.Id">
<i class="fa fa-@(flag.Item.Icon) fa-fw fa-lg d-@(flag.Item.IconColour)"></i>@flag.Item.Name <small>(@flag.Count.ToString("N0") user@(flag.Count == 1 ? null : "s"))</small>
</div>
}
</div>
@Html.AntiForgeryToken()
}
</div>
}
@if (Model.DeviceProfiles.Any(b => b.Count > 0))
{
<div id="DocumentTemplate_BulkGenerate_Dialog_AddDeviceProfile" class="dialog dialog-bulk-generate" title="@(Model.DocumentTemplate.Description): Add User by Assigned Device Profile">
<div class="brief">
<div>
Add all users associated with a device in the selected profile to the bulk generation.
</div>
</div>
@using (Html.BeginForm(MVC.API.DocumentTemplate.BulkGenerateAddDeviceProfile(), FormMethod.Post))
{
<input name="deviceProfileId" type="hidden" required />
<div class="dialog-item-picker">
@foreach (var profile in Model.DeviceProfiles)
{
<div class="item @(profile.Count == 0 ? "disabled" : null)" data-id="@profile.Item.Id">
<i class="fa fa-cog fa-fw fa-lg"></i>@profile.Item.Name <small>(@profile.Count.ToString("N0") user@(profile.Count == 1 ? null : "s"))</small>
</div>
}
</div>
@Html.AntiForgeryToken()
}
</div>
}
@if (Model.DeviceBatches.Any(b => b.Count > 0))
{
<div id="DocumentTemplate_BulkGenerate_Dialog_AddDeviceBatch" class="dialog dialog-bulk-generate" title="@(Model.DocumentTemplate.Description): Add User by Assigned Device Batch">
<div class="brief">
<div>
Add all users associated with a device in the selected batch to the bulk generation.
</div>
</div>
@using (Html.BeginForm(MVC.API.DocumentTemplate.BulkGenerateAddDeviceBatch(), FormMethod.Post))
{
<input name="deviceBatchId" type="hidden" required />
<div class="dialog-item-picker">
@foreach (var batch in Model.DeviceBatches)
{
<div class="item @(batch.Count == 0 ? "disabled" : null)" data-id="@batch.Item.Id">
<i class="fa fa-cog fa-fw fa-lg"></i>@batch.Item.Name <small>(@batch.Count.ToString("N0") user@(batch.Count == 1 ? null : "s"))</small>
</div>
}
</div>
@Html.AntiForgeryToken()
}
</div>
}
@if (Model.DocumentTemplates.Any(b => b.Count > 0))
{
<div id="DocumentTemplate_BulkGenerate_Dialog_AddDocumentAttachment" class="dialog dialog-bulk-generate" title="@(Model.DocumentTemplate.Description): Add User by Assigned Device Batch">
<div class="brief">
<div>
Add all users associated with an attachment of the selected document template to the bulk generation.
</div>
</div>
@using (Html.BeginForm(MVC.API.DocumentTemplate.BulkGenerateAddDocumentAttachment(), FormMethod.Post))
{
<input name="documentTemplateId" type="hidden" required />
<div class="dialog-item-picker">
@foreach (var template in Model.DocumentTemplates)
{
<div class="item @(template.Count == 0 ? "disabled" : null)" data-id="@template.Item.Id">
<i class="fa fa-file-text-o fa-fw fa-lg"></i>@template.Item.Id: @template.Item.Description <small>(@template.Count.ToString("N0") user@(template.Count == 1 ? null : "s"))</small>
</div>
}
</div>
<div class="sub">
<label for="DocumentTemplate_BulkGenerate_Dialog_AddDocumentAttachment_Threshold">Attachment Added After <small>(optional)</small></label>
<input id="DocumentTemplate_BulkGenerate_Dialog_AddDocumentAttachment_Threshold" name="threshold" type="date" />
</div>
@Html.AntiForgeryToken()
}
</div>
}
File diff suppressed because it is too large Load Diff