Files
Disco/Disco.Web/Areas/Config/Views/DeviceBatch/Show.cshtml
T
Gary Sharp a819d2722a Feature #49: Active Directory Managed Groups
Document Template Attachments, Device Batches, Device Profiles and User
Flags can be associated with an Active Directory group. This AD group is
then automatically synchronized with relevant User/Machine accounts.
Contains various other UI tweaks and configuration enhancements.
2014-06-16 22:21:31 +10:00

728 lines
36 KiB
Plaintext

@model Disco.Web.Areas.Config.Models.DeviceBatch.ShowModel
@using Disco.Services.Devices.ManagedGroups;
@using Disco.Web.Areas.Config.Models.Shared;
@{
Authorization.Require(Claims.Config.DeviceBatch.Show);
ViewBag.Title = Html.ToBreadcrumb("Configuration", MVC.Config.Config.Index(), "Device Batches", MVC.Config.DeviceBatch.Index(null), Model.DeviceBatch.ToString());
var canConfig = Authorization.Has(Claims.Config.DeviceBatch.Configure);
var canDeviceModelShow = Authorization.Has(Claims.Config.DeviceModel.Show);
var hideAdvanced =
Model.DeviceBatch.AssignedUsersLinkedGroup == null &&
Model.DeviceBatch.DevicesLinkedGroup == null;
if (canConfig)
{
Html.BundleDeferred("~/ClientScripts/Modules/Disco-PropertyChangeHelpers");
Html.BundleDeferred("~/ClientScripts/Modules/Disco-AjaxHelperIcons");
Html.BundleDeferred("~/ClientScripts/Modules/tinymce");
}
}
<div class="form deviceBatches@(hideAdvanced ? " Config_HideAdvanced" : null)" style="width: 730px">
<table>
<tr>
<th style="width: 150px">Id:
</th>
<td>
@Html.DisplayFor(model => model.DeviceBatch.Id)
</td>
</tr>
<tr>
<th>Name:
</th>
<td>
@if (canConfig)
{
@Html.EditorFor(model => model.DeviceBatch.Name)
@AjaxHelpers.AjaxSave()
@AjaxHelpers.AjaxLoader()
<script type="text/javascript">
$(function () {
document.DiscoFunctions.PropertyChangeHelper(
$('#DeviceBatch_Name'),
'Invalid Name',
'@(Url.Action(MVC.API.DeviceBatch.UpdateName(Model.DeviceBatch.Id)))',
'BatchName'
);
});
</script>
}
else
{
@Model.DeviceBatch.Name
}
</td>
</tr>
<tr>
<th>Default Device Model:
</th>
<td>@if (canConfig)
{
@Html.DropDownListFor(model => model.DeviceBatch.DefaultDeviceModelId, Model.DeviceModels.ToSelectListItems(null, true))
@AjaxHelpers.AjaxSave()
@AjaxHelpers.AjaxLoader()
<script type="text/javascript">
$(function () {
document.DiscoFunctions.PropertyChangeHelper(
$('#DeviceBatch_DefaultDeviceModelId'),
null,
'@(Url.Action(MVC.API.DeviceBatch.UpdateDefaultDeviceModelId(Model.DeviceBatch.Id)))',
'DefaultDeviceModelId'
);
});
</script>
}
else
{
if (Model.DefaultDeviceModel == null)
{<span class="smallMessage">&lt;None Specified&gt;</span>}
else
{@Model.DefaultDeviceModel.ToString();
}
}
<br />
<span class="smallMessage">Devices added offline will default to this Device Model.
Once a device enrols the Device Model will be accurately represented.</span>
</td>
</tr>
<tr>
<th>Devices</th>
<td>
@if (Model.DeviceModelMembers.Count > 0)
{
<table class="tableData smallTable">
<thead>
<tr>
<th>Model</th>
<th>Device Count</th>
<th>Decommissioned</th>
</tr>
</thead>
<tbody>
@foreach (var membership in Model.DeviceModelMembers.OrderByDescending(dmm => dmm.DeviceCount))
{
<tr>
<td>
@if (canDeviceModelShow)
{
@Html.ActionLink(membership.DeviceModel.ToString(), MVC.Config.DeviceModel.Index(membership.DeviceModel.Id))
}
else
{
@membership.DeviceModel.ToString()
}
</td>
<td>
@membership.DeviceCount.ToString("n0")
</td>
<td>
@membership.DeviceDecommissionedCount.ToString("n0")
</td>
</tr>
}
</tbody>
<tfoot>
<tr>
<th>Total Models: @Model.DeviceModelMembers.Count.ToString("n0")</th>
<th>@Model.DeviceCount.ToString("n0")</th>
<th>@Model.DeviceDecommissionedCount.ToString("n0")</th>
</tr>
</tfoot>
</table>
}
else
{
<div class="smallMessage">No device models are referenced in this batch.</div>
}
@if (Model.DeviceBatch.UnitQuantity.HasValue && Model.DeviceBatch.UnitQuantity.Value > Model.DeviceCount)
{
var missingCount = Model.DeviceBatch.UnitQuantity.Value - Model.DeviceCount;
<div style="padding: 0.7em 0.7em; margin-top: 20px;" class="ui-state-highlight ui-corner-all">
<i class="fa fa-info-circle information"></i>
@Model.DeviceCount.ToString("n0") of @(Model.DeviceBatch.UnitQuantity.Value.ToString("n0")) purchased devices are managed by Disco. <strong>@missingCount.ToString("n0") @(missingCount == 1 ? "is" : "are") not managed</strong>.
</div>
}
</td>
</tr>
<tr>
<th>Purchase:
</th>
<td class="details">
<table class="sub">
<tr>
<th class="name" style="width: 100px">Purchase Date:
</th>
<td>
@if (canConfig)
{
@Html.EditorFor(model => model.DeviceBatch.PurchaseDate)
@AjaxHelpers.AjaxLoader()
<script>
$(function () {
var dateField = $('#DeviceBatch_PurchaseDate');
document.DiscoFunctions.DateChangeHelper(
dateField,
'Invalid Date',
'@(Url.Action(MVC.API.DeviceBatch.UpdatePurchaseDate(Model.DeviceBatch.Id)))',
'PurchaseDate',
null,
true
);
});
</script>
}
else
{
@CommonHelpers.FriendlyDate(Model.DeviceBatch.PurchaseDate)
}
</td>
</tr>
<tr>
<th>Supplier:
</th>
<td>@if (canConfig)
{
@Html.EditorFor(model => model.DeviceBatch.Supplier)
@AjaxHelpers.AjaxSave()
@AjaxHelpers.AjaxLoader()
<script type="text/javascript">
$(function () {
document.DiscoFunctions.PropertyChangeHelper(
$('#DeviceBatch_Supplier'),
'Batch Supplier',
'@(Url.Action(MVC.API.DeviceBatch.UpdateSupplier(Model.DeviceBatch.Id)))',
'Supplier'
);
});
</script>
}
else
{
if (string.IsNullOrEmpty(Model.DeviceBatch.Supplier))
{<span class="smallMessage">&lt;None Specified&gt;</span>}
else
{@Model.DeviceBatch.Supplier}
}
</td>
</tr>
<tr>
<th>Unit Cost:
</th>
<td>@if (canConfig)
{
@Html.EditorFor(model => model.DeviceBatch.UnitCost)
@AjaxHelpers.AjaxSave()
@AjaxHelpers.AjaxLoader()
<script type="text/javascript">
$(function () {
document.DiscoFunctions.PropertyChangeHelper(
$('#DeviceBatch_UnitCost'),
'Unit Cost',
'@(Url.Action(MVC.API.DeviceBatch.UpdateUnitCost(Model.DeviceBatch.Id)))',
'UnitCost'
);
});
</script>
}
else
{
if (!Model.DeviceBatch.UnitCost.HasValue)
{<span class="smallMessage">&lt;None Specified&gt;</span>}
else
{@Model.DeviceBatch.UnitCost.Value.ToString("C")}
}
</td>
</tr>
<tr>
<th>Quantity:
</th>
<td>@if (canConfig)
{
@Html.EditorFor(model => model.DeviceBatch.UnitQuantity)
@AjaxHelpers.AjaxSave()
@AjaxHelpers.AjaxLoader()
<script type="text/javascript">
$(function () {
document.DiscoFunctions.PropertyChangeHelper(
$('#DeviceBatch_UnitQuantity'),
'Quantity',
'@(Url.Action(MVC.API.DeviceBatch.UpdateUnitQuantity(Model.DeviceBatch.Id)))',
'UnitQuantity'
);
});
</script>
}
else
{
if (!Model.DeviceBatch.UnitQuantity.HasValue)
{<span class="smallMessage">&lt;None Specified&gt;</span>}
else
{@Model.DeviceBatch.UnitQuantity.Value.ToString("n0")}
}
</td>
</tr>
</table>
<div id="DeviceBatch_PurchaseDetails_Container">
<div>
Details @AjaxHelpers.AjaxLoader("ajaxPurchaseDetails")
</div>
@if (canConfig)
{
@Html.EditorFor(model => model.DeviceBatch.PurchaseDetails)
<script type="text/javascript">
$(function () {
var model = {
$field: $('#DeviceBatch_PurchaseDetails'),
fieldName: 'PurchaseDetails',
$ajax_loading: null,
$ajax_ok: null,
updated: function () {
if (!model.$ajax_loading)
model.$ajax_loading = $('#ajax' + model.fieldName + '_loading');
if (!model.$ajax_ok)
model.$ajax_ok = $('#ajax' + model.fieldName + '_ok');
model.$ajax_loading.show();
var data = {};
data[model.fieldName] = model.$field.tinymce().getContent();
$.ajax({
url: '@(Url.Action(MVC.API.DeviceBatch.UpdatePurchaseDetails(Model.DeviceBatch.Id)))',
dataType: 'json',
data: data,
traditional: true,
type: 'POST',
success: function (d) {
if (d == 'OK') {
model.$ajax_loading.hide();
model.$ajax_ok.show().delay('fast').fadeOut('slow');
} else {
model.$ajax_loading.hide();
alert('Unable to update purchase details: ' + d);
}
},
error: function (jqXHR, textStatus, errorThrown) {
alert('Unable to update purchase details: ' + errorThrown);
model.$ajax_loading.hide();
}
})
}
};
model.$field.tinymce({
theme: 'simple',
add_unload_trigger: false,
schema: "html5",
statusbar: false,
setup: function (ed) {
ed.on('init', function () {
$(ed.getWin()).blur(model.updated);
});
}
});
});
</script>
}
else
{
if (string.IsNullOrEmpty(Model.DeviceBatch.PurchaseDetails))
{<span class="smallMessage">&lt;None Specified&gt;</span>}
else
{@(new HtmlString(Model.DeviceBatch.PurchaseDetails))}
}
</div>
</td>
</tr>
<tr>
<th>Warranty:
</th>
<td class="details">
<table class="sub">
<tr>
<th class="name" style="width: 100px">Valid Until:
</th>
<td>
@if (canConfig)
{
@Html.EditorFor(model => model.DeviceBatch.WarrantyValidUntil)
@AjaxHelpers.AjaxLoader()
<script>
$(function () {
var dateField = $('#DeviceBatch_WarrantyValidUntil');
document.DiscoFunctions.DateChangeHelper(
dateField,
'Warranty Valid Until',
'@(Url.Action(MVC.API.DeviceBatch.UpdateWarrantyValidUntil(Model.DeviceBatch.Id)))',
'WarrantyValidUntil',
null,
true
);
});
</script>
}
else
{
@CommonHelpers.FriendlyDate(Model.DeviceBatch.WarrantyValidUntil, "Unknown")
}
</td>
</tr>
</table>
<div id="DeviceBatch_WarrantyDetails_Container">
<div>
Details @AjaxHelpers.AjaxLoader("ajaxWarrantyDetails")
</div>
@if (canConfig)
{
@Html.EditorFor(model => model.DeviceBatch.WarrantyDetails)
<script type="text/javascript">
$(function () {
var model = {
$field: $('#DeviceBatch_WarrantyDetails'),
fieldName: 'WarrantyDetails',
$ajax_loading: null,
$ajax_ok: null,
updated: function () {
if (!model.$ajax_loading)
model.$ajax_loading = $('#ajax' + model.fieldName + '_loading');
if (!model.$ajax_ok)
model.$ajax_ok = $('#ajax' + model.fieldName + '_ok');
model.$ajax_loading.show();
var data = {};
data[model.fieldName] = model.$field.tinymce().getContent();
$.ajax({
url: '@(Url.Action(MVC.API.DeviceBatch.UpdateWarrantyDetails(Model.DeviceBatch.Id)))',
dataType: 'json',
data: data,
traditional: true,
type: 'POST',
success: function (d) {
if (d == 'OK') {
model.$ajax_loading.hide();
model.$ajax_ok.show().delay('fast').fadeOut('slow');
} else {
model.$ajax_loading.hide();
alert('Unable to update warranty details: ' + d);
}
},
error: function (jqXHR, textStatus, errorThrown) {
alert('Unable to update warranty details: ' + errorThrown);
model.$ajax_loading.hide();
}
})
}
};
model.$field.tinymce({
theme: 'simple',
add_unload_trigger: false,
schema: "html5",
statusbar: false,
setup: function (ed) {
ed.on('init', function () {
$(ed.getWin()).blur(model.updated);
});
}
});
});
</script>
}
else
{
if (string.IsNullOrEmpty(Model.DeviceBatch.WarrantyDetails))
{<span class="smallMessage">&lt;None Specified&gt;</span>}
else
{@(new HtmlString(Model.DeviceBatch.WarrantyDetails))}
}
</div>
</td>
</tr>
<tr>
<th>Insurance:
</th>
<td class="details">
<table class="sub">
<tr>
<th class="name" style="width: 100px">Supplier:
</th>
<td>@if (canConfig)
{
@Html.EditorFor(model => model.DeviceBatch.InsuranceSupplier)
@AjaxHelpers.AjaxSave()
@AjaxHelpers.AjaxLoader()
<script type="text/javascript">
$(function () {
document.DiscoFunctions.PropertyChangeHelper(
$('#DeviceBatch_InsuranceSupplier'),
'Insurance Supplier',
'@(Url.Action(MVC.API.DeviceBatch.UpdateInsuranceSupplier(Model.DeviceBatch.Id)))',
'InsuranceSupplier'
);
});
</script>
}
else
{
if (string.IsNullOrEmpty(Model.DeviceBatch.InsuranceSupplier))
{<span class="smallMessage">&lt;None Specified&gt;</span>}
else
{@Model.DeviceBatch.InsuranceSupplier;
}
}
</td>
</tr>
<tr>
<th class="name">Insured Date:
</th>
<td>@if (canConfig)
{
@Html.EditorFor(model => model.DeviceBatch.InsuredDate)
@AjaxHelpers.AjaxLoader()
<script>
$(function () {
var dateField = $('#DeviceBatch_InsuredDate');
document.DiscoFunctions.DateChangeHelper(
dateField,
'Insured Date',
'@(Url.Action(MVC.API.DeviceBatch.UpdateInsuredDate(Model.DeviceBatch.Id)))',
'InsuredDate',
null,
true
);
});
</script>
}
else
{
@CommonHelpers.FriendlyDate(Model.DeviceBatch.InsuredDate, "Unknown")
}
</td>
</tr>
<tr>
<th class="name">Insured Until:
</th>
<td>@if (canConfig)
{
@Html.EditorFor(model => model.DeviceBatch.InsuredUntil)
@AjaxHelpers.AjaxLoader()
<script>
$(function () {
var dateField = $('#DeviceBatch_InsuredUntil');
document.DiscoFunctions.DateChangeHelper(
dateField,
'Insured Until',
'@(Url.Action(MVC.API.DeviceBatch.UpdateInsuredUntil(Model.DeviceBatch.Id)))',
'InsuredUntil',
null,
true
);
});
</script>
}
else
{
@CommonHelpers.FriendlyDate(Model.DeviceBatch.InsuredUntil, "Unknown")
}
</td>
</tr>
</table>
<div id="DeviceBatch_InsuranceDetails_Container">
<div>
Details @AjaxHelpers.AjaxLoader("ajaxInsuranceDetails")
</div>
@if (canConfig)
{
@Html.EditorFor(model => model.DeviceBatch.InsuranceDetails)
<script type="text/javascript">
$(function () {
var model = {
$field: $('#DeviceBatch_InsuranceDetails'),
$ajax_loading: null,
$ajax_ok: null,
updated: function () {
if (!model.$ajax_loading)
model.$ajax_loading = $('#ajaxInsuranceDetails_loading');
if (!model.$ajax_ok)
model.$ajax_ok = $('#ajaxInsuranceDetails_ok');
model.$ajax_loading.show();
var data = { InsuranceDetails: model.$field.tinymce().getContent() };
$.ajax({
url: '@(Url.Action(MVC.API.DeviceBatch.UpdateInsuranceDetails(Model.DeviceBatch.Id)))',
dataType: 'json',
data: data,
traditional: true,
type: 'POST',
success: function (d) {
if (d == 'OK') {
model.$ajax_loading.hide();
model.$ajax_ok.show().delay('fast').fadeOut('slow');
} else {
model.$ajax_loading.hide();
alert('Unable to update insurance details: ' + d);
}
},
error: function (jqXHR, textStatus, errorThrown) {
alert('Unable to update insurance details: ' + errorThrown);
model.$ajax_loading.hide();
}
})
}
};
model.$field.tinymce({
theme: 'simple',
add_unload_trigger: false,
schema: "html5",
statusbar: false,
setup: function (ed) {
ed.on('init', function () {
$(ed.getWin()).blur(model.updated);
});
}
});
});
</script>
}
else
{
if (string.IsNullOrEmpty(Model.DeviceBatch.InsuranceDetails))
{<span class="smallMessage">&lt;None Specified&gt;</span>}
else
{@(new HtmlString(Model.DeviceBatch.InsuranceDetails))}
}
</div>
</td>
</tr>
<tr>
<th>Comments:<br />
@AjaxHelpers.AjaxLoader("ajaxComments")
</th>
<td>@if (canConfig)
{
@Html.EditorFor(model => model.DeviceBatch.Comments)
<script type="text/javascript">
$(function () {
var model = {
$field: $('#DeviceBatch_Comments'),
$ajax_loading: null,
$ajax_ok: null,
updated: function () {
if (!model.$ajax_loading)
model.$ajax_loading = $('#ajaxComments_loading');
if (!model.$ajax_ok)
model.$ajax_ok = $('#ajaxComments_ok');
model.$ajax_loading.show();
var data = { Comments: model.$field.tinymce().getContent() };
$.ajax({
url: '@(Url.Action(MVC.API.DeviceBatch.UpdateComments(Model.DeviceBatch.Id)))',
dataType: 'json',
data: data,
traditional: true,
type: 'POST',
success: function (d) {
if (d == 'OK') {
model.$ajax_loading.hide();
model.$ajax_ok.show().delay('fast').fadeOut('slow');
} else {
model.$ajax_loading.hide();
alert('Unable to update comments: ' + d);
}
},
error: function (jqXHR, textStatus, errorThrown) {
alert('Unable to update comments: ' + errorThrown);
model.$ajax_loading.hide();
}
})
}
};
model.$field.tinymce({
theme: 'simple',
add_unload_trigger: false,
schema: "html5",
statusbar: false,
setup: function (ed) {
ed.on('init', function () {
$(ed.getWin()).blur(model.updated);
});
}
});
});
</script>
}
else
{
if (string.IsNullOrEmpty(Model.DeviceBatch.Comments))
{<span class="smallMessage">&lt;None Specified&gt;</span>}
else
{@(new HtmlString(Model.DeviceBatch.Comments))}
}
</td>
</tr>
@if (hideAdvanced)
{
<tr>
<td colspan="2" style="text-align: right;">
<button id="Config_HideAdvanced_Show" class="button small">Show Advanced Options</button>
<script>
$(function () {
$('#Config_HideAdvanced_Show').click(function () {
var $this = $(this);
$this.closest('.Config_HideAdvanced').removeClass('Config_HideAdvanced');
$this.closest('tr').remove();
});
});
</script>
</td>
</tr>
}
<tr class="Config_HideAdvanced_Item">
<th>Linked Groups:
</th>
<td>
<div>
@Html.Partial(MVC.Config.Shared.Views.LinkedGroupInstance, new LinkedGroupModel()
{
CanConfigure = canConfig,
CategoryDescription = DeviceBatchDevicesManagedGroup.GetCategoryDescription(Model.DeviceBatch),
Description = DeviceBatchDevicesManagedGroup.GetDescription(Model.DeviceBatch),
ManagedGroup = Model.DevicesLinkedGroup,
UpdateUrl = Url.Action(MVC.API.DeviceBatch.UpdateDevicesLinkedGroup(Model.DeviceBatch.Id, redirect: true))
})
@Html.Partial(MVC.Config.Shared.Views.LinkedGroupInstance, new LinkedGroupModel()
{
CanConfigure = canConfig,
CategoryDescription = DeviceBatchAssignedUsersManagedGroup.GetCategoryDescription(Model.DeviceBatch),
Description = DeviceBatchAssignedUsersManagedGroup.GetDescription(Model.DeviceBatch),
ManagedGroup = Model.AssignedUsersLinkedGroup,
UpdateUrl = Url.Action(MVC.API.DeviceBatch.UpdateAssignedUsersLinkedGroup(Model.DeviceBatch.Id, redirect: true))
})
@if (canConfig)
{
@Html.Partial(MVC.Config.Shared.Views.LinkedGroupShared)
}
</div>
<div style="padding: 0.7em 0.7em;" class="ui-state-highlight ui-corner-all">
<i class="fa fa-info-circle information"></i>&nbsp;Linked Active Directory Groups are automatically synchronized to include members currently associated with this Device Batch.
</div>
</td>
</tr>
</table>
</div>
<div class="actionBar">
@if (Model.CanDelete)
{
@Html.ActionLinkButton("Delete", MVC.API.DeviceBatch.Delete(Model.DeviceBatch.Id, true), "buttonDelete")
}
@if (Model.DeviceCount > 0)
{
if (Authorization.Has(Claims.Device.Actions.Export))
{
@Html.ActionLinkButton("Export Devices", MVC.Device.Export(null, Disco.Models.Services.Devices.Exporting.DeviceExportTypes.Batch, Model.DeviceBatch.Id))
}
if (Authorization.Has(Claims.Device.Search) && Model.DeviceCount > 0)
{
@Html.ActionLinkButton(string.Format("View {0} Device{1}", Model.DeviceCount, (Model.DeviceCount != 1 ? "s" : null)), MVC.Search.Query(Model.DeviceBatch.Id.ToString(), "DeviceBatch"))
}
}
</div>