aperio device actions to modal in blazor page
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.3.32825.248
|
||||
# Visual Studio Version 18
|
||||
VisualStudioVersion = 18.0.11123.170 d18.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aperio_Control_Centre", "Aperio_Control_Centre\Aperio_Control_Centre.csproj", "{E58799A0-6C10-4CEB-BBE2-78A85755B44B}"
|
||||
EndProject
|
||||
|
||||
@@ -162,22 +162,31 @@
|
||||
</TemplateColumn> *@
|
||||
|
||||
<TemplateColumn Title="Actions">
|
||||
<button class="btn btn-primary" @onclick="@(() => Actions(context))">Actions</button>
|
||||
@* <button class="btn btn-primary" @onclick="@(() => Actions(context))">Actions</button> *@
|
||||
<button class="btn btn-primary" @onclick="@(() => ShowDeviceActions(context))">Actions</button>
|
||||
</TemplateColumn>
|
||||
</QuickGrid>
|
||||
|
||||
<p><strong>@message</strong></p>
|
||||
|
||||
<DeviceActions IsOpen=_showDeviceActions AperioDevice=_deviceActionAperioDevice OnClose="CloseDeviceActions"></DeviceActions>
|
||||
|
||||
|
||||
@code {
|
||||
private QuickGrid<IAperioBase>? devicesGrid;
|
||||
private IQueryable<IAperioBase>? devices;
|
||||
|
||||
private GridSort<IAperioBase> sortByFullName = GridSort<IAperioBase>.ByAscending(e => e.Id);
|
||||
|
||||
string message = string.Empty;
|
||||
private string message = string.Empty;
|
||||
|
||||
private PeriodicTimer refreshTimer = new(TimeSpan.FromSeconds(1));
|
||||
|
||||
public bool _showDeviceActions { get; set; } = false;
|
||||
private IAperioBase? _deviceActionAperioDevice { get; set; }
|
||||
|
||||
|
||||
|
||||
// protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
// {
|
||||
// if (firstRender)
|
||||
@@ -220,8 +229,20 @@
|
||||
this.StateHasChanged();
|
||||
}
|
||||
|
||||
void Actions(IAperioBase p)
|
||||
private void Actions(IAperioBase p)
|
||||
{
|
||||
navigation.NavigateTo($"Aperio/DeviceActions/{p.Id}");
|
||||
}
|
||||
|
||||
|
||||
private void ShowDeviceActions(IAperioBase device)
|
||||
{
|
||||
_deviceActionAperioDevice = device;
|
||||
_showDeviceActions = true;
|
||||
}
|
||||
|
||||
public void CloseDeviceActions()
|
||||
{
|
||||
_showDeviceActions = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,164 @@
|
||||
@inject IJSRuntime JS
|
||||
|
||||
<script src="./BlazorComponents/Aperio/DeviceActions.razor.js"></script>
|
||||
|
||||
<!-- Modal -->
|
||||
<div class="modal fade" id="deviceActionsModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true" @ref=ModalRef>
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Device Actions @AperioDevice?.Name</h5>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-8 offset-lg-2">
|
||||
|
||||
|
||||
@if (AperioDevice is IAperioDoor aperioDoor)
|
||||
{
|
||||
<div class="row mb-3">
|
||||
<button class="btn btn-primary" onclick="@(async () => await aperioDoor.GetSupportedDoorModesFromDevice(tokenSource.Token))">Get Supported Door Modes</button>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<button class="btn btn-primary" onclick="@(async () => await aperioDoor.GetDoorModeFromDevice(tokenSource.Token))">Get Door Mode</button>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<button class="btn btn-primary" onclick="@(async () => await aperioDoor.GetDoorStateFromDevice(tokenSource.Token))">Get Door State</button>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<button class="btn btn-primary" onclick="@(async () => await aperioDoor.GetLockStateFromDevice(tokenSource.Token))">Get Lock State</button>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (AperioDevice is IAperioLockDevice aperioLock)
|
||||
{
|
||||
<div class="row mb-3">
|
||||
<button class="btn btn-primary" onclick="@(async () => await aperioLock.GetKeyCylinderStateFromDevice(tokenSource.Token))">Get KeyCylinder State</button>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<button class="btn btn-primary" onclick="@(async () => await aperioLock.GetHandleStateFromDevice(tokenSource.Token))">Get Handle State</button>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<button class="btn btn-primary" onclick="@(async () => await aperioLock.GetDTCsFromDevice(tokenSource.Token))">Get DTC'S</button>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<button class="btn btn-primary" onclick="@(async () => await aperioLock.GetLockVersionsFromDevice(tokenSource.Token))">Get lock version</button>
|
||||
</div>
|
||||
@if (aperioLock is IAperioWireless aperioWireless)
|
||||
{
|
||||
<div class="row mb-3">
|
||||
<button class="btn btn-primary" onclick="@(async () => await aperioWireless.GetAuditTrail(tokenSource.Token))">Get Audit Trail</button>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<button class="btn btn-primary" onclick="@(async () => await aperioWireless.DeleteCredentials(tokenSource.Token))">Delete Credentials</button>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
@if (AperioDevice is IAperioHubDevice aperioHub)
|
||||
{
|
||||
<div class="row mb-3">
|
||||
<button class="btn btn-primary" onclick="@(async () => await aperioHub.GetDeviceListFromDevice(tokenSource.Token))">Get device list</button>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<button class="btn btn-primary" onclick="@(async () => await aperioHub.GetDeviceTimeFromDevice(tokenSource.Token))">Get device time</button>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<button class="btn btn-primary" onclick="@(async () => await aperioHub.SetDeviceTimeOnDevice(tokenSource.Token))">Set device time</button>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<button class="btn btn-primary" onclick="@(async () => await aperioHub.GetTamperStateFromDevice(tokenSource.Token))">Get Tamper State</button>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<button class="btn btn-primary" onclick="@(async () => await aperioHub.RestartDevice(tokenSource.Token))">Restart device</button>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<button class="btn btn-primary" onclick="@(async () => await aperioHub.GetDTCsFromDevice(tokenSource.Token))">Get DTC'S</button>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<button class="btn btn-primary" onclick="@(async () => await aperioHub.GetFirmwareVersionFromDevice(tokenSource.Token))">Get firmware version</button>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<button class="btn btn-primary" onclick="@(async () => await aperioHub.GetLockVersionsFromDevice(tokenSource.Token))">Get lock version</button>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<button class="btn btn-primary" onclick="@(async () => await aperioHub.GetMainHwVersionFromDevice(tokenSource.Token))">Get Hardware version</button>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (AperioDevice is IAperioOptaDevice aperioOpta)
|
||||
{
|
||||
<div class="row mb-3">
|
||||
<button class="btn btn-primary" onclick="@(async () => await aperioOpta.UnlockDoor(tokenSource.Token))">Unlock Door</button>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<button class="btn btn-primary" onclick="@(async () => await aperioOpta.GetActivatorStateFromDevice(tokenSource.Token))">Get Activator State</button>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<button class="btn btn-primary" onclick="@(async () => await aperioOpta.GetTamperStateFromDevice(tokenSource.Token))">Get Tamper State</button>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<button class="btn btn-primary" onclick="@(async () => await aperioOpta.RestartDevice(tokenSource.Token))">Restart device</button>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<button class="btn btn-primary" onclick="@(async () => await aperioOpta.GetFirmwareVersionFromDevice(tokenSource.Token))">Get firmware version</button>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<button class="btn btn-primary" onclick="@(async () => await aperioOpta.GetMainHwVersionFromDevice(tokenSource.Token))">Get Hardware version</button>
|
||||
</div>
|
||||
}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" @onclick="@(async () => await OnClose.InvokeAsync())">Close</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
@code {
|
||||
private ElementReference ModalRef;
|
||||
|
||||
[Parameter]
|
||||
public bool IsOpen { get; set; }
|
||||
private bool _isOpen;
|
||||
|
||||
[Parameter]
|
||||
public IAperioBase? AperioDevice { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public EventCallback OnClose { get; set; }
|
||||
|
||||
CancellationTokenSource tokenSource = new CancellationTokenSource();
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
await ToggleModal();
|
||||
await base.OnParametersSetAsync();
|
||||
}
|
||||
|
||||
private async Task ToggleModal()
|
||||
{
|
||||
if (_isOpen == IsOpen) return;
|
||||
|
||||
string jsCommand = IsOpen ? "showModal" : "closeModal";
|
||||
await JS.InvokeVoidAsync(jsCommand, ModalRef);
|
||||
|
||||
_isOpen = IsOpen;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
function showModal(modal) {
|
||||
|
||||
//console.debug("modal open");
|
||||
//console.debug(modal);
|
||||
//modal.modal('show');
|
||||
|
||||
$('#deviceActionsModal').modal('show');
|
||||
}
|
||||
|
||||
function closeModal(modal) {
|
||||
|
||||
//console.debug("modal close");
|
||||
//console.debug(modal);
|
||||
//modal.modal('hide');
|
||||
|
||||
$('#deviceActionsModal').modal('hide');
|
||||
}
|
||||
@@ -1,17 +1,11 @@
|
||||
using Aperio_Control_Centre.AperioServer;
|
||||
using Aperio_Control_Centre.AperioServer.Devices;
|
||||
using Aperio_Control_Centre.Extensions;
|
||||
using Aperio_Control_Centre.Extensions;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Localization;
|
||||
|
||||
namespace Aperio_Control_Centre.Controllers
|
||||
{
|
||||
public class AperioController(IAperioDeviceList deviceList, IStringLocalizer<AperioController> localizer) : Controller
|
||||
public class AperioController() : Controller
|
||||
{
|
||||
private readonly IAperioDeviceList _deviceList = deviceList;
|
||||
private readonly IStringLocalizer<AperioController> _localizer = localizer;
|
||||
|
||||
[HttpGet]
|
||||
[Authorize]
|
||||
public ActionResult Connections()
|
||||
@@ -38,151 +32,5 @@ namespace Aperio_Control_Centre.Controllers
|
||||
this.CreateReturnUrl();
|
||||
return View();
|
||||
}
|
||||
|
||||
|
||||
[HttpGet]
|
||||
[Authorize]
|
||||
public ActionResult DeviceActions(string? id)
|
||||
{
|
||||
//Debug.WriteLine($"Device ID = {id}");
|
||||
|
||||
if (id == null)
|
||||
{
|
||||
return BadRequest();
|
||||
}
|
||||
|
||||
IAperioBase? dev = _deviceList.GetDevice(id);
|
||||
if (dev == null)
|
||||
{
|
||||
return RedirectToAction("Devices");
|
||||
}
|
||||
|
||||
//TODO: use dev.Id in title
|
||||
//this.CreateTitle();
|
||||
ViewData["title"] = _localizer["DeviceActions", dev.Id];
|
||||
return View(dev);
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Authorize]
|
||||
public async Task<ActionResult> DoDeviceActions(string? deviceId, string? command, CancellationToken token)
|
||||
{
|
||||
//Debug.WriteLine($"Id = {deviceId}");
|
||||
//Debug.WriteLine($"Command = {command}");
|
||||
|
||||
if (deviceId == null || command == null)
|
||||
{
|
||||
return BadRequest();
|
||||
}
|
||||
IAperioBase? dev = _deviceList.GetDevice(deviceId);
|
||||
|
||||
if (dev == null)
|
||||
{
|
||||
return RedirectToAction("Devices");
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (command)
|
||||
{
|
||||
case "getsupporteddoormodes":
|
||||
if (dev is IAperioDoor d1)
|
||||
{
|
||||
await d1.GetSupportedDoorModesFromDevice(token);
|
||||
}
|
||||
break;
|
||||
case "getdoormode":
|
||||
if (dev is IAperioDoor d2)
|
||||
{
|
||||
await d2.GetDoorModeFromDevice(token);
|
||||
}
|
||||
break;
|
||||
case "getdoorstate":
|
||||
if (dev is IAperioDoor d3)
|
||||
{
|
||||
await d3.GetDoorStateFromDevice(token);
|
||||
}
|
||||
break;
|
||||
case "getlockstate":
|
||||
if (dev is IAperioDoor d4)
|
||||
{
|
||||
await d4.GetLockStateFromDevice(token);
|
||||
}
|
||||
break;
|
||||
case "getkeycylinderstate":
|
||||
if (dev is IAperioWireless d5)
|
||||
{
|
||||
await d5.GetKeyCylinderStateFromDevice(token);
|
||||
}
|
||||
break;
|
||||
case "gethandlestate":
|
||||
if (dev is IAperioWireless d6)
|
||||
{
|
||||
await d6.GetHandleStateFromDevice(token);
|
||||
}
|
||||
break;
|
||||
case "tamperstate":
|
||||
await dev.GetTamperStateFromDevice(token);
|
||||
break;
|
||||
case "getactivatorstate":
|
||||
if (dev is IAperioActivator d7)
|
||||
{
|
||||
await d7.GetActivatorStateFromDevice(token);
|
||||
}
|
||||
break;
|
||||
case "getdevicelist":
|
||||
await dev.GetDeviceListFromDevice(token);
|
||||
break;
|
||||
case "getdevicetime":
|
||||
if (dev is IAperioHubDevice d9)
|
||||
{
|
||||
await d9.GetDeviceTimeFromDevice(token);
|
||||
}
|
||||
break;
|
||||
case "setdevicetime":
|
||||
if (dev is IAperioHubDevice d10)
|
||||
{
|
||||
await d10.SetDeviceTimeOnDevice(token);
|
||||
}
|
||||
break;
|
||||
case "restart":
|
||||
await dev.RestartDevice(token);
|
||||
break;
|
||||
case "getdtcs":
|
||||
await dev.GetDTCsFromDevice(token);
|
||||
break;
|
||||
case "getfirmwareversion":
|
||||
await dev.GetFirmwareVersionFromDevice(token);
|
||||
break;
|
||||
case "getlockversions":
|
||||
await dev.GetLockVersionsFromDevice(token);
|
||||
break;
|
||||
case "getmainhwversion":
|
||||
await dev.GetMainHwVersionFromDevice(token);
|
||||
break;
|
||||
case "unlockdoor":
|
||||
if (dev is IAperioDoor d11)
|
||||
{
|
||||
await d11.UnlockDoor(token);
|
||||
}
|
||||
break;
|
||||
case "getaudittrail":
|
||||
if (dev is IAperioWireless d12)
|
||||
{
|
||||
await d12.GetAuditTrail(token);
|
||||
}
|
||||
break;
|
||||
case "deletecredentials":
|
||||
if (dev is IAperioWireless d13)
|
||||
{
|
||||
await d13.DeleteCredentials(token);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return new RedirectToRouteResult(new RouteValueDictionary(new { action = "DeviceActions", controller = "Aperio", id = deviceId }));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,7 +125,7 @@ namespace Aperio_Control_Centre.Controllers
|
||||
List<string> Devices = db.DoorModeSchedules.Where(i => i.TimezoneId == timezone.Id).Select(d => d.Device.DeviceId).ToList();
|
||||
foreach (string deviceId in Devices)
|
||||
{
|
||||
Debug.WriteLine(deviceId);
|
||||
//Debug.WriteLine(deviceId);
|
||||
if (_devicesList.GetDevice(deviceId) is IAperioDoor door)
|
||||
{
|
||||
await door.LoadDoorModeSchedule(token);
|
||||
|
||||
@@ -1,120 +0,0 @@
|
||||
@using Aperio_Control_Centre.AperioServer.Devices
|
||||
@model Aperio_Control_Centre.AperioServer.Devices.IAperioBase
|
||||
@inject IViewLocalizer Localizer
|
||||
|
||||
<script type=text/javascript>
|
||||
function callAction(deviceid, command) {
|
||||
$.ajax({
|
||||
url: '@Url.Action("DoDeviceActions", "Aperio")' + "?deviceId=" + deviceid + "&command=" + command,
|
||||
type: "GET"
|
||||
})
|
||||
.done(function (result) {
|
||||
if (result.error) {
|
||||
alert(result.error);
|
||||
}
|
||||
})
|
||||
.fail(function (xhr, status) {
|
||||
alert(status);
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
@Html.PageTitle(ViewData)
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-6 offset-lg-3">
|
||||
|
||||
@if(Model is IAperioDoor)
|
||||
{
|
||||
<div class="row mb-3">
|
||||
<button class="btn btn-primary" onclick="callAction('@Model.Id','getsupporteddoormodes')">@Localizer["getsupporteddoormodes"]</button>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<button class="btn btn-primary" onclick="callAction('@Model.Id','getdoormode')">Get Door Mode</button>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<button class="btn btn-primary" onclick="callAction('@Model.Id','getdoorstate')">Get Door State</button>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<button class="btn btn-primary" onclick="callAction('@Model.Id','getlockstate')">Get Lock State</button>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<button class="btn btn-primary" onclick="callAction('@Model.Id','getdevicelist')">Get device list</button>
|
||||
</div>
|
||||
}
|
||||
@if (Model is IAperioLockDevice)
|
||||
{
|
||||
<div class="row mb-3">
|
||||
<button class="btn btn-primary" onclick="callAction('@Model.Id','getkeycylinderstate')">Get KeyCylinder State</button>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<button class="btn btn-primary" onclick="callAction('@Model.Id','gethandlestate')">Get Handle State</button>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<button class="btn btn-primary" onclick="callAction('@Model.Id','getdtcs')">Get DTC'S</button>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<button class="btn btn-primary" onclick="callAction('@Model.Id','getlockversions')">Get lock version</button>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<button class="btn btn-primary" onclick="callAction('@Model.Id','getaudittrail')">Get Audit Trail</button>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<button class="btn btn-primary" onclick="callAction('@Model.Id','deletecredentials')">Delete Credentials</button>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (Model is IAperioHubDevice)
|
||||
{
|
||||
<div class="row mb-3">
|
||||
<button class="btn btn-primary" onclick="callAction('@Model.Id','getdevicelist')">Get device list</button>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<button class="btn btn-primary" onclick="callAction('@Model.Id','getdevicetime')">Get device time</button>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<button class="btn btn-primary" onclick="callAction('@Model.Id','setdevicetime')">Set device time</button>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<button class="btn btn-primary" onclick="callAction('@Model.Id','tamperstate')">Get Tamper State</button>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<button class="btn btn-primary" onclick="callAction('@Model.Id','restart')">Restart device</button>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<button class="btn btn-primary" onclick="callAction('@Model.Id','getdtcs')">Get DTC'S</button>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<button class="btn btn-primary" onclick="callAction('@Model.Id','getfirmwareversion')">Get firmware version</button>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<button class="btn btn-primary" onclick="callAction('@Model.Id','getlockversions')">Get lock version</button>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<button class="btn btn-primary" onclick="callAction('@Model.Id','getmainhwversion')">Get Hardware version</button>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (Model is IAperioOptaDevice)
|
||||
{
|
||||
<div class="row mb-3">
|
||||
<button class="btn btn-primary" onclick="callAction('@Model.Id','unlockdoor')">Unlock Door</button>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<button class="btn btn-primary" onclick="callAction('@Model.Id','getactivatorstate')">Get Activator State</button>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<button class="btn btn-primary" onclick="callAction('@Model.Id','tamperstate')">Get Tamper State</button>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<button class="btn btn-primary" onclick="callAction('@Model.Id','restart')">Restart device</button>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<button class="btn btn-primary" onclick="callAction('@Model.Id','getfirmwareversion')">Get firmware version</button>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<button class="btn btn-primary" onclick="callAction('@Model.Id','getmainhwversion')">Get Hardware version</button>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
Reference in New Issue
Block a user