mirror of
https://github.com/immense/Remotely.git
synced 2025-10-26 11:27:15 +00:00
260 lines
12 KiB
Plaintext
260 lines
12 KiB
Plaintext
@page "/device-details/{deviceId?}"
|
|
|
|
@attribute [Authorize]
|
|
@inherits AuthComponentBase
|
|
|
|
|
|
@if (string.IsNullOrWhiteSpace(DeviceId))
|
|
{
|
|
<div class="row mt-5">
|
|
<div class="col-sm-6 offset-2">
|
|
|
|
<h3>Device ID:</h3>
|
|
<div class="input-group mb-2">
|
|
<input type="text" class="form-control" placeholder="Enter a device ID to see its details"
|
|
@bind="_inputDeviceId"
|
|
@bind:event="oninput"
|
|
@onkeydown="EvaluateDeviceIdInputKeyDown">
|
|
<div class="input-group-append">
|
|
<button class="btn btn-primary" @onclick="NavigateToDeviceId">Go</button>
|
|
</div>
|
|
</div>
|
|
<div class="text-muted">
|
|
You can also go directly to a device's details by:
|
|
<ul>
|
|
<li>Right-clicking a device card on the main page while it's collapsed</li>
|
|
<li>Clicking the "Open in New Tab" button in a device card's header while it's expanded</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
}
|
|
else if (Device is null)
|
|
{
|
|
<h3>Device not found.</h3>
|
|
}
|
|
else if (!DataService.DoesUserHaveAccessToDevice(Device.ID, User))
|
|
{
|
|
<h3>Unauthorized.</h3>
|
|
}
|
|
else
|
|
{
|
|
<TabControl InitialActiveTab="device">
|
|
<TabHeaders>
|
|
<TabHeader Name="device">
|
|
Details
|
|
</TabHeader>
|
|
<TabHeader Name="remote-logs" OnActivated="GetRemoteLogs">
|
|
Remote Logs
|
|
</TabHeader>
|
|
<TabHeader Name="script-history" OnActivated="GetScriptHistory">
|
|
Script History
|
|
</TabHeader>
|
|
</TabHeaders>
|
|
|
|
<TabContents>
|
|
<TabContent Name="device">
|
|
<div class="col-sm-8 mb-2">
|
|
<h3 class="mb-3 mt-3">
|
|
Device Details
|
|
</h3>
|
|
|
|
<EditForm Model="Device" OnValidSubmit="HandleValidSubmit" @onkeydown="EditFormKeyDown">
|
|
<DataAnnotationsValidator />
|
|
<ValidationSummary />
|
|
|
|
@if (!string.IsNullOrWhiteSpace(_alertMessage))
|
|
{
|
|
<AlertBanner Message="@_alertMessage" />
|
|
}
|
|
|
|
|
|
<div class="form-group row">
|
|
<label for="device-name" class="col-sm-2 col-form-label">Device:</label>
|
|
<div class="col-sm-10">
|
|
<input type="text" class="form-control" name="device-name" readonly value="@Device.DeviceName" />
|
|
</div>
|
|
</div>
|
|
<div class="form-group row">
|
|
<label for="device-id" class="col-sm-2 col-form-label">Device ID:</label>
|
|
<div class="col-sm-10">
|
|
<input type="text" class="form-control" name="device-id" readonly value="@Device.ID" />
|
|
</div>
|
|
</div>
|
|
<div class="form-group row">
|
|
<label for="agent-version" class="col-sm-2 col-form-label">Agent Version:</label>
|
|
<div class="col-sm-10">
|
|
<input type="text" class="form-control" name="agent-version" readonly value="@Device.AgentVersion" />
|
|
</div>
|
|
</div>
|
|
<div class="form-group row">
|
|
<label for="agent-platform" class="col-sm-2 col-form-label">Platform:</label>
|
|
<div class="col-sm-10">
|
|
<input type="text" class="form-control" name="agent-platform" readonly value="@Device.Platform" />
|
|
</div>
|
|
</div>
|
|
<div class="form-group row">
|
|
<label for="agent-os-description" class="col-sm-2 col-form-label">Platform:</label>
|
|
<div class="col-sm-10">
|
|
<input type="text" class="form-control" name="agent-os-description" readonly value="@Device.OSDescription" />
|
|
</div>
|
|
</div>
|
|
<div class="form-group row">
|
|
<label for="agent-storage-percent" class="col-sm-2 col-form-label">
|
|
Disk:
|
|
<button type="button" class="btn btn-link p-0 m-0" @onclick="ShowAllDisks" style="font-size: 50%">
|
|
(View All)
|
|
</button>
|
|
</label>
|
|
<div class="col-sm-10">
|
|
<input type="text" class="form-control" name="agent-storage-percent" readonly value="@(MathHelper.GetFormattedPercent(Device.UsedStoragePercent))" />
|
|
</div>
|
|
</div>
|
|
<div class="form-group row">
|
|
<label for="agent-storage-total" class="col-sm-2 col-form-label">
|
|
Total Storage:
|
|
</label>
|
|
<div class="col-sm-10">
|
|
<input type="text" class="form-control" name="agent-storage-total" readonly value="@(Device.TotalStorage)" />
|
|
</div>
|
|
</div>
|
|
<div class="form-group row">
|
|
<label for="agent-memory-percent" class="col-sm-2 col-form-label">
|
|
Memory:
|
|
</label>
|
|
<div class="col-sm-10">
|
|
<input type="text" class="form-control" name="agent-memory-percent" readonly value="@(MathHelper.GetFormattedPercent(Device.UsedMemoryPercent))" />
|
|
</div>
|
|
</div>
|
|
<div class="form-group row">
|
|
<label for="agent-memory-total" class="col-sm-2 col-form-label">
|
|
Total Memory:
|
|
</label>
|
|
<div class="col-sm-10">
|
|
<input type="text" class="form-control" name="agent-memory-total" readonly value="@(Device.TotalMemory)" />
|
|
</div>
|
|
</div>
|
|
<div class="form-group row">
|
|
<label for="device-alias" class="col-sm-2 col-form-label">Device Alias:</label>
|
|
<div class="col-sm-10">
|
|
<InputText class="form-control" @bind-Value="@Device.Alias" />
|
|
<ValidationMessage For="() => Device.Alias" />
|
|
</div>
|
|
</div>
|
|
<div class="form-group row">
|
|
<label for="webrtc-setting" class="col-sm-2 col-form-label">WebRTC Setting:</label>
|
|
<div class="col-sm-10">
|
|
<InputSelect @bind-Value="Device.WebRtcSetting" class="form-control">
|
|
@foreach (var setting in Enum.GetValues(typeof(WebRtcSetting)))
|
|
{
|
|
<option @key="setting" value="@setting">@setting</option>
|
|
}
|
|
</InputSelect>
|
|
<ValidationMessage For="() => Device.WebRtcSetting" />
|
|
</div>
|
|
|
|
</div>
|
|
<div class="form-group row">
|
|
<label for="device-groups" class="col-sm-2 col-form-label">Device Group:</label>
|
|
<div class="col-sm-10">
|
|
<InputSelect @bind-Value="Device.DeviceGroupID" class="form-control">
|
|
<option value="">None</option>
|
|
|
|
@foreach (var group in DataService.GetDeviceGroups(Username))
|
|
{
|
|
<option @key="group.ID" value="@group.ID">@group.Name</option>
|
|
}
|
|
</InputSelect>
|
|
<ValidationMessage For="() => Device.DeviceGroupID" />
|
|
</div>
|
|
</div>
|
|
<div class="form-group row">
|
|
<label for="tags" class="col-sm-2 col-form-label">Tags:</label>
|
|
<div class="col-sm-10">
|
|
<InputText @bind-Value="Device.Tags" class="form-control" />
|
|
<ValidationMessage For="() => Device.Tags" />
|
|
</div>
|
|
</div>
|
|
<div class="form-group row">
|
|
<label for="notes" class="col-sm-2 col-form-label">Notes:</label>
|
|
<div class="col-sm-10">
|
|
<InputTextArea @bind-Value="Device.Notes" style="width:100%; height: 10em;"></InputTextArea>
|
|
<ValidationMessage For="() => Device.Notes" />
|
|
</div>
|
|
</div>
|
|
<div class="text-right">
|
|
<button type="submit" class="btn btn-primary">Save</button>
|
|
</div>
|
|
</EditForm>
|
|
</div>
|
|
</TabContent>
|
|
|
|
<TabContent Name="remote-logs">
|
|
<div class="py-3">
|
|
@if (!Device.IsOnline)
|
|
{
|
|
<h5 class="text-center mt-5">Device must be online to retrieve logs.</h5>
|
|
}
|
|
else
|
|
{
|
|
@if (_logLines.Any())
|
|
{
|
|
<div style="white-space: pre;">
|
|
@foreach (var line in _logLines)
|
|
{
|
|
@line
|
|
}
|
|
</div>
|
|
}
|
|
else
|
|
{
|
|
<LoadingSignal />
|
|
}
|
|
}
|
|
|
|
</div>
|
|
|
|
</TabContent>
|
|
|
|
<TabContent Name="script-history">
|
|
|
|
<h3 class="mb-3 mt-3">
|
|
Script History
|
|
</h3>
|
|
<table class="table table-hover table-striped">
|
|
<thead>
|
|
<tr>
|
|
<th>Shell</th>
|
|
<th>Timestamp</th>
|
|
<th>User</th>
|
|
<th>Duration</th>
|
|
<th>Input</th>
|
|
<th>Output</th>
|
|
<th>Error</th>
|
|
<th></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@foreach (var scriptResult in _scriptResults)
|
|
{
|
|
<tr>
|
|
<td>@scriptResult.Shell</td>
|
|
<td>@scriptResult.TimeStamp</td>
|
|
<td>@scriptResult.SenderUserName</td>
|
|
<td>@scriptResult.RunTime</td>
|
|
<td>@GetTrimmedText(scriptResult.ScriptInput, 25)</td>
|
|
<td>@GetTrimmedText(scriptResult.StandardOutput, 25)</td>
|
|
<td>@GetTrimmedText(scriptResult.ErrorOutput, 25)</td>
|
|
<td>
|
|
<button class="btn btn-sm btn-primary" @onclick="() => ShowFullScriptOutput(scriptResult)">Show Full</button>
|
|
</td>
|
|
</tr>
|
|
}
|
|
</tbody>
|
|
</table>
|
|
|
|
</TabContent>
|
|
</TabContents>
|
|
</TabControl>
|
|
}
|