Compare commits
2 Commits
261d2db417
...
7b1216eec1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7b1216eec1 | ||
|
|
9787422f65 |
@ -71,6 +71,7 @@ public class EventManager
|
||||
DateTime? to = null,
|
||||
int? limit = null,
|
||||
int? offset = null,
|
||||
Event.ValenceType? valenceType = null,
|
||||
Dictionary<string, object>? filters = null)
|
||||
{
|
||||
if(History is null)
|
||||
@ -92,6 +93,9 @@ public class EventManager
|
||||
if (to is not null)
|
||||
ret = ret.Where(x => x.When <= to);
|
||||
|
||||
if (valenceType is not null)
|
||||
ret = ret.Where(x => x.Valence == valenceType);
|
||||
|
||||
if (offset is not null)
|
||||
ret = ret.Skip(offset.Value);
|
||||
|
||||
@ -101,12 +105,14 @@ public class EventManager
|
||||
foreach (var i in ret)
|
||||
yield return i;
|
||||
|
||||
|
||||
|
||||
//TODO: Implement filters
|
||||
|
||||
yield break;
|
||||
}
|
||||
|
||||
await foreach (var i in History.GetEvents(subject, from, to, limit, offset, filters))
|
||||
await foreach (var i in History.GetEvents(subject, from, to, limit, offset, valenceType, filters))
|
||||
yield return i;
|
||||
}
|
||||
}
|
||||
@ -31,7 +31,14 @@ public abstract class Persistence
|
||||
|
||||
public abstract Task RegisterEvent(Event e);
|
||||
public abstract Task<Event?> GetEvent(string id);
|
||||
public abstract IAsyncEnumerable<Event> GetEvents(string? subject = null, DateTime? from = null, DateTime? to = null, int? limit = null, int? offset = null, Dictionary<string, object>? filters = null);
|
||||
public abstract IAsyncEnumerable<Event> GetEvents(
|
||||
string? subject = null,
|
||||
DateTime? from = null,
|
||||
DateTime? to = null,
|
||||
int? limit = null,
|
||||
int? offset = null,
|
||||
Event.ValenceType? valenceType = null,
|
||||
Dictionary<string, object>? filters = null);
|
||||
|
||||
protected virtual void ExceptionCatched(Exception e)
|
||||
{
|
||||
|
||||
@ -2,12 +2,22 @@
|
||||
|
||||
public class Event
|
||||
{
|
||||
public enum ValenceType
|
||||
{
|
||||
Normal,
|
||||
Error,
|
||||
Emergency
|
||||
}
|
||||
|
||||
public const string TYPE_STATE_CHANGED = "state_changed";
|
||||
public const string TYPE_LOG = "log";
|
||||
|
||||
public string UniqueId { get; set; }
|
||||
public string ThrowerId { get; set; }
|
||||
public string Type { get; set; }
|
||||
public DateTime When { get; set; } = DateTime.Now;
|
||||
public string Description { get; set; } = "";
|
||||
public ValenceType Valence { get; set; } = default;
|
||||
|
||||
public Dictionary<string, object> Properties { get; protected set; } = new Dictionary<string, object>();
|
||||
public object? this[string key]
|
||||
@ -32,11 +42,12 @@ public class Event
|
||||
|
||||
}
|
||||
|
||||
public Event(string uniqueId, string throwerId, string type, DateTime? when = null)
|
||||
public Event(string uniqueId, string throwerId, string type, string description = "", DateTime? when = null)
|
||||
{
|
||||
UniqueId = uniqueId;
|
||||
ThrowerId = throwerId;
|
||||
Type = type;
|
||||
Description = description;
|
||||
if(when != null)
|
||||
When = when.Value;
|
||||
}
|
||||
@ -44,8 +55,28 @@ public class Event
|
||||
public static Event FromStateChange(string key, object? value, DateTime when)
|
||||
{
|
||||
string id = Guid.NewGuid().ToString();
|
||||
var ret = new Event(id, key, TYPE_STATE_CHANGED, when);
|
||||
var ret = new Event(id, key, TYPE_STATE_CHANGED, when:when);
|
||||
ret[nameof(Triplet.value)] = value;
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static Event FromLog(
|
||||
string thrower,
|
||||
string content,
|
||||
DateTime? when = null,
|
||||
int severity = 6,
|
||||
Exception? exception = null
|
||||
)
|
||||
{
|
||||
if (when == null)
|
||||
when = DateTime.Now;
|
||||
|
||||
string id = Guid.NewGuid().ToString();
|
||||
var ret = new Event(id, thrower, TYPE_LOG, description: content, when: when);
|
||||
ret["severity"] = severity;
|
||||
if (exception is not null && exception.StackTrace is not null)
|
||||
ret["trace"] = exception.StackTrace;
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
@ -54,6 +54,12 @@ public class Instance
|
||||
State.Push(t.key, t.predicate, t.value, t.LastFlush);
|
||||
}
|
||||
|
||||
public void Add(IEnumerable<Event> events)
|
||||
{
|
||||
foreach (var i in events)
|
||||
Event.Push(i);
|
||||
}
|
||||
|
||||
public T? RetrieveElement<T>(string id) where T : Element
|
||||
{
|
||||
var triplets = State.Get(id).ToList();
|
||||
|
||||
12
Salmon.Core/Salmon - Backup.Core.csproj
Normal file
12
Salmon.Core/Salmon - Backup.Core.csproj
Normal file
@ -0,0 +1,12 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
|
||||
<Title>Salmon.Core</Title>
|
||||
<Description>Common parts of Salmon</Description>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
@ -4,6 +4,11 @@
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
|
||||
<Title>Salmon.Core</Title>
|
||||
<PackageId>Salmon</PackageId>
|
||||
<Version>0.1.0</Version>
|
||||
<Description>Common parts of Salmon</Description>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@ -1,7 +1,4 @@
|
||||
using System.Net.Http.Json;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text.Json;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Salmon.Core;
|
||||
|
||||
@ -17,17 +14,18 @@ public class Transmitter
|
||||
foreach (Element element in elements)
|
||||
triplets.AddRange(Translator.Encode(element));
|
||||
|
||||
Console.WriteLine(JsonSerializer.Serialize(triplets));
|
||||
var result = await Client.PostAsJsonAsync(uri, triplets, cancellationToken: tk);
|
||||
|
||||
if (!result.IsSuccessStatusCode)
|
||||
throw new Exception($"SendAsync call return code {result.StatusCode} when call {uri}.");
|
||||
|
||||
throw new Exception($"SendAsync(elements) call return code {result.StatusCode} when call {uri}.");
|
||||
}
|
||||
|
||||
public async Task SendAsync(Uri uri, IEnumerable<Event> events, CancellationToken tk = default)
|
||||
{
|
||||
await Client.PostAsJsonAsync(uri, events, cancellationToken: tk);
|
||||
var result = await Client.PostAsJsonAsync(uri, events, cancellationToken: tk);
|
||||
|
||||
if (!result.IsSuccessStatusCode)
|
||||
throw new Exception($"SendAsync(events) call return code {result.StatusCode} when call {uri}.");
|
||||
}
|
||||
|
||||
public async Task SendAsync(IEnumerable<Element> elements, CancellationToken tk = default)
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
{
|
||||
"Url":"http://127.0.0.1:5009/api/",
|
||||
"Url":"http://salmon.voie93quarts.fr/api/",
|
||||
"Period":15000,
|
||||
"Watch":[
|
||||
{
|
||||
|
||||
@ -3,8 +3,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.6.33723.286
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Salmon.Model", "Salmon.Model\Salmon.Model.csproj", "{DD4EDB99-A7A9-413F-967B-FE4D0ADD8D0A}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Salmon.Core", "Salmon.Core\Salmon.Core.csproj", "{97733A9E-5BBB-484F-B8C7-AF4A6EC41731}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Salmon.Test", "Salmon.Test\Salmon.Test.csproj", "{CA8F6995-ED22-43BC-BE20-EB9D8477225A}"
|
||||
@ -13,16 +11,14 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Salmon.Web", "Salmon.Web\Sa
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Salmon.Service", "Salmon.Service\Salmon.Service.csproj", "{357108AA-4D7C-479D-93AA-9D7FC9455A48}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Salmon.Model", "Salmon.Model\Salmon.Model.csproj", "{5F083251-3DD9-4124-B467-B82665C32792}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{DD4EDB99-A7A9-413F-967B-FE4D0ADD8D0A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{DD4EDB99-A7A9-413F-967B-FE4D0ADD8D0A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{DD4EDB99-A7A9-413F-967B-FE4D0ADD8D0A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{DD4EDB99-A7A9-413F-967B-FE4D0ADD8D0A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{97733A9E-5BBB-484F-B8C7-AF4A6EC41731}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{97733A9E-5BBB-484F-B8C7-AF4A6EC41731}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{97733A9E-5BBB-484F-B8C7-AF4A6EC41731}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
@ -39,6 +35,10 @@ Global
|
||||
{357108AA-4D7C-479D-93AA-9D7FC9455A48}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{357108AA-4D7C-479D-93AA-9D7FC9455A48}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{357108AA-4D7C-479D-93AA-9D7FC9455A48}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{5F083251-3DD9-4124-B467-B82665C32792}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{5F083251-3DD9-4124-B467-B82665C32792}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{5F083251-3DD9-4124-B467-B82665C32792}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{5F083251-3DD9-4124-B467-B82665C32792}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
29
Salmon.Web/Components/CopyButton.razor
Normal file
29
Salmon.Web/Components/CopyButton.razor
Normal file
@ -0,0 +1,29 @@
|
||||
@inject IJSRuntime JSRuntime
|
||||
|
||||
<button type="button" class="btn" @onclick="CopyTextToClipboard">
|
||||
@if(Clicked)
|
||||
{
|
||||
<i class="bi bi-clipboard-check"></i>
|
||||
}
|
||||
else
|
||||
{
|
||||
<i class="bi bi-clipboard"></i>
|
||||
}
|
||||
|
||||
</button>
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public string Value { get; set; }
|
||||
|
||||
bool Clicked { get; set; } = false;
|
||||
|
||||
private async Task CopyTextToClipboard()
|
||||
{
|
||||
if (Value is null)
|
||||
return;
|
||||
|
||||
await JSRuntime.InvokeVoidAsync("clipboardCopy.copyText", Value.ToString());
|
||||
Clicked = true;
|
||||
}
|
||||
}
|
||||
40
Salmon.Web/Components/ElementCard.razor
Normal file
40
Salmon.Web/Components/ElementCard.razor
Normal file
@ -0,0 +1,40 @@
|
||||
@inject Salmon.Core.Instance Salmon;
|
||||
|
||||
@if(Target is not null)
|
||||
{
|
||||
<Card Class="col-6" Style="width:18rem;margin:10px;">
|
||||
<CardHeader>
|
||||
<NavLink href=@($"Element/{System.Web.HttpUtility.UrlEncode(Target.UniqueId)}")>
|
||||
<span class="oi oi-zoom-in" aria-hidden="true"></span>
|
||||
</NavLink>
|
||||
@Target.LastType
|
||||
</CardHeader>
|
||||
<CardBody>
|
||||
<CardTitle>@Target.ShortName</CardTitle>
|
||||
@if (!String.IsNullOrEmpty(Target.LongName))
|
||||
{
|
||||
<CardSubTitle>
|
||||
@Target.LongName
|
||||
</CardSubTitle>
|
||||
}
|
||||
<CardText>@Target.Description</CardText>
|
||||
</CardBody>
|
||||
<ul class="list-group list-group-flush">
|
||||
@foreach (var kv in Target.ImportantProperties())
|
||||
{
|
||||
<li class="list-group-item">@kv.Key: @kv.Value</li>
|
||||
}
|
||||
<li class="list-group-item"><small>id: @Target.UniqueId</small></li>
|
||||
</ul>
|
||||
@if (Salmon.GetLastElementUpdate(Target.UniqueId) is not null)
|
||||
{
|
||||
<CardFooter>
|
||||
<small class="text-muted">Last updated <i>@TimespanHelper.GetReadableTimespan(DateTime.Now - Salmon.GetLastElementUpdate(Target.UniqueId).Value)</i></small>
|
||||
</CardFooter>
|
||||
}
|
||||
</Card>
|
||||
}
|
||||
@code {
|
||||
[Parameter]
|
||||
public Element? Target { get; set; }
|
||||
}
|
||||
39
Salmon.Web/Components/ElementDeck.razor
Normal file
39
Salmon.Web/Components/ElementDeck.razor
Normal file
@ -0,0 +1,39 @@
|
||||
@inject Salmon.Core.Instance Salmon;
|
||||
|
||||
<div Style="display:flex;flex-wrap:wrap; height:100%;">
|
||||
@foreach (var e in Elements)
|
||||
{
|
||||
<ElementCard Target=e />
|
||||
}
|
||||
</div>
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public string? FilterByParent { get; set; } = null;
|
||||
|
||||
List<Element> Elements { get; set; } = new();
|
||||
private static System.Timers.Timer Time = new System.Timers.Timer(5000);
|
||||
|
||||
protected async override Task OnInitializedAsync()
|
||||
{
|
||||
await base.OnInitializedAsync();
|
||||
|
||||
Time.Elapsed += async (Object? source, System.Timers.ElapsedEventArgs e) =>
|
||||
{
|
||||
await InvokeAsync(() => Refresh());
|
||||
};
|
||||
Time.AutoReset = true;
|
||||
Time.Enabled = true;
|
||||
|
||||
Refresh();
|
||||
}
|
||||
|
||||
public void Refresh()
|
||||
{
|
||||
Elements = Salmon.GetAllElements().ToList();
|
||||
if (FilterByParent is not null)
|
||||
Elements = Elements.Where(x => x.ParentId == FilterByParent).ToList();
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
26
Salmon.Web/Components/EventTable.razor
Normal file
26
Salmon.Web/Components/EventTable.razor
Normal file
@ -0,0 +1,26 @@
|
||||
@if (Events is not null)
|
||||
{
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Date</th>
|
||||
<th>Type</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@if (Events is not null)
|
||||
@foreach (var e in Events)
|
||||
{
|
||||
<tr>
|
||||
<td>@e.When</td>
|
||||
<td>@e.Type</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
}
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public List<Event>? Events { get; set; } = null;
|
||||
}
|
||||
34
Salmon.Web/Components/PrettyValueDisplay.razor
Normal file
34
Salmon.Web/Components/PrettyValueDisplay.razor
Normal file
@ -0,0 +1,34 @@
|
||||
@using Salmon.Core.Cliff
|
||||
|
||||
|
||||
@if(Value is null)
|
||||
{
|
||||
<span>(null)</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Predicate is not null && Predicate == "parent")
|
||||
{
|
||||
<a href=@($"Element/{System.Web.HttpUtility.UrlEncode(Value.ToString())}")>@Value.ToString()</a>
|
||||
}
|
||||
else if (Predicate is not null && Predicate == "Uri")
|
||||
{
|
||||
<a href=@Value.ToString()>@Value.ToString()</a>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span>@Value.ToString()</span>
|
||||
}
|
||||
|
||||
<CopyButton Value=@Value.ToString() />
|
||||
}
|
||||
|
||||
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public object? Value { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string Predicate { get; set; }
|
||||
}
|
||||
34
Salmon.Web/Components/TripletTable.razor
Normal file
34
Salmon.Web/Components/TripletTable.razor
Normal file
@ -0,0 +1,34 @@
|
||||
@if(Triplets is not null)
|
||||
{
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Dernier changement</th>
|
||||
<th>Nom</th>
|
||||
<th>Valeur</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@if (Triplets is not null)
|
||||
@foreach (var t in Triplets)
|
||||
{
|
||||
<tr>
|
||||
<td>@t.LastFlush</td>
|
||||
<td>@t.predicate</td>
|
||||
<td>
|
||||
<PrettyValueDisplay Predicate=@t.predicate Value=@t.value />
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
}
|
||||
|
||||
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public List<Triplet>? Triplets { get; set; } = null;
|
||||
|
||||
|
||||
}
|
||||
@ -38,5 +38,11 @@ namespace Salmon.Web.Controllers
|
||||
{
|
||||
Instance.Set(triplets);
|
||||
}
|
||||
|
||||
[HttpPost("Push/Events")]
|
||||
public void Post([FromBody] IEnumerable<Event> events)
|
||||
{
|
||||
Instance.Add(events);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -218,6 +218,8 @@ public class MongoDbInterface
|
||||
new KeyValuePair<string, object>("_id", e.UniqueId),
|
||||
new KeyValuePair<string, object>("Thrower", e.ThrowerId),
|
||||
new KeyValuePair<string, object>("Type", e.Type),
|
||||
new KeyValuePair<string, object>("Description", e.Description),
|
||||
new KeyValuePair<string, object>("Valence", (int)e.Valence),
|
||||
new KeyValuePair<string, object>("When", e.When),
|
||||
new KeyValuePair<string, object>("Properties", properties),
|
||||
});
|
||||
@ -232,7 +234,19 @@ public class MongoDbInterface
|
||||
|
||||
private Event EventFromBson(BsonDocument bson)
|
||||
{
|
||||
Event ret = new(bson["_id"].AsString, bson["Thrower"].AsString, bson["Type"].AsString, bson["When"].ToUniversalTime());
|
||||
Event ret = new(
|
||||
bson["_id"].AsString,
|
||||
bson["Thrower"].AsString,
|
||||
bson["Type"].AsString,
|
||||
"",
|
||||
bson["When"].ToUniversalTime());
|
||||
|
||||
if (bson.Contains("Description"))
|
||||
ret.Description = bson["Description"].ToString() ?? "";
|
||||
|
||||
if (bson.Contains("Valence"))
|
||||
ret.Valence = (Event.ValenceType)bson["Valence"].ToInt32();
|
||||
|
||||
foreach (var kv in bson["Properties"].AsBsonDocument)
|
||||
ret.Properties.Add(kv.Name, kv.Value);
|
||||
|
||||
@ -247,14 +261,25 @@ public class MongoDbInterface
|
||||
return false;
|
||||
}
|
||||
|
||||
public override async IAsyncEnumerable<Event> GetEvents(string? subject = null, DateTime? from = null, DateTime? to = null, int? limit = null, int? offset = null, Dictionary<string, object>? filters = null)
|
||||
public override async IAsyncEnumerable<Event> GetEvents(
|
||||
string? subject = null,
|
||||
DateTime? from = null,
|
||||
DateTime? to = null,
|
||||
int? limit = null,
|
||||
int? offset = null,
|
||||
Event.ValenceType? valenceType = null,
|
||||
Dictionary<string, object>? filters = null
|
||||
)
|
||||
{
|
||||
var conditions = new List<FilterDefinition<BsonDocument>>();
|
||||
|
||||
if (subject is not null)
|
||||
conditions.Add(Builders<BsonDocument>.Filter.Eq("Thrower", subject));
|
||||
|
||||
if(filters is not null)
|
||||
if (valenceType is not null)
|
||||
conditions.Add(Builders<BsonDocument>.Filter.Eq("Valence", (int)valenceType.Value));
|
||||
|
||||
if (filters is not null)
|
||||
{
|
||||
Func<Constraint, string, object, FilterDefinition<BsonDocument>> createFilter = (Constraint c, string property, object value) =>
|
||||
{
|
||||
|
||||
@ -1,71 +1,3 @@
|
||||
@page "/ElementList"
|
||||
|
||||
@inject Salmon.Core.Instance Salmon;
|
||||
|
||||
<h3>Éléments</h3>
|
||||
|
||||
<div Style="display:flex;flex-wrap:wrap; height:100%;">
|
||||
@foreach(var e in Elements)
|
||||
{
|
||||
<Card Class="col-6" Style="width:18rem;margin:10px;">
|
||||
<CardHeader>
|
||||
<NavLink href=@($"Element/{System.Web.HttpUtility.UrlEncode(e.UniqueId)}")>
|
||||
<span class="oi oi-zoom-in" aria-hidden="true"></span>
|
||||
</NavLink>
|
||||
@e.LastType
|
||||
</CardHeader>
|
||||
<CardBody>
|
||||
<CardTitle>@e.ShortName</CardTitle>
|
||||
@if(!String.IsNullOrEmpty(e.LongName))
|
||||
{
|
||||
<CardSubTitle>
|
||||
@e.LongName
|
||||
</CardSubTitle>
|
||||
}
|
||||
<CardText>@e.Description</CardText>
|
||||
</CardBody>
|
||||
<ul class="list-group list-group-flush">
|
||||
@foreach(var kv in e.ImportantProperties())
|
||||
{
|
||||
<li class="list-group-item">@kv.Key: @kv.Value</li>
|
||||
}
|
||||
<li class="list-group-item"><small>id: @e.UniqueId</small></li>
|
||||
</ul>
|
||||
@if(Salmon.GetLastElementUpdate(e.UniqueId) is not null)
|
||||
{
|
||||
<CardFooter>
|
||||
<small class="text-muted">Last updated <i>@TimespanHelper.GetReadableTimespan(DateTime.Now - Salmon.GetLastElementUpdate(e.UniqueId).Value)</i></small>
|
||||
</CardFooter>
|
||||
}
|
||||
</Card>
|
||||
}
|
||||
</div>
|
||||
|
||||
@code {
|
||||
List<Element> Elements = new();
|
||||
private static System.Timers.Timer Time = new System.Timers.Timer(5000);
|
||||
|
||||
|
||||
protected async override Task OnInitializedAsync()
|
||||
{
|
||||
await base.OnInitializedAsync();
|
||||
|
||||
Time.Elapsed += async (Object? source, System.Timers.ElapsedEventArgs e) =>
|
||||
{
|
||||
await InvokeAsync(() => Refresh());
|
||||
};
|
||||
Time.AutoReset = true;
|
||||
Time.Enabled = true;
|
||||
|
||||
Refresh();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public void Refresh()
|
||||
{
|
||||
Elements = Salmon.GetAllElements().ToList();
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
<ElementDeck />
|
||||
@ -22,46 +22,13 @@ else
|
||||
<h3>@ThisElement.LongName</h3>
|
||||
|
||||
<h4>Propriétés</h4>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Dernier changement</th>
|
||||
<th>Nom</th>
|
||||
<th>Valeur</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@if (Triplets is not null)
|
||||
@foreach (var t in Triplets)
|
||||
{
|
||||
<tr>
|
||||
<td>@t.LastFlush</td>
|
||||
<td>@t.predicate</td>
|
||||
<td>@t.value</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
<TripletTable Triplets=@Triplets />
|
||||
|
||||
<h4>Enfants</h4>
|
||||
<ElementDeck FilterByParent=@Id />
|
||||
|
||||
<h4>Évènements</h4>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Date</th>
|
||||
<th>Type</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@if(Events is not null)
|
||||
@foreach (var e in Events)
|
||||
{
|
||||
<tr>
|
||||
<td>@e.When</td>
|
||||
<td>@e.Type</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
<EventTable Events=@Events />
|
||||
}
|
||||
|
||||
@code {
|
||||
@ -70,8 +37,8 @@ else
|
||||
string? Error = $"Chargement...";
|
||||
|
||||
Salmon.Core.Element? ThisElement = null;
|
||||
List<Triplet>? Triplets = null;
|
||||
List<Event>? Events = null;
|
||||
List<Triplet>? Triplets { get; set; } = null;
|
||||
List<Event>? Events { get; set; } = null;
|
||||
|
||||
|
||||
|
||||
@ -107,6 +74,8 @@ else
|
||||
events.Add(e);
|
||||
|
||||
Events = events;
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -15,9 +15,6 @@
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css" rel="stylesheet" />
|
||||
<link href="_content/Blazor.Bootstrap/blazor.bootstrap.css" rel="stylesheet" />
|
||||
|
||||
|
||||
|
||||
|
||||
<link rel="stylesheet" href="css/bootstrap/bootstrap.min.css" />
|
||||
<link href="css/site.css" rel="stylesheet" />
|
||||
<link href="Salmon.Web.styles.css" rel="stylesheet" />
|
||||
@ -47,6 +44,17 @@
|
||||
|
||||
|
||||
|
||||
|
||||
<script>
|
||||
window.clipboardCopy = {
|
||||
copyText: function (text) {
|
||||
navigator.clipboard.writeText(text).then(function () {
|
||||
//alert("Copied to clipboard!");
|
||||
})
|
||||
.catch(function (error) {
|
||||
alert(error);
|
||||
});
|
||||
}
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@ -6,6 +6,8 @@ using System.Text.Json.Serialization;
|
||||
|
||||
Salmon.Core.Instance CoreInstance;
|
||||
|
||||
Salmon.Model.Monitor.Drive _;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
builder.Services
|
||||
.AddControllers()
|
||||
|
||||
@ -10,6 +10,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Blazor.Bootstrap" Version="2.1.0" />
|
||||
<PackageReference Include="FontAwesome" Version="4.7.0" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.18.1" />
|
||||
<PackageReference Include="MongoDB.Driver" Version="2.25.0" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
<div class="top-row ps-3 navbar navbar-dark">
|
||||
<div class="container-fluid">
|
||||
<img src="favicon.png" style="width:32px; height:32px;" />
|
||||
<a class="navbar-brand" href="">Salmon.Web</a>
|
||||
<button title="Navigation menu" class="navbar-toggler" @onclick="ToggleNavMenu">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
@ -24,16 +25,6 @@
|
||||
<span class="oi oi-home" aria-hidden="true"></span> Event List
|
||||
</NavLink>
|
||||
</div>
|
||||
<div class="nav-item px-3">
|
||||
<NavLink class="nav-link" href="counter">
|
||||
<span class="oi oi-plus" aria-hidden="true"></span> Counter
|
||||
</NavLink>
|
||||
</div>
|
||||
<div class="nav-item px-3">
|
||||
<NavLink class="nav-link" href="fetchdata">
|
||||
<span class="oi oi-list-rich" aria-hidden="true"></span> Fetch data
|
||||
</NavLink>
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
@using Microsoft.JSInterop
|
||||
@using Salmon.Web
|
||||
@using Salmon.Web.Shared
|
||||
@using Salmon.Web.Components
|
||||
|
||||
@using Salmon.Core;
|
||||
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 804 KiB |
Loading…
Reference in New Issue
Block a user