Files
Disco/Disco.Web/Areas/Config/Views/DeviceProfile/Show.cshtml
T
2025-09-18 18:27:29 +10:00

1159 lines
62 KiB
Plaintext

@model Disco.Web.Areas.Config.Models.DeviceProfile.ShowModel
@using Disco.Services.Devices.ManagedGroups;
@using Disco.Web.Areas.Config.Models.Shared;
@{
Authorization.Require(Claims.Config.DeviceProfile.Show);
ViewBag.Title = Html.ToBreadcrumb("Configuration", MVC.Config.Config.Index(), "Device Profiles", MVC.Config.DeviceProfile.Index(null), Model.DeviceProfile.ToString());
var canConfig = Authorization.Has(Claims.Config.DeviceProfile.Configure);
var canConfigExpression = Authorization.Has(Claims.Config.DeviceProfile.ConfigureComputerNameTemplate);
var canDelete = (Authorization.Has(Claims.Config.DeviceProfile.Delete) && Model.CanDelete);
var canViewPlugins = Authorization.Has(Claims.Config.Plugin.Install);
var hideAdvanced =
Model.DeviceProfile.AssignedUsersLinkedGroup == null &&
Model.DeviceProfile.DevicesLinkedGroup == null;
if (canConfig)
{
Html.BundleDeferred("~/Style/Fancytree");
Html.BundleDeferred("~/ClientScripts/Modules/jQuery-Fancytree");
Html.BundleDeferred("~/ClientScripts/Modules/Disco-PropertyChangeHelpers");
}
}
<div id="configurationDeviceProfileShow" class="form@(hideAdvanced ? " Config_HideAdvanced" : null)" style="width: 640px">
<table>
<tr>
<th style="width: 170px;">
Id:
</th>
<td>
@Html.DisplayFor(model => model.DeviceProfile.Id)
</td>
</tr>
<tr>
<th>
Name:
</th>
<td>
@if (canConfig)
{
@Html.TextBoxFor(model => model.DeviceProfile.Name)
@AjaxHelpers.AjaxSave()
@AjaxHelpers.AjaxLoader()
<script type="text/javascript">
$(function () {
document.DiscoFunctions.PropertyChangeHelper(
$('#DeviceProfile_Name'),
'Name',
'@Url.Action(MVC.API.DeviceProfile.UpdateName(Model.DeviceProfile.Id))',
'ProfileName'
);
});
</script>
}
else
{
@Model.DeviceProfile.Name
}
</td>
</tr>
<tr>
<th>
Short Name:
</th>
<td>
@if (canConfig)
{
@Html.TextBoxFor(model => model.DeviceProfile.ShortName)
@AjaxHelpers.AjaxSave()
@AjaxHelpers.AjaxLoader()
<script type="text/javascript">
$(function () {
document.DiscoFunctions.PropertyChangeHelper(
$('#DeviceProfile_ShortName'),
'Short Name',
'@Url.Action(MVC.API.DeviceProfile.UpdateShortName(Model.DeviceProfile.Id))',
'ShortName'
);
});
</script>
}
else
{
@Model.DeviceProfile.ShortName
}
</td>
</tr>
<tr>
<th>
Description:
</th>
<td>
@if (canConfig)
{
@Html.EditorFor(model => model.DeviceProfile.Description)
@AjaxHelpers.AjaxSave()
@AjaxHelpers.AjaxLoader()
<script type="text/javascript">
$(function () {
document.DiscoFunctions.PropertyChangeHelper(
$('#DeviceProfile_Description'),
'Description',
'@Url.Action(MVC.API.DeviceProfile.UpdateDescription(Model.DeviceProfile.Id))',
'Description'
);
});
</script>
}
else
{
@Model.DeviceProfile.Description
}
</td>
</tr>
<tr>
<th>Members</th>
<td>
<div><strong>@Model.DeviceCount.ToString("n0")</strong> @(Model.DeviceCount == 1 ? "devices is a member" : "devices are members") of this profile.</div>
@if (Model.DeviceDecommissionedCount > 0)
{
<div class="smallMessage">@Model.DeviceDecommissionedCount.ToString("n0") @(Model.DeviceDecommissionedCount == 1 ? "device is" : "devices are") decommissioned.</div>
}
</td>
</tr>
<tr>
<th>
Distribution Type:
</th>
<td>
@if (canConfig)
{
@Html.DropDownList("DeviceProfile_DistributionType", Model.DeviceProfileDistributionTypes)
@AjaxHelpers.AjaxLoader()
<script type="text/javascript">
$(function () {
document.DiscoFunctions.PropertyChangeHelper(
$('#DeviceProfile_DistributionType'),
null,
'@Url.Action(MVC.API.DeviceProfile.UpdateDistributionType(Model.DeviceProfile.Id))',
'DistributionType'
);
});
</script>
}
else
{
@Model.DeviceProfile.DistributionType.ToString()
}
<div class="info-box">
<p class="fa-p">
<i class="fa fa-info-circle"></i>One-to-many devices are typically shared.
One-to-one devices are typically assigned to a user;
enrolment with a one-to-one device isn't considered complete until it is assigned.
</p>
</div>
</td>
</tr>
<tr>
<th>
Address:
</th>
<td>
@if (canConfig)
{
@Html.DropDownListFor(m => m.DeviceProfile.DefaultOrganisationAddress, Model.OrganisationAddresses.ToSelectListItems(Model.DeviceProfile.DefaultOrganisationAddress, true, "None"))
@AjaxHelpers.AjaxLoader()
<script type="text/javascript">
$(function () {
document.DiscoFunctions.PropertyChangeHelper(
$('#DeviceProfile_DefaultOrganisationAddress'),
null,
'@Url.Action(MVC.API.DeviceProfile.UpdateDefaultOrganisationAddress(Model.DeviceProfile.Id))',
'DefaultOrganisationAddress'
);
});
</script>
}
else
{
if (Model.DefaultOrganisationAddress == null)
{
<span class="smallMessage">&lt;None Specified&gt;</span>
}
else
{
@Model.DefaultOrganisationAddress.ToString()
}
}
<div class="info-box">
<p class="fa-p">
<i class="fa fa-info-circle"></i>The profile address is used to separate jobs for <a href="@Url.Action(MVC.Config.Organisation.Index())">multi-site mode</a>.
It is also suggested as the default address for warranty/repair actions.
</p>
</div>
</td>
</tr>
<tr>
<th>Policies</th>
<td>
<div>
@if (canConfig)
{
<input id="DeviceProfile_ProvisionADAccount" type="checkbox" @(Model.DeviceProfile.ProvisionADAccount ? new MvcHtmlString("checked=\"checked\" ") : new MvcHtmlString(string.Empty)) />
<script type="text/javascript">
$(function () {
document.DiscoFunctions.PropertyChangeHelper(
$('#DeviceProfile_ProvisionADAccount'),
null,
'@Url.Action(MVC.API.DeviceProfile.UpdateProvisionADAccount(Model.DeviceProfile.Id))',
'ProvisionADAccount'
);
});
</script>
}
else
{
<input id="DeviceProfile_ProvisionADAccount" type="checkbox" @(Model.DeviceProfile.ProvisionADAccount ? new MvcHtmlString("checked=\"checked\" ") : new MvcHtmlString(string.Empty)) disabled="disabled" />
}
<label for="DeviceProfile_ProvisionADAccount">
Provision Active Directory Account
</label>
@AjaxHelpers.AjaxLoader()
<div class="info-box">
<p class="fa-p">
<i class="fa fa-info-circle"></i>When enabled an Active Directory account will be provisioned for the device when enrolment occurs
and the device will be joined to the domain (refer to the <code>Computer&nbsp;Name&nbsp;Template&nbsp;Expression</code> and the
<code>Organisational&nbsp;Unit</code> configuration options below).
</p>
</div>
</div>
<div style="margin-top: 8px;">
@if (canConfig)
{
<input id="DeviceProfile_ProvisionFromOtherDomain" type="checkbox" @(Model.DeviceProfile.ProvisionFromOtherDomain ? new MvcHtmlString("checked=\"checked\" ") : new MvcHtmlString(string.Empty)) />
<script type="text/javascript">
$(function () {
document.DiscoFunctions.PropertyChangeHelper(
$('#DeviceProfile_ProvisionFromOtherDomain'),
null,
'@Url.Action(MVC.API.DeviceProfile.UpdateProvisionFromOtherDomain(Model.DeviceProfile.Id))',
'ProvisionFromOtherDomain'
);
});
</script>
}
else
{
<input id="DeviceProfile_ProvisionFromOtherDomain" type="checkbox" @(Model.DeviceProfile.ProvisionFromOtherDomain ? new MvcHtmlString("checked=\"checked\" ") : new MvcHtmlString(string.Empty)) disabled="disabled" />
}
<label for="DeviceProfile_ProvisionFromOtherDomain">
Provision from another Domain
</label>
@AjaxHelpers.AjaxLoader()
<div class="info-box">
<p class="fa-p">
<i class="fa fa-info-circle"></i>When enabled, devices joined to another domain will be enrolled. Based on other policies this may change the domain they are bound to (eg. Provision Active Directory Account)
</p>
</div>
</div>
<div style="margin-top: 8px;">
@if (canConfig)
{
<input id="DeviceProfile_AssignedUserLocalAdmin" type="checkbox" @(Model.DeviceProfile.AssignedUserLocalAdmin ? new MvcHtmlString("checked=\"checked\" ") : new MvcHtmlString(string.Empty)) />
<script type="text/javascript">
$(function () {
document.DiscoFunctions.PropertyChangeHelper(
$('#DeviceProfile_AssignedUserLocalAdmin'),
null,
'@Url.Action(MVC.API.DeviceProfile.UpdateAssignedUserLocalAdmin(Model.DeviceProfile.Id))',
'AssignedUserLocalAdmin'
);
});
</script>
}
else
{
<input id="DeviceProfile_AssignedUserLocalAdmin" type="checkbox" @(Model.DeviceProfile.AssignedUserLocalAdmin ? new MvcHtmlString("checked=\"checked\" ") : new MvcHtmlString(string.Empty)) disabled="disabled" />
}
<label for="DeviceProfile_AssignedUserLocalAdmin">
Assigned User is Local Administrator
</label>
@AjaxHelpers.AjaxLoader()
<div class="info-box">
<p class="fa-p">
<i class="fa fa-info-circle"></i>When enabled the user assigned to the device will be added to the <code>Local&nbsp;Administrators</code> group during device enrolment.
</p>
</div>
</div>
<div style="margin-top: 8px;">
@if (canConfig)
{
<input id="DeviceProfile_SetAssignedUserForLogon" type="checkbox" @(Model.DeviceProfile.SetAssignedUserForLogon ? new MvcHtmlString("checked=\"checked\" ") : new MvcHtmlString(string.Empty)) />
<script type="text/javascript">
$(function () {
document.DiscoFunctions.PropertyChangeHelper(
$('#DeviceProfile_SetAssignedUserForLogon'),
null,
'@Url.Action(MVC.API.DeviceProfile.UpdateSetAssignedUserForLogon(Model.DeviceProfile.Id))',
'setAssignedUserForLogon'
);
});
</script>
}
else
{
<input id="DeviceProfile_SetAssignedUserForLogon" type="checkbox" @(Model.DeviceProfile.SetAssignedUserForLogon ? new MvcHtmlString("checked=\"checked\" ") : new MvcHtmlString(string.Empty)) disabled="disabled" />
}
<label for="DeviceProfile_SetAssignedUserForLogon">
Set Assigned User for Logon
</label>
@AjaxHelpers.AjaxLoader()
<div class="info-box">
<p class="fa-p">
<i class="fa fa-info-circle"></i>When enabled the assigned user details will be pre-populated at the device logon screen.
</p>
</div>
</div>
<div style="margin-top: 8px;">
@if (canConfig)
{
<input id="DeviceProfile_AllowUntrustedReimageJobEnrolment" type="checkbox" @(Model.DeviceProfile.AllowUntrustedReimageJobEnrolment ? new MvcHtmlString("checked=\"checked\" ") : null) />
<script type="text/javascript">
$(function () {
document.DiscoFunctions.PropertyChangeHelper(
$('#DeviceProfile_AllowUntrustedReimageJobEnrolment'),
null,
'@Url.Action(MVC.API.DeviceProfile.UpdateAllowUntrustedReimageJobEnrolment(Model.DeviceProfile.Id))',
'AllowUntrustedReimageJobEnrolment'
);
});
</script>
}
else
{
<input id="DeviceProfile_AllowUntrustedReimageJobEnrolment" type="checkbox" @(Model.DeviceProfile.AllowUntrustedReimageJobEnrolment ? new MvcHtmlString("checked=\"checked\" ") : new MvcHtmlString(string.Empty)) disabled="disabled" />
}
<label for="DeviceProfile_AllowUntrustedReimageJobEnrolment">
Allow Untrusted Enrolment Where a <span class="code">'Software - Reimage'</span> Job is Open
</label>
@AjaxHelpers.AjaxLoader()
<div class="info-box">
<p class="fa-p">
<i class="fa fa-info-circle"></i>When enabled an untrusted device enrolment will be allowed if a <code>Software&nbsp;-&nbsp;Reimage</code> job is open for the device.
</p>
</div>
</div>
</td>
</tr>
<tr>
<th>
Computer Name<br />
Template Expression:
</th>
<td>
<div id="displayComputerNameTemplate" class="code">
@if (string.IsNullOrWhiteSpace(Model.DeviceProfile.ComputerNameTemplate))
{
<span class="smallMessage">&lt;None Specified&gt;</span>
}
else
{
@Model.DeviceProfile.ComputerNameTemplate
}
</div>
@if (canConfig && canConfigExpression)
{
<a id="changeComputerNameTemplate" href="#" class="button small">Change</a>@AjaxHelpers.AjaxLoader()
<div id="dialogComputerNameTemplate" title="Computer Name Template" class="dialog">
@using (Html.BeginForm(MVC.API.DeviceProfile.UpdateComputerNameTemplate(Model.DeviceProfile.Id, null, false)))
{
@Html.AntiForgeryToken()
@Html.TextArea("ComputerNameTemplate", Model.DeviceProfile.ComputerNameTemplate, new { spellcheck = "false", required = "required" })
}
<div class="hidden info-box error code whitespace-pre-wrap">
</div>
<div class="test hidden">
@using (Html.BeginForm(MVC.API.DeviceProfile.TestComputerNameTemplate(Model.DeviceProfile.Id)))
{
@Html.AntiForgeryToken();
<table class="genericData">
<thead>
<tr>
<th>Serial Number</th>
<th>Current</th>
<th>Result</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<input id="ComputerNameTemplateTestSearch" name="UserSpecifiedDeviceSerialNumber" type="text" placeholder="Device Serial Number" spellcheck="false" />
</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
</tbody>
</table>
}
</div>
<button id="ComputerNameTemplateTest" class="button small" type="button">Test Template</button>@AjaxHelpers.AjaxLoader()
</div>
<script type="text/javascript">
$(() => {
let $dialog = null;
let $textarea = null;
let currentValue = null;
$('#changeComputerNameTemplate').click(e => {
e.preventDefault();
if (!$dialog) {
$textarea = $('#ComputerNameTemplate');
currentValue = $textarea.val();
$dialog = $('#dialogComputerNameTemplate').dialog({
autoOpen: false,
buttons: null,
draggable: false,
modal: true,
resizable: false,
width: 700,
buttons: {
"Cancel": () => {
$textarea.val(currentValue);
$dialog.find('.error').addClass('hidden');
$dialog.dialog("close");
},
"Expression Browser": () => {
window.open('@(Url.Action(MVC.Config.Expressions.Browser()))', '_blank');
},
"Save": () => {
const $form = $textarea.closest('form');
$(this).find('.error').addClass('hidden');
if ($form[0].reportValidity()) {
const body = new FormData($form[0]);
const url = $form.attr('action');
const $ajaxLoading = $('#changeComputerNameTemplate').nextAll('.ajaxLoading').first();
$ajaxLoading.show();
$dialog.dialog('close');
fetch(url, {
method: 'POST',
body: body
}).then(response => {
if (response.ok) {
currentValue = $textarea.val();
const $display = $('#displayComputerNameTemplate');
if (currentValue) {
$display.text(currentValue);
} else {
$display.html('<span class="smallMessage">&lt;None Specified&gt;</span>');
}
$ajaxLoading.hide().next('.ajaxOk').show().delay('fast').fadeOut('slow');
} else if (response.status == 400) {
response.json().then(data => {
$ajaxLoading.hide();
$dialog.dialog('open');
$dialog.find('.error').text(data).removeClass('hidden');
console.error(data);
})
}
}).catch(error => {
alert('Unable to save computer name template');
$ajaxLoading.hide();
$dialog.dialog('open');
$dialog.find('.error').text('Unable to save computer name template: ' + error).removeClass('hidden');
console.error(error);
});
}
}
}
});
const $buttonTest = $dialog.find('#ComputerNameTemplateTest');
$buttonTest.click(e => {
e.preventDefault();
const $test = $dialog.find('.test');
const $ajaxLoading = $(e.currentTarget).nextAll('.ajaxLoading').first();
$ajaxLoading.show();
const $form = $test.find('form');
const url = $form.attr('action');
const body = new FormData($form[0]);
body.append('ComputerNameTemplate', $textarea.val());
fetch(url, {
method: 'POST',
body: body
}).then(response => {
if (response.ok) {
response.json().then(data => {
const $table = $test.find('table tbody');
if (data.UserSpecifiedResult) {
const result = data.UserSpecifiedResult;
const row = $table.find('tr').first();
row.find('input').val(result.DeviceSerialNumber);
const columns = row.find('td');
columns.eq(1).html('');
$('<span class="code">').text(result.DeviceComputerName)
.appendTo(columns.eq(1))
columns.eq(2).html('');
$('<span class="code">').text(result.RenderedComputerName)
.appendTo(columns.eq(2))
if (!result.Success) {
$('<div class="info-box error code whitespace-pre-wrap">').text(result.ErrorMessage).appendTo(columns[2]);
}
}
if (data.RandomDeviceResults) {
$table.find('tr').slice(1).remove();
for (var i = 0; i < data.RandomDeviceResults.length; i++) {
const result = data.RandomDeviceResults[i];
const row = $('<tr><td></td><td></td><td></td></tr>');
const columns = row.find('td');
$('<a>').attr({
href: result.Url,
target: '_blank'
}).text(result.DeviceSerialNumber)
.appendTo(columns.eq(0));
$('<span class="code">').text(result.DeviceComputerName)
.appendTo(columns.eq(1))
$('<span class="code">').text(result.RenderedComputerName)
.appendTo(columns.eq(2))
if (!result.Success) {
$('<div class="info-box error code whitespace-pre-wrap">').text(result.ErrorMessage).appendTo(columns.eq(2));
}
row.appendTo($table);
}
}
$test.removeClass('hidden');
$ajaxLoading.hide().next('.ajaxOk').show().delay('fast').fadeOut('slow');
});
} else if (response.status == 400) {
response.json().then(data => {
$ajaxLoading.hide();
$test.addClass('hidden');
$dialog.find('.error').text(data).removeClass('hidden');
console.error(data);
})
}
}).catch(error => {
$ajaxLoading.hide();
$test.addClass('hidden');
$dialog.find('.error').text('Unable to test computer name template: ' + error).removeClass('hidden');
console.error(error);
});
return false;
})
const $testSearchText = $dialog.find('#ComputerNameTemplateTestSearch');
$testSearchText.autocomplete({
source: '@(Url.Action(MVC.API.Search.Devices()))',
minLength: 2,
focus: function (e, ui) {
$testSearchText.val(ui.item.Id);
return false;
},
select: function (e, ui) {
$testSearchText.val(ui.item.Id).blur();
$buttonTest.click();
return false;
}
}).data('ui-autocomplete')._renderItem = function (ul, item) {
return $('<li>')
.data('item.autocomplete', item)
.append($('<a>').text(item.Description))
.appendTo(ul);
};
}
$dialog.dialog('open');
return false;
});
});
</script>
}
<div style="margin-top: 8px;">
@if (canConfig)
{
<input id="DeviceProfile_EnforceComputerNameConvention" type="checkbox" @(Model.DeviceProfile.EnforceComputerNameConvention ? new MvcHtmlString("checked=\"checked\" ") : new MvcHtmlString(string.Empty)) />
<script type="text/javascript">
$(function () {
document.DiscoFunctions.PropertyChangeHelper(
$('#DeviceProfile_EnforceComputerNameConvention'),
null,
'@Url.Action(MVC.API.DeviceProfile.UpdateEnforceComputerNameConvention(Model.DeviceProfile.Id))',
'EnforceComputerNameConvention'
);
});
</script>
}
else
{
<input id="DeviceProfile_EnforceComputerNameConvention" type="checkbox" @(Model.DeviceProfile.EnforceComputerNameConvention ? new MvcHtmlString("checked=\"checked\" ") : new MvcHtmlString(string.Empty)) disabled="disabled" />
}
<label for="DeviceProfile_EnforceComputerNameConvention">
Enforce Naming Convention
</label>
@AjaxHelpers.AjaxLoader()
</div>
<div class="info-box">
<p class="fa-p">
<i class="fa fa-info-circle"></i>Computer names are only changed when Active Directory accounts are provisioned.
If the device has already joined the domain when enrolment occurs the name will remain the same unless Enforce Naming Convention is enabled.
</p>
</div>
</td>
</tr>
<tr>
<th>
Organisational Unit:
</th>
<td>
@if (canConfig)
{
<div id="DeviceProfile_OrganisationalUnit" class="code" data-value="@Model.DeviceProfile.OrganisationalUnit">
<span>
@Model.FriendlyOrganisationalUnitName
</span>
</div>
<button id="changeOrganisationalUnit" type="button" class="button small">Change</button>@AjaxHelpers.AjaxLoader()
<div id="dialogOrganisationalUnit" title="Organisational Unit" class="dialog" data-url="@(Url.Action(MVC.API.System.DomainOrganisationalUnits()))">
<div id="dialogOrganisationalUnit_Loading">
@AjaxHelpers.AjaxLoader() Loading Organisational Units
</div>
<div id="treeOrganisationalUnit" class="organisationalUnitTree">
</div>
@using (Html.BeginForm(MVC.API.DeviceProfile.UpdateOrganisationalUnit(Model.DeviceProfile.Id, redirect: true)))
{
@Html.AntiForgeryToken();
<input type="hidden" name="OrganisationalUnit" />
<div class="enforceOrganisationalUnit">
<input id="enforceOrganisationalUnit" type="checkbox" name="enforce" value="true" /> <label for="enforceOrganisationalUnit">Move all profile devices to this organisational unit</label>
</div>
}
</div>
<script type="text/javascript">
$(function () {
var ouValue = $('#DeviceProfile_OrganisationalUnit').attr('data-value');
let $ouTree = null;
let ouTree = null;
let $dialog = null;
var $enforceCheckbox;
var ouSet = function (ou) {
const $form = $dialog.find('form');
$form.find('input[name="OrganisationalUnit"]').val(ou);
$form.submit();
}
var expandNodeTree = function (node) {
var parent = node.parent;
if (parent) {
expandNodeTree(parent);
parent.setExpanded(true, { noAnimation: true, noEvents: false });
}
}
var expandAndFocusNode = function (nodeKey) {
if (ouTree) {
var ouNode = ouTree.getNodeByKey(ouValue);
if (ouNode) {
expandNodeTree(ouNode);
ouNode.setFocus(true);
ouNode.setActive(true);
var li = ouNode.li;
var liOffset = li.offsetParent;
if (liOffset && li.offsetTop + li.offsetHeight > liOffset.offsetHeight) {
$(liOffset).animate({ 'scrollTop': li.offsetTop - liOffset.offsetHeight + li.offsetHeight + 4 }, 'fast');
}
}
}
}
var ouChange = async function () {
if (!$dialog) {
$dialog = $('#dialogOrganisationalUnit').dialog({
autoOpen: false,
buttons: null,
draggable: false,
modal: true,
resizable: false,
width: 500,
height: 500
});
$loading = $('#dialogOrganisationalUnit_Loading');
$loading.find('i.ajaxLoading').show();
$ouTree = $('#treeOrganisationalUnit');
$dialog.css('overflow', 'visible');
$enforceCheckbox = $('#enforceOrganisationalUnit');
const body = new FormData();
body.append('__RequestVerificationToken', document.body.dataset.antiforgery);
const response = await fetch($dialog.attr('data-url'), {
method: 'POST',
body: body
});
const data = await response.json();
$loading.hide();
// Make 'Domains' unselectable
$.each(data, function (i, node) {
node.unselectable = true;
});
ouTree = $ouTree.fancytree({
source: data,
checkbox: false,
selectMode: 1,
keyboard: false,
fx: null
}).fancytree('getTree');
ouTree.$container.css('position', 'relative');
// Set Buttons
$dialog.dialog('option', 'buttons', {
'Use Default Computers Container': function () {
var $this = $(this);
$this.css('overflow', 'hidden');
$this.dialog("disable");
$this.dialog("option", "buttons", null);
ouSet('');
},
'Save': function () {
var node = ouTree.getActiveNode();
if (node && node.key.substr(0, 3).toLowerCase() == 'ou=') {
var $this = $(this);
$this.css('overflow', 'hidden');
$this.dialog("disable");
$this.dialog("option", "buttons", null);
ouSet(node.key);
} else {
alert('Select an Organisational Unit to Save')
}
}
});
// Expand
expandAndFocusNode(ouValue);
ouTree.options.fx = { height: "toggle", duration: 200 };
}
$dialog.dialog('open');
$enforceCheckbox.prop('checked', $('#DeviceProfile_EnforceOrganisationalUnit').prop('checked'));
};
$('#changeOrganisationalUnit').click(ouChange);
});
</script>
}
else
{
<div id="displayOrganisationalUnit" class="code">
<span>
@Model.FriendlyOrganisationalUnitName
</span>
</div>
}
@if (!Model.OrganisationalUnitExists)
{
<div class="info-box error">
<p class="fa-p">
<i class="fa fa-exclamation-triangle"></i>The Organisational Unit could not be found.
</p>
</div>
}
<div style="margin-top: 8px;">
@if (canConfig)
{
<input id="DeviceProfile_EnforceOrganisationalUnit" type="checkbox" @(Model.DeviceProfile.EnforceOrganisationalUnit ? new MvcHtmlString("checked=\"checked\" ") : new MvcHtmlString(string.Empty)) />
<script type="text/javascript">
$(function () {
document.DiscoFunctions.PropertyChangeHelper(
$('#DeviceProfile_EnforceOrganisationalUnit'),
null,
'@Url.Action(MVC.API.DeviceProfile.UpdateEnforceOrganisationalUnit(Model.DeviceProfile.Id))',
'EnforceOrganisationalUnit'
);
});
</script>
}
else
{
<input id="DeviceProfile_EnforceOrganisationalUnit" type="checkbox" @(Model.DeviceProfile.EnforceOrganisationalUnit ? new MvcHtmlString("checked=\"checked\" ") : new MvcHtmlString(string.Empty)) disabled="disabled" />
}
<label for="DeviceProfile_EnforceOrganisationalUnit">
Enforce Organisational Unit
</label>
@AjaxHelpers.AjaxLoader()
</div>
<div class="info-box">
<p class="fa-p">
<i class="fa fa-info-circle"></i>When an Active Directory account is provisioned it will be placed in this container. This typically occurs
at device enrolment. If the device has already joined the domain and the <code>Enforce&nbsp;Organisational&nbsp;Unit</code> option is enabled
the Active Directory account will be moved into this organisational unit during enrolment.
</p>
</div>
</td>
</tr>
<tr>
<th>
Provision Certificates:
@if (canConfig && (Model.CertificateProviders.Count > 0 || Model.CertificateAuthorityProviders.Count > 0))
{
<br />
@AjaxHelpers.AjaxLoader("DeviceProfile_CertificateProviders")
}
@if (canConfig && Model.CertificateProviders.Count > 0)
{
<script type="text/javascript">
$(function () {
const $container = $('#DeviceProfile_CertificateProviders');
$container.on('change', 'input', function () {
const $ajaxLoading = $('#DeviceProfile_CertificateProviders_loading').show();
const body = new FormData();
body.append('__RequestVerificationToken', document.body.dataset.antiforgery);
body.append('certificateProviders', $container.find('input:checked',).map(function () { return $(this).val() }).get().join(','));
fetch('@(Url.Action(MVC.API.DeviceProfile.UpdateCertificateProviders(Model.DeviceProfile.Id)))', {
method: 'POST',
body: body
}).then(r => {
if (r.ok) {
$ajaxLoading.hide().next('.ajaxOk').show().delay('fast').fadeOut('slow');
} else {
alert('Unable to change property "CertificateProviders":\n' + r.statusText);
$ajaxLoading.hide();
}
}).catch(e => {
alert('Unable to change property "CertificateProviders":\n' + e);
$ajaxLoading.hide();
});
});
});
</script>
}
@if (canConfig && Model.CertificateProviders.Count > 0)
{
<script type="text/javascript">
$(function () {
var $container = $('#DeviceProfile_CertificateAuthorityProviders');
$container.on('change', 'input', function () {
var $ajaxLoading = $('#DeviceProfile_CertificateProviders_loading').show();
const body = new FormData();
body.append('__RequestVerificationToken', document.body.dataset.antiforgery);
body.append('certificateAuthorityProviders', $container.find('input:checked',).map(function () { return $(this).val() }).get().join(','));
fetch('@(Url.Action(MVC.API.DeviceProfile.UpdateCertificateAuthorityProviders(Model.DeviceProfile.Id)))', {
method: 'POST',
body: body
}).then(r => {
if (r.ok) {
$ajaxLoading.hide().next('.ajaxOk').show().delay('fast').fadeOut('slow');
} else {
alert('Unable to change property "CertificateAuthorityProviders":\n' + r.statusText);
$ajaxLoading.hide();
}
}).catch(e => {
alert('Unable to change property "CertificateAuthorityProviders":\n' + e);
$ajaxLoading.hide();
});
});
});
</script>
}
</th>
<td>
<h4>Device/Machine Certificates</h4>
@if (canConfig && Model.CertificateProviders.Count > 0)
{
@CommonHelpers.CheckBoxList("DeviceProfile_CertificateProviders", "DeviceProfile_CertificateProviders", Model.CertificateProviders.ToSelectListItems(Model.DeviceProfile.GetCertificateProviders()))
}
else
{
var certificateProviders = Model.DeviceProfile.GetCertificateProviders().ToList();
if (certificateProviders.Count == 0)
{
<span class="smallMessage">&lt;None Allocated&gt;</span>
}
else
{
<ul>
@foreach (var certificateProvider in certificateProviders)
{
<li>@certificateProvider.Name</li>
}
</ul>
}
}
<h4 style="margin-top: 4px;">Authority Certificates</h4>
@if (canConfig && Model.CertificateAuthorityProviders.Count > 0)
{
@CommonHelpers.CheckBoxList("DeviceProfile_CertificateAuthorityProviders", "DeviceProfile_CertificateAuthorityProviders", Model.CertificateAuthorityProviders.ToSelectListItems(Model.DeviceProfile.GetCertificateAuthorityProviders()))
}
else
{
var certificateProviders = Model.DeviceProfile.GetCertificateAuthorityProviders().ToList();
if (certificateProviders.Count == 0)
{
<span class="smallMessage">&lt;None Allocated&gt;</span>
}
else
{
<ul>
@foreach (var certificateProvider in certificateProviders)
{
<li>@certificateProvider.Name</li>
}
</ul>
}
}
@if (canViewPlugins)
{
<div class="info-box">
<p class="fa-p">
<i class="fa fa-info-circle"></i>View the <a href="@(Url.Action(MVC.Config.Plugins.Install()))">Plugin Catalogue</a> to discover and install certificate provider plugins.
</p>
</div>
}
</td>
</tr>
<tr>
<th>
Provision Wireless Profiles:
@if (canConfig && Model.WirelessProfileProviders.Count > 0)
{
<br />
@AjaxHelpers.AjaxLoader("DeviceProfile_WirelessProfileProviders")
<script type="text/javascript">
$(function () {
var $container = $('#DeviceProfile_WirelessProfileProviders');
$container.on('change', 'input', function () {
var $ajaxLoading = $('#DeviceProfile_WirelessProfileProviders_loading').show();
const body = new FormData();
body.append('__RequestVerificationToken', document.body.dataset.antiforgery);
body.append('wirelessProfileProviders', $container.find('input:checked',).map(function () { return $(this).val() }).get().join(','));
fetch('@(Url.Action(MVC.API.DeviceProfile.UpdateWirelessProfileProviders(Model.DeviceProfile.Id)))', {
method: 'POST',
body: body
}).then(r => {
if (r.ok) {
$ajaxLoading.hide().next('.ajaxOk').show().delay('fast').fadeOut('slow');
} else {
alert('Unable to change property "WirelessProfileProviders":\n' + r.statusText);
$ajaxLoading.hide();
}
}).catch(e => {
alert('Unable to change property "WirelessProfileProviders":\n' + e);
$ajaxLoading.hide();
});
});
});
</script>
}
</th>
<td>
@if (canConfig && Model.WirelessProfileProviders.Count > 0)
{
@CommonHelpers.CheckBoxList("DeviceProfile_WirelessProfileProviders", "DeviceProfile_WirelessProfileProviders", Model.WirelessProfileProviders.ToSelectListItems(Model.DeviceProfile.GetWirelessProfileProviders()))
}
else
{
var wirelessProfileProviders = Model.DeviceProfile.GetWirelessProfileProviders().ToList();
if (wirelessProfileProviders.Count == 0)
{
<span class="smallMessage">&lt;None Allocated&gt;</span>
}
else
{
<ul>
@foreach (var wirelessProfileProvider in wirelessProfileProviders)
{
<li>@wirelessProfileProvider.Name</li>
}
</ul>
}
}
@if (canViewPlugins)
{
<div class="info-box">
<p class="fa-p">
<i class="fa fa-info-circle"></i>View the <a href="@(Url.Action(MVC.Config.Plugins.Install()))">Plugin Catalogue</a> to discover and install wireless profile provider plugins.
</p>
</div>
}
</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 = DeviceProfileDevicesManagedGroup.GetCategoryDescription(Model.DeviceProfile),
Description = DeviceProfileDevicesManagedGroup.GetDescription(Model.DeviceProfile),
ManagedGroup = Model.DevicesLinkedGroup,
UpdateUrl = Url.Action(MVC.API.DeviceProfile.UpdateDevicesLinkedGroup(Model.DeviceProfile.Id, redirect: true))
})
@Html.Partial(MVC.Config.Shared.Views.LinkedGroupInstance, new LinkedGroupModel()
{
CanConfigure = canConfig,
CategoryDescription = DeviceProfileAssignedUsersManagedGroup.GetCategoryDescription(Model.DeviceProfile),
Description = DeviceProfileAssignedUsersManagedGroup.GetDescription(Model.DeviceProfile),
ManagedGroup = Model.AssignedUsersLinkedGroup,
UpdateUrl = Url.Action(MVC.API.DeviceProfile.UpdateAssignedUsersLinkedGroup(Model.DeviceProfile.Id, redirect: true))
})
@if (canConfig)
{
@Html.Partial(MVC.Config.Shared.Views.LinkedGroupShared)
}
</div>
</td>
</tr>
</table>
</div>
@Html.Partial(MVC.Config.Shared.Views._DeviceGroupDocumentBulkGenerate, Model)
<div class="actionBar">
@if (Model.CanDecommission)
{
<button id="DeviceProfile_Decommission" class="button">Decommission All Devices</button>
<div id="DeviceProfile_Decommission_Dialog" class="dialog" title="Profile Device Decommission">
@using (Html.BeginForm(MVC.API.Device.DeviceProfileDecommission(Model.DeviceProfile.Id)))
{
@Html.AntiForgeryToken()
<div class="clearfix" style="margin-bottom: 10px;">
<i class="fa fa-question-circle fa-lg information"></i>&nbsp;Why are these devices to be decommissioned?
</div>
<div>
<ul class="none">
@foreach (DecommissionReasons decommissionReason in Enum.GetValues(typeof(DecommissionReasons)).Cast<DecommissionReasons>().OrderBy(r => r.ToString()))
{
<li>
<input type="radio" id="DeviceProfile_Decommission_Dialog_Reason_@((int)decommissionReason)"
name="decommissionReason" value="@((int)decommissionReason)" @((decommissionReason == DecommissionReasons.EndOfLife) ? "checked=\"checked\"" : string.Empty) />
<label for="DeviceProfile_Decommission_Dialog_Reason_@((int)decommissionReason)">@(decommissionReason.ReasonMessage())</label>
</li>
}
</ul>
<br />
<label>
<input type="checkbox" value="true" name="unassignUsers" />
Unassign devices users
</label>
</div>
}
</div>
<script type="text/javascript">
$(function () {
let buttonDialog = null;
$('#DeviceProfile_Decommission').click(function () {
if (!buttonDialog) {
buttonDialog = $('#DeviceProfile_Decommission_Dialog')
.dialog({
resizable: false,
modal: true,
autoOpen: false,
buttons: {
"Decommission": function () {
const $this = $(this);
$this.find('form').trigger('submit');
$this.dialog("disable");
$this.dialog("option", "buttons", null);
},
Cancel: function () {
$(this).dialog("close");
}
}
});
}
buttonDialog.dialog('open');
return false;
});
});
</script>
}
@if (canDelete)
{
<button id="buttonDelete" type="button" class="button">Delete</button>
<div id="dialogConfirmDelete" class="dialog" title="Delete this Device Profile?">
@using (Html.BeginForm(MVC.API.DeviceProfile.Delete(Model.DeviceProfile.Id, true)))
{
@Html.AntiForgeryToken()
}
<p>
<i class="fa fa-exclamation-triangle fa-lg warning"></i>
This item will be permanently deleted and cannot be recovered. Are you sure?
</p>
</div>
<script type="text/javascript">
$(function () {
let dialog = null;
$('#buttonDelete').on('click', function () {
if (!dialog) {
dialog = $("#dialogConfirmDelete").dialog({
resizable: false,
width: 300,
modal: true,
autoOpen: false,
buttons: {
"Delete": function () {
$(this)
.dialog("option", "buttons", null)
.find('form').trigger('submit');
},
Cancel: function () {
$(this).dialog("close");
}
}
});
}
dialog.dialog('open');
});
});
</script>
}
@if (Authorization.Has(Claims.Device.Actions.Export))
{
@Html.ActionLinkButton("Export Devices", MVC.Device.Export(null, Disco.Models.Services.Devices.DeviceExportTypes.Profile, Model.DeviceProfile.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.DeviceProfile.Id.ToString(), "DeviceProfile"))
}
</div>