983 lines
50 KiB
Plaintext
983 lines
50 KiB
Plaintext
@model Disco.Web.Areas.Config.Models.DeviceFlag.ShowModel
|
|
@using Disco.Services.Interop.ActiveDirectory;
|
|
@using Disco.Services.Devices.DeviceFlags;
|
|
@using Disco.Web.Areas.Config.Models.Shared;
|
|
@{
|
|
Authorization.Require(Claims.Config.DeviceFlag.Show);
|
|
|
|
ViewBag.Title = Html.ToBreadcrumb("Configuration", MVC.Config.Config.Index(), "Device Flags", MVC.Config.DeviceFlag.Index(null), Model.DeviceFlag.ToString());
|
|
|
|
var canConfig = Authorization.Has(Claims.Config.DeviceFlag.Configure);
|
|
var canDelete = Authorization.Has(Claims.Config.DeviceFlag.Delete);
|
|
var canBulkAssignment = Authorization.HasAll(Claims.Device.Actions.AddFlags, Claims.Device.Actions.RemoveFlags, Claims.Device.ShowFlagAssignments);
|
|
var canShowDevices = Model.CurrentAssignmentCount > 0 && Authorization.HasAll(Claims.Device.Search, Claims.Device.ShowFlagAssignments);
|
|
var canExportCurrent = Model.CurrentAssignmentCount > 0 && Authorization.Has(Claims.Config.DeviceFlag.Export);
|
|
var canExportAll = Model.TotalAssignmentCount > 0 && Authorization.Has(Claims.Config.DeviceFlag.Export);
|
|
|
|
var hideAdvanced =
|
|
Model.Permission.IsDefault() &&
|
|
Model.DeviceFlag.DevicesLinkedGroup == null &&
|
|
Model.DeviceFlag.DeviceUsersLinkedGroup == null &&
|
|
Model.DeviceFlag.OnAssignmentExpression == null &&
|
|
Model.DeviceFlag.OnUnassignmentExpression == null;
|
|
|
|
Html.BundleDeferred("~/ClientScripts/Modules/Disco-PropertyChangeHelpers");
|
|
}
|
|
<div id="Config_DeviceFlags_Show" class="form@(hideAdvanced ? " Config_HideAdvanced" : null)" style="width: 550px">
|
|
<table>
|
|
<tr>
|
|
<th style="width: 150px">
|
|
Id:
|
|
</th>
|
|
<td>
|
|
@Html.DisplayFor(model => model.DeviceFlag.Id)
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<th>
|
|
Name:
|
|
</th>
|
|
<td>
|
|
@if (canConfig)
|
|
{
|
|
@Html.EditorFor(model => model.DeviceFlag.Name)
|
|
@AjaxHelpers.AjaxSave()
|
|
@AjaxHelpers.AjaxLoader()
|
|
<script type="text/javascript">
|
|
$(function () {
|
|
document.DiscoFunctions.PropertyChangeHelper(
|
|
$('#DeviceFlag_Name'),
|
|
'Invalid Name',
|
|
'@(Url.Action(MVC.API.DeviceFlag.UpdateName(Model.DeviceFlag.Id)))',
|
|
'FlagName'
|
|
);
|
|
});
|
|
</script>
|
|
}
|
|
else
|
|
{
|
|
@Model.DeviceFlag.Name
|
|
}
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<th>
|
|
Description:
|
|
</th>
|
|
<td>
|
|
@if (canConfig)
|
|
{@Html.EditorFor(model => model.DeviceFlag.Description)
|
|
@AjaxHelpers.AjaxSave()
|
|
@AjaxHelpers.AjaxLoader()
|
|
<script type="text/javascript">
|
|
$(function () {
|
|
document.DiscoFunctions.PropertyChangeHelper(
|
|
$('#DeviceFlag_Description'),
|
|
'Invalid Description',
|
|
'@(Url.Action(MVC.API.DeviceFlag.UpdateDescription(Model.DeviceFlag.Id)))',
|
|
'Description'
|
|
);
|
|
});
|
|
</script>
|
|
}
|
|
else
|
|
{
|
|
<pre>
|
|
@if (string.IsNullOrEmpty(Model.DeviceFlag.Description))
|
|
{
|
|
<text><None></text>
|
|
}
|
|
else
|
|
{
|
|
@Model.DeviceFlag.Description.ToHtmlComment()
|
|
}
|
|
</pre>
|
|
}
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<th>
|
|
Statistics:
|
|
</th>
|
|
<td>
|
|
<div><strong>@Model.CurrentAssignmentCount device@(Model.CurrentAssignmentCount != 1 ? "s" : null) currently assigned</strong></div>
|
|
<div>@Model.TotalAssignmentCount total device historical assignment@(Model.TotalAssignmentCount != 1 ? "s" : null)</div>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<th>
|
|
Icon:
|
|
</th>
|
|
<td>
|
|
<i id="Config_DeviceFlags_Icon" data-icon="@(Model.DeviceFlag.Icon)" data-colour="@(Model.DeviceFlag.IconColour)" class="fa fa-@(Model.DeviceFlag.Icon) fa-4x d-@(Model.DeviceFlag.IconColour)"></i>
|
|
@if (canConfig)
|
|
{
|
|
<div>
|
|
<a id="Config_DeviceFlags_Icon_Update" href="#" class="button small">Update</a>
|
|
<div id="Config_DeviceFlags_Icon_Update_Dialog" class="dialog" title="Device Flag Icon">
|
|
@using (Html.BeginForm(MVC.API.DeviceFlag.UpdateIconAndColour(id: Model.DeviceFlag.Id, redirect: true)))
|
|
{
|
|
@Html.AntiForgeryToken()
|
|
<input type="hidden" name="icon" />
|
|
<input type="hidden" name="iconColour" />
|
|
}
|
|
<div>
|
|
<div class="colours">
|
|
@foreach (var colour in Model.ThemeColours)
|
|
{
|
|
<i data-colour="@(colour.Key)" class="fa fa-square d-@(colour.Key)" title="@colour.Value"></i>
|
|
}
|
|
</div>
|
|
<div class="icons">
|
|
@foreach (var icon in Model.Icons)
|
|
{
|
|
<i data-icon="@(icon.Key)" class="fa fa-@(icon.Key)" title="@icon.Value"></i>
|
|
}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<script>
|
|
(function () {
|
|
var dialog, icon, colours, icons;
|
|
|
|
function showDialog() {
|
|
if (!dialog) {
|
|
dialog = $('#Config_DeviceFlags_Icon_Update_Dialog').dialog({
|
|
resizable: false,
|
|
modal: true,
|
|
autoOpen: false,
|
|
width: 1000,
|
|
buttons: {
|
|
"Save": save,
|
|
Cancel: cancel
|
|
}
|
|
});
|
|
|
|
colours = dialog.find('.colours');
|
|
icons = dialog.find('.icons');
|
|
|
|
colours.on('click', 'i', selectColour);
|
|
icons.on('click', 'i', selectIcon);
|
|
}
|
|
|
|
colours.find('i[data-colour="' + icon.attr('data-colour') + '"]').each(selectColour);
|
|
icons.find('i[data-icon="' + icon.attr('data-icon') + '"]').each(selectIcon);
|
|
|
|
dialog.dialog('open');
|
|
|
|
return false;
|
|
}
|
|
|
|
function selectColour() {
|
|
var $this = $(this),
|
|
colourCode = $this.attr('data-colour'),
|
|
previousColourCode = icons.attr('data-colour');
|
|
|
|
|
|
colours.find('i').removeClass('selected fa-check-square').addClass('fa-square');
|
|
$this.removeClass('fa-square').addClass('fa-check-square selected');
|
|
|
|
if (previousColourCode)
|
|
icons.removeClass('d-' + previousColourCode);
|
|
icons.attr('data-colour', colourCode)
|
|
icons.addClass('d-' + colourCode);
|
|
}
|
|
function selectIcon() {
|
|
var $this = $(this),
|
|
iconCode = $this.attr('data-icon');
|
|
|
|
icons.find('i').removeClass('selected');
|
|
$this.addClass('selected');
|
|
}
|
|
|
|
function save() {
|
|
dialog.dialog("option", "buttons", null);
|
|
const $form = dialog.find('form');
|
|
$form.find('input[name="icon"]').val(icons.find('i.selected').attr('data-icon'));
|
|
$form.find('input[name="iconColour"]').val(colours.find('i.selected').attr('data-colour'));
|
|
$form.trigger('submit');
|
|
}
|
|
|
|
function cancel() {
|
|
$(this).dialog("close");
|
|
}
|
|
|
|
$(function () {
|
|
icon = $('#Config_DeviceFlags_Icon');
|
|
$('#Config_DeviceFlags_Icon_Update').click(showDialog);
|
|
});
|
|
}());
|
|
</script>
|
|
</div>
|
|
}
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<th>
|
|
Scheduled Unassignment:
|
|
</th>
|
|
<td>
|
|
@if (canConfig)
|
|
{
|
|
<input id="DeviceFlag_DefaultRemoveDays" type="number" min="1" max="@int.MaxValue" value="@Model.DeviceFlag.DefaultRemoveDays" />
|
|
@AjaxHelpers.AjaxSave()
|
|
@AjaxHelpers.AjaxLoader()
|
|
@:days
|
|
<script type="text/javascript">
|
|
$(function () {
|
|
document.DiscoFunctions.PropertyChangeHelper(
|
|
$('#DeviceFlag_DefaultRemoveDays'),
|
|
'Invalid Value',
|
|
'@(Url.Action(MVC.API.DeviceFlag.UpdateDefaultRemoveDays(Model.DeviceFlag.Id)))',
|
|
'defaultRemoveDays'
|
|
);
|
|
});
|
|
</script>
|
|
}
|
|
else
|
|
{
|
|
if (Model.DeviceFlag.DefaultRemoveDays.HasValue)
|
|
{
|
|
<span><strong>@Model.DeviceFlag.DefaultRemoveDays</strong> days</span>
|
|
}
|
|
else
|
|
{
|
|
<span><em>Not Enabled</em></span>
|
|
}
|
|
}
|
|
<div class="info-box">
|
|
<p class="fa-p">
|
|
<i class="fa fa-fw fa-info-circle"></i>
|
|
Optionally specify the number of days a flag is removed from a device.
|
|
If one (1), the flag will be removed that night (midnight).<br />
|
|
If the user has permission, the date can be adjusted when assigning the flag.
|
|
Changing this value does not affect existing assignments.
|
|
</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>
|
|
Assignment Permission<br />
|
|
Override:
|
|
</th>
|
|
<td>
|
|
@if (!Model.Permission.IsDefault())
|
|
{
|
|
var permission = Model.Permission;
|
|
<div>
|
|
@if (permission.Inherit)
|
|
{
|
|
<span><i class="fa fa-check-square-o"></i> Inheriting from Authorization Roles</span>
|
|
}
|
|
else
|
|
{
|
|
<span><i class="fa fa-square-o"></i> Authorization Roles are Ignored</span>
|
|
}
|
|
</div>
|
|
if (!permission.HasSubjects())
|
|
{
|
|
<span class="smallMessage">There are no users/groups associated with this permission override</span>
|
|
}
|
|
else
|
|
{
|
|
if (permission.IsSimple())
|
|
{
|
|
<table class="tableData">
|
|
<thead>
|
|
<tr>
|
|
<th>Users/Groups/Roles</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@foreach (var subjectId in permission.CanShowSubjectIds)
|
|
{
|
|
<tr>
|
|
<td>
|
|
@{
|
|
int roleId;
|
|
if (subjectId.StartsWith("[") && int.TryParse(subjectId.Trim('[', ']'), out roleId))
|
|
{
|
|
<span>@Disco.Services.Users.UserService.GetAuthorizationRoleName(roleId) @subjectId</span>
|
|
}
|
|
else
|
|
{
|
|
<span>@subjectId</span>
|
|
}
|
|
}
|
|
</td>
|
|
</tr>
|
|
}
|
|
</tbody>
|
|
</table>
|
|
<div class="info-box">
|
|
<p class="fa-p">
|
|
<i class="fa fa-fw fa-info-circle"></i> All users/groups/roles can view, assign, edit assignments, and remove assignments for this flag.
|
|
</p>
|
|
</div>
|
|
}
|
|
else
|
|
{
|
|
var subjects = permission.AllSubjects();
|
|
<table class="tableData">
|
|
<thead>
|
|
<tr>
|
|
<th>Users/Groups/Roles</th>
|
|
<th>View</th>
|
|
<th>Assign</th>
|
|
<th>Edit</th>
|
|
<th>Remove</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@foreach (var subjectId in subjects.OrderBy(s => s))
|
|
{
|
|
<tr>
|
|
<td>
|
|
<i class="fa"></i> @{
|
|
int roleId;
|
|
if (subjectId.StartsWith("[") && int.TryParse(subjectId.Trim('[', ']'), out roleId))
|
|
{
|
|
<span>@Disco.Services.Users.UserService.GetAuthorizationRoleName(roleId) @subjectId</span>
|
|
}
|
|
else
|
|
{
|
|
<span>@subjectId</span>
|
|
}
|
|
}
|
|
</td>
|
|
<td>
|
|
@if (permission.CanShowSubjectIds.Contains(subjectId))
|
|
{
|
|
<i class="fa fa-fw fa-check"></i>
|
|
}
|
|
</td>
|
|
<td>
|
|
@if (permission.CanAssignSubjectIds.Contains(subjectId))
|
|
{
|
|
<i class="fa fa-fw fa-check"></i>
|
|
}
|
|
</td>
|
|
<td>
|
|
@if (permission.CanEditSubjectIds.Contains(subjectId))
|
|
{
|
|
<i class="fa fa-fw fa-check"></i>
|
|
}
|
|
</td>
|
|
<td>
|
|
@if (permission.CanRemoveSubjectIds.Contains(subjectId))
|
|
{
|
|
<i class="fa fa-fw fa-check"></i>
|
|
}
|
|
</td>
|
|
</tr>
|
|
}
|
|
</tbody>
|
|
</table>
|
|
}
|
|
|
|
}
|
|
}
|
|
@if (canConfig)
|
|
{
|
|
var permission = Model.Permission;
|
|
<button id="Config_Flag_Permission_Edit" class="button small">@(permission.IsDefault() ? "Override" : "Edit") Permission</button>
|
|
|
|
<div id="Config_Flag_Permissions" class="dialog" title="Flag Assignment Permission Override">
|
|
@using (Html.BeginForm(MVC.API.DeviceFlag.Permission(Model.DeviceFlag.Id)))
|
|
{
|
|
@Html.AntiForgeryToken()
|
|
<input type="hidden" name="IsOverride" value="true" />
|
|
<div id="Config_Flag_Permissions_Inherit_Container">
|
|
<label>
|
|
<input id="Config_Flag_Permissions_Inherit" type="checkbox" name="Inherit" value="true" @(permission.Inherit ? "checked" : null) /> Inherit Authorization from Authorization Roles
|
|
</label>
|
|
</div>
|
|
<div class="tableDataContainer">
|
|
<table class="tableData">
|
|
<thead>
|
|
<tr>
|
|
<th>User/Group/Role</th>
|
|
<th>View</th>
|
|
<th>Assign</th>
|
|
<th>Edit</th>
|
|
<th>Remove</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@{
|
|
var subjects = permission.AllSubjects();
|
|
|
|
foreach (var subjectId in subjects.OrderBy(s => s))
|
|
{
|
|
<tr data-subjectid="@subjectId">
|
|
<td><i class="fa type"></i> <span>@subjectId</span><i class="fa fa-times-circle remove"></i></td>
|
|
<td>
|
|
<input type="checkbox" name="CanShow" value="@subjectId" @(permission.CanShowSubjectIds.Contains(subjectId) ? " checked" : null) />
|
|
</td>
|
|
<td>
|
|
<input type="checkbox" name="CanAssign" value="@subjectId" @(permission.CanAssignSubjectIds.Contains(subjectId) ? " checked" : null) />
|
|
</td>
|
|
<td>
|
|
<input type="checkbox" name="CanEdit" value="@subjectId" @(permission.CanEditSubjectIds.Contains(subjectId) ? " checked" : null) />
|
|
</td>
|
|
<td>
|
|
<input type="checkbox" name="CanRemove" value="@subjectId" @(permission.CanRemoveSubjectIds.Contains(subjectId) ? " checked" : null) />
|
|
</td>
|
|
</tr>
|
|
}
|
|
}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<div>
|
|
<input type="text" id="Config_Flag_Permissions_Subject_Input" placeholder="Search Users/Groups/Roles" data-autocompleteurl="@(Url.Action(MVC.API.System.SearchSubjects(null, includeAuthorizationRoles: true)))" />
|
|
<button type="button" id="Config_Flag_Permissions_Subject_Add" class="button small" data-subjecturl="@Url.Action(MVC.API.System.Subject(null, includeAuthorizationRoles: true))">Add</button>
|
|
</div>
|
|
}
|
|
</div>
|
|
<script>
|
|
$(function () {
|
|
let $dialog = null;
|
|
let originalSubjects = null;
|
|
let originalInherit = null;
|
|
$('#Config_Flag_Permission_Edit').on('click', async function () {
|
|
if (!$dialog) {
|
|
$dialog = $('#Config_Flag_Permissions');
|
|
const $tbody = $dialog.find('tbody');
|
|
const $inherit = $dialog.find('#Config_Flag_Permissions_Inherit');
|
|
const $input = $dialog.find('#Config_Flag_Permissions_Subject_Input');
|
|
const $add = $dialog.find('#Config_Flag_Permissions_Subject_Add');
|
|
|
|
$dialog.dialog({
|
|
resizable: false,
|
|
modal: true,
|
|
autoOpen: false,
|
|
width: 550,
|
|
height: 420,
|
|
buttons: {
|
|
Cancel: function () {
|
|
$(this).dialog('close');
|
|
$tbody.html(originalSubjects);
|
|
$inherit.prop('checked', originalInherit);
|
|
},
|
|
'Remove Override': function () {
|
|
const $this = $(this);
|
|
$(this).dialog('option', 'buttons', null);
|
|
$this.find('input[name="IsOverride"]').val('false');
|
|
$this.find('form').trigger('submit');
|
|
},
|
|
'Save Changes': function () {
|
|
$(this).dialog('option', 'buttons', null);
|
|
$(this).find('form').trigger('submit');
|
|
}
|
|
}
|
|
});
|
|
|
|
$tbody.on('click', 'i.remove', function () {
|
|
$(this).closest('tr').remove();
|
|
});
|
|
|
|
$input
|
|
.autocomplete({
|
|
source: $input.attr('data-autocompleteurl'),
|
|
minLength: 2,
|
|
focus: function (e, ui) {
|
|
$input.val(ui.item.Id);
|
|
return false;
|
|
},
|
|
select: function (e, ui) {
|
|
$input.val(ui.item.Id).blur();
|
|
$add.trigger('click');
|
|
$input.val('');
|
|
return false;
|
|
}
|
|
}).data('ui-autocomplete')._renderItem = function (ul, item) {
|
|
return $("<li></li>")
|
|
.data('item.autocomplete', item)
|
|
.append('<a><strong>' + item.Name + '</strong><br>' + item.Id + ' (' + item.Type + ')</a>')
|
|
.appendTo(ul);
|
|
};
|
|
|
|
$add.on('click', async function () {
|
|
const value = $input.val();
|
|
if (!value) {
|
|
$input.focus();
|
|
return;
|
|
}
|
|
const existing = $tbody.find('tr').filter(function () {
|
|
return $(this).attr('data-subjectid') === value;
|
|
});
|
|
if (existing.length !== 0) {
|
|
$input.val('');
|
|
$input.focus();
|
|
return;
|
|
}
|
|
|
|
const body = new FormData();
|
|
body.append('id', value);
|
|
const response = await fetch($add.attr('data-subjecturl'), {
|
|
body: body,
|
|
method: 'POST'
|
|
});
|
|
|
|
if (!response.ok) {
|
|
alert('Unable to lookup User/Group/Role: ' + response.statusText);
|
|
$input.focus();
|
|
return;
|
|
}
|
|
|
|
const subject = await response.json();
|
|
|
|
if (!subject) {
|
|
alert('Invalid User/Group/Role');
|
|
$input.focus();
|
|
return;
|
|
}
|
|
|
|
const $record = $('<tr><td><i class="fa type"></i> <span></span><i class="fa fa-times-circle remove"></i></td><td><input type="checkbox" name="CanShow" checked /></td><td><input type="checkbox" name="CanAssign" checked /></td><td><input type="checkbox" name="CanEdit" checked /></td><td><input type="checkbox" name="CanRemove" checked /></td></tr>');
|
|
$record.attr('data-subjectid', subject.Id);
|
|
$record.find('span').text(subject.Name + ' ' + subject.Id);
|
|
$record.find('i.type').addClass(subject.Type === 'role' ? 'fa-lock' : subject.IsGroup ? 'fa-users' : 'fa-user');
|
|
$record.find('input').val(subject.Id);
|
|
$tbody.append($record);
|
|
$input.val('');
|
|
$input.focus();
|
|
});
|
|
|
|
const $records = $tbody.find('tr');
|
|
for (var i = 0; i < $records.length; i++) {
|
|
const $record = $($records[i]);
|
|
const body = new FormData();
|
|
body.append('id', $record.attr('data-subjectid'));
|
|
const response = await fetch($add.attr('data-subjecturl'), {
|
|
body: body,
|
|
method: 'POST'
|
|
});
|
|
if (response.ok) {
|
|
const subject = await response.json();
|
|
if (subject) {
|
|
$record.find('span').text(subject.Name + ' ' + subject.Id);
|
|
$record.find('i.type').addClass(subject.Type === 'role' ? 'fa-lock' : subject.IsGroup ? 'fa-users' : 'fa-user');
|
|
continue;
|
|
}
|
|
}
|
|
$record.remove();
|
|
}
|
|
originalInherit = $inherit.prop('checked');
|
|
originalSubjects = $tbody.html();
|
|
$dialog.dialog('open');
|
|
} else {
|
|
$dialog.dialog('open');
|
|
}
|
|
});
|
|
});
|
|
</script>
|
|
}
|
|
<div class="info-box">
|
|
<p class="fa-p">
|
|
<i class="fa fa-fw fa-info-circle"></i> Flag actions are normally authorized globally by
|
|
@if (Authorization.Has(Claims.DiscoAdminAccount))
|
|
{
|
|
<span><a href="@Url.Action(MVC.Config.AuthorizationRole.Index(null))">Authorization Roles</a>.</span>
|
|
}
|
|
else
|
|
{
|
|
<span>Authorization Roles.</span>
|
|
}
|
|
Overriding individual flag permissions allows for targeted authorization.
|
|
</p>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
<tr class="Config_HideAdvanced_Item">
|
|
<th>
|
|
On Assignment<br />Expression:
|
|
</th>
|
|
<td>
|
|
@if (canConfig)
|
|
{
|
|
@Html.EditorFor(model => model.DeviceFlag.OnAssignmentExpression)
|
|
@AjaxHelpers.AjaxRemove()
|
|
@AjaxHelpers.AjaxSave()
|
|
@AjaxHelpers.AjaxLoader()
|
|
<script type="text/javascript">
|
|
$(function () {
|
|
var field = $('#DeviceFlag_OnAssignmentExpression');
|
|
var fieldRemove = field.next('.ajaxRemove');
|
|
var fieldOriginalWidth, fieldOriginalHeight;
|
|
|
|
document.DiscoFunctions.PropertyChangeHelper(
|
|
field,
|
|
'None',
|
|
'@Url.Action(MVC.API.DeviceFlag.UpdateOnAssignmentExpression(Model.DeviceFlag.Id))',
|
|
'OnAssignmentExpression'
|
|
);
|
|
|
|
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();
|
|
});
|
|
|
|
if (!!field.val()) {
|
|
fieldRemove.show();
|
|
} else {
|
|
fieldRemove.hide();
|
|
}
|
|
});
|
|
</script>
|
|
}
|
|
else
|
|
{
|
|
if (string.IsNullOrWhiteSpace(Model.DeviceFlag.OnAssignmentExpression))
|
|
{
|
|
<span class="smallMessage"><None Specified></span>
|
|
}
|
|
else
|
|
{
|
|
<div class="code">
|
|
@Model.DeviceFlag.OnAssignmentExpression
|
|
</div>
|
|
}
|
|
}
|
|
<div class="info-box">
|
|
<p class="fa-p">
|
|
<i class="fa fa-fw fa-info-circle"></i>This expression will be evaluated whenever the flag is assigned to a device. The output of the expression will be shown with the flag assignment.
|
|
</p>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
<tr class="Config_HideAdvanced_Item">
|
|
<th>
|
|
On Unassignment<br />Expression:
|
|
</th>
|
|
<td>
|
|
@if (canConfig)
|
|
{
|
|
@Html.EditorFor(model => model.DeviceFlag.OnUnassignmentExpression)
|
|
@AjaxHelpers.AjaxRemove()
|
|
@AjaxHelpers.AjaxSave()
|
|
@AjaxHelpers.AjaxLoader()
|
|
<script type="text/javascript">
|
|
$(function () {
|
|
var field = $('#DeviceFlag_OnUnassignmentExpression');
|
|
var fieldRemove = field.next('.ajaxRemove');
|
|
var fieldOriginalWidth, fieldOriginalHeight;
|
|
|
|
document.DiscoFunctions.PropertyChangeHelper(
|
|
field,
|
|
'None',
|
|
'@Url.Action(MVC.API.DeviceFlag.UpdateOnUnassignmentExpression(Model.DeviceFlag.Id))',
|
|
'OnUnassignmentExpression'
|
|
);
|
|
|
|
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();
|
|
});
|
|
|
|
if (!!field.val()) {
|
|
fieldRemove.show();
|
|
} else {
|
|
fieldRemove.hide();
|
|
}
|
|
});
|
|
</script>
|
|
}
|
|
else
|
|
{
|
|
if (string.IsNullOrWhiteSpace(Model.DeviceFlag.OnUnassignmentExpression))
|
|
{
|
|
<span class="smallMessage"><None Specified></span>
|
|
}
|
|
else
|
|
{
|
|
<div class="code">
|
|
@Model.DeviceFlag.OnUnassignmentExpression
|
|
</div>
|
|
}
|
|
}
|
|
<div class="info-box">
|
|
<p class="fa-p">
|
|
<i class="fa fa-fw fa-info-circle"></i>This expression will be evaluated whenever the flag is removed from a device. The output of the expression will be shown with the flag assignment.
|
|
</p>
|
|
</div>
|
|
</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 = DeviceFlagDevicesManagedGroup.GetCategoryDescription(Model.DeviceFlag),
|
|
Description = DeviceFlagDevicesManagedGroup.GetDescription(Model.DeviceFlag),
|
|
ManagedGroup = Model.DevicesLinkedGroup,
|
|
IncludeFilterBeginDate = true,
|
|
UpdateUrl = Url.Action(MVC.API.DeviceFlag.UpdateDevicesLinkedGroup(Model.DeviceFlag.Id, redirect: true))
|
|
})
|
|
@Html.Partial(MVC.Config.Shared.Views.LinkedGroupInstance, new LinkedGroupModel()
|
|
{
|
|
CanConfigure = canConfig,
|
|
CategoryDescription = DeviceFlagDeviceAssignedUsersManagedGroup.GetCategoryDescription(Model.DeviceFlag),
|
|
Description = DeviceFlagDeviceAssignedUsersManagedGroup.GetDescription(Model.DeviceFlag),
|
|
ManagedGroup = Model.AssignedUserLinkedGroup,
|
|
IncludeFilterBeginDate = true,
|
|
UpdateUrl = Url.Action(MVC.API.DeviceFlag.UpdateAssignedUserLinkedGroup(Model.DeviceFlag.Id, redirect: true))
|
|
})
|
|
@if (canConfig)
|
|
{
|
|
@Html.Partial(MVC.Config.Shared.Views.LinkedGroupShared)
|
|
}
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
@if (canBulkAssignment || canDelete || canShowDevices || canExportCurrent || canExportAll)
|
|
{
|
|
<div class="actionBar">
|
|
@if (canExportCurrent)
|
|
{
|
|
@Html.ActionLinkButton("Export Current Assignments", MVC.Config.DeviceFlag.Export(null, Model.DeviceFlag.Id, true), "Config_DeviceFlags_Actions_ExportCurrent_Button")
|
|
}
|
|
@if (canExportAll)
|
|
{
|
|
@Html.ActionLinkButton("Export All Assignments", MVC.Config.DeviceFlag.Export(null, Model.DeviceFlag.Id, false), "Config_DeviceFlags_Actions_ExportAll_Button")
|
|
}
|
|
@if (canBulkAssignment)
|
|
{
|
|
<a href="#" id="Config_DeviceFlags_BulkAssign_Button" class="button">Bulk Assign Devices</a>
|
|
<div id="Config_DeviceFlags_BulkAssign_ModeDialog" class="dialog" title="Bulk Assign Device Mode">
|
|
<p>
|
|
Select the mode used to assign devices:
|
|
</p>
|
|
<div>
|
|
<div class="add">
|
|
<h5><i class="fa fa-plus fa-fw"></i>Add</h5>
|
|
<p>
|
|
Specified devices will have this flag <strong>added</strong>. Devices who already have this flag will be skipped.
|
|
</p>
|
|
</div>
|
|
<div class="override">
|
|
<h5><i class="fa fa-repeat fa-fw"></i>Override</h5>
|
|
<p>
|
|
Specified devices will have this flag <strong>added</strong>. Specified devices which already have this flag will be skipped.
|
|
Devices who already have this flag but are not specified will have the flag <strong>removed</strong>.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div id="Config_DeviceFlags_BulkAssign_AssignDialog" class="dialog" title="Bulk Assign Devices" data-assignedurl="@Url.Action(MVC.API.DeviceFlag.AssignedDevices(Model.DeviceFlag.Id))">
|
|
<div class="brief">
|
|
<div>
|
|
Enter multiple <strong>Device Serial Numbers</strong> separated by <code><new line></code>, commas (<code>,</code>) or semicolons (<code>;</code>).
|
|
</div>
|
|
</div>
|
|
<div class="loading">
|
|
<h4><i class="fa fa-lg fa-cog fa-spin" title="Please Wait"></i>Loading current assignments...</h4>
|
|
</div>
|
|
<form action="#" method="post" data-overrideaction="@(Url.Action(MVC.API.DeviceFlag.BulkAssignDevices(Model.DeviceFlag.Id, true)))" data-addaction="@(Url.Action(MVC.API.DeviceFlag.BulkAssignDevices(Model.DeviceFlag.Id, false)))">
|
|
@Html.AntiForgeryToken()
|
|
<textarea id="Config_DeviceFlags_BulkAssign_AssignDialog_DeviceSerialNumbers" name="DeviceSerialNumbers"></textarea>
|
|
<h4>Comments:</h4>
|
|
<textarea id="Config_DeviceFlags_BulkAssign_AssignDialog_Comments" name="Comments"></textarea>
|
|
</form>
|
|
</div>
|
|
<script>
|
|
$(function () {
|
|
var modeDialog, assignDialog, assignDeviceSerialNumbers;
|
|
|
|
function showModeDialog() {
|
|
if (!modeDialog) {
|
|
modeDialog = $('#Config_DeviceFlags_BulkAssign_ModeDialog').dialog({
|
|
resizable: false,
|
|
modal: true,
|
|
autoOpen: false,
|
|
width: 400,
|
|
buttons: {
|
|
Cancel: function () {
|
|
$(this).dialog('close');
|
|
}
|
|
}
|
|
});
|
|
|
|
modeDialog.find('.add').click(function () {
|
|
modeDialog.dialog('close');
|
|
showAssignDialog('Add');
|
|
});
|
|
modeDialog.find('.override').click(function () {
|
|
modeDialog.dialog('close');
|
|
showAssignDialog('Override');
|
|
});
|
|
}
|
|
modeDialog.dialog('open');
|
|
}
|
|
function showAssignDialog(mode) {
|
|
if (!assignDialog) {
|
|
assignDialog = $('#Config_DeviceFlags_BulkAssign_AssignDialog').dialog({
|
|
resizable: false,
|
|
modal: true,
|
|
autoOpen: false,
|
|
width: 460
|
|
});
|
|
|
|
assignDeviceSerialNumbers = $('#Config_DeviceFlags_BulkAssign_AssignDialog_DeviceSerialNumbers');
|
|
}
|
|
|
|
assignDialog.removeClass('loading');
|
|
|
|
var buttons = {};
|
|
buttons[mode + " Device Flags"] = function () {
|
|
$(this).find('form').submit();
|
|
$(this).dialog("disable");
|
|
}
|
|
buttons['Cancel'] = function () {
|
|
$(this).dialog('close');
|
|
}
|
|
assignDialog.dialog('option', 'buttons', buttons);
|
|
assignDialog.dialog('option', 'title', 'Bulk Assign Devices: ' + mode);
|
|
|
|
const $form = assignDeviceSerialNumbers.closest('form');
|
|
if (mode == "Override") {
|
|
$form.attr('action', $form.attr('data-overrideaction'));
|
|
|
|
assignDialog.addClass('loading');
|
|
const body = new FormData();
|
|
body.append('__RequestVerificationToken', document.body.dataset.antiforgery);
|
|
fetch(assignDialog.attr('data-assignedurl'), {
|
|
method: 'POST',
|
|
body: body
|
|
}).then(r => {
|
|
assignDialog.removeClass('loading');
|
|
if (!r.ok) {
|
|
alert('Unable to load current assignments:\n' + r.statusText);
|
|
assignDialog.dialog('close');
|
|
} else {
|
|
r.json().then(j => {
|
|
if (!j) {
|
|
assignDeviceSerialNumbers.val('');
|
|
} else {
|
|
assignDeviceSerialNumbers.val(j.join('\n'));
|
|
}
|
|
})
|
|
}
|
|
});
|
|
}
|
|
else // Assume Add
|
|
{
|
|
$form.attr('action', $form.attr('data-addaction'));
|
|
}
|
|
|
|
assignDialog.dialog('open');
|
|
}
|
|
|
|
$('#Config_DeviceFlags_BulkAssign_Button').click(function () {
|
|
showModeDialog();
|
|
return false;
|
|
});
|
|
});
|
|
</script>
|
|
}
|
|
@if (canDelete)
|
|
{
|
|
<button id="Config_DeviceFlags_Actions_Delete_Button" type="button" class="button">Delete</button>
|
|
<div id="Config_DeviceFlags_Actions_Delete_Dialog" class="dialog" title="Delete this Device Flag?">
|
|
@using (Html.BeginForm(MVC.API.DeviceFlag.Delete(Model.DeviceFlag.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.<br />
|
|
<br />
|
|
@if (Model.CurrentAssignmentCount > 0)
|
|
{
|
|
<strong>@Model.CurrentAssignmentCount device@(Model.CurrentAssignmentCount != 1 ? "s are" : " is") currently assigned</strong>
|
|
<br />
|
|
<br />
|
|
}
|
|
Are you sure?
|
|
</p>
|
|
</div>
|
|
<script type="text/javascript">
|
|
$(function () {
|
|
let buttonDialog = null;
|
|
$('#Config_DeviceFlags_Actions_Delete_Button').on('click', function () {
|
|
const $button = $(this);
|
|
if (!buttonDialog) {
|
|
buttonDialog = $('#Config_DeviceFlags_Actions_Delete_Dialog').dialog({
|
|
resizable: false,
|
|
modal: true,
|
|
autoOpen: false,
|
|
buttons: {
|
|
"Delete": function () {
|
|
$(this)
|
|
.dialog("option", "buttons", null)
|
|
.find('form').trigger('submit');
|
|
},
|
|
Cancel: function () {
|
|
$(this).dialog("close");
|
|
}
|
|
}
|
|
});
|
|
}
|
|
buttonDialog.dialog('open');
|
|
});
|
|
});
|
|
</script>
|
|
}
|
|
@if (canShowDevices)
|
|
{
|
|
@Html.ActionLinkButton(string.Format("Show {0} device{1}", Model.CurrentAssignmentCount, (Model.CurrentAssignmentCount == 1 ? null : "s")), MVC.Search.Query(Model.DeviceFlag.Id.ToString(), "DeviceFlag"), "Config_DeviceFlags_Actions_ShowDevices_Button")
|
|
}
|
|
</div>
|
|
}
|