Compare commits
5 Commits
feat/timer
...
cdf225bad1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cdf225bad1 | ||
|
|
59e051f162 | ||
|
|
1352dda20e | ||
|
|
33b5b03bf4 | ||
|
|
6b986db62e |
@@ -1,28 +0,0 @@
|
||||
using DbFirst.Application.Time.Commands;
|
||||
using DbFirst.Domain.Entities;
|
||||
using MediatR;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace DbFirst.API.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/[controller]")]
|
||||
public class TimeController : ControllerBase
|
||||
{
|
||||
private readonly IMediator _mediator;
|
||||
|
||||
public TimeController(IMediator mediator)
|
||||
{
|
||||
_mediator = mediator;
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async Task<ActionResult<TimeRecord>> InsertAndGetLast(CancellationToken cancellationToken)
|
||||
{
|
||||
var result = await _mediator.Send(new InsertTimeCommand(), cancellationToken);
|
||||
if (result == null)
|
||||
return NotFound();
|
||||
|
||||
return Ok(result);
|
||||
}
|
||||
}
|
||||
@@ -54,7 +54,6 @@ builder.Services.AddApplication();
|
||||
builder.Services.AddScoped<ICatalogRepository, CatalogRepository>();
|
||||
builder.Services.AddScoped<IMassDataRepository, MassDataRepository>();
|
||||
builder.Services.AddScoped<ILayoutRepository, LayoutRepository>();
|
||||
builder.Services.AddScoped<ITimeRepository, TimeRepository>();
|
||||
|
||||
builder.Services.AddDevExpressControls();
|
||||
builder.Services.AddSignalR();
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
using DbFirst.Domain.Entities;
|
||||
|
||||
namespace DbFirst.Application.Repositories;
|
||||
|
||||
public interface ITimeRepository
|
||||
{
|
||||
Task InsertAsync(CancellationToken cancellationToken = default);
|
||||
Task<TimeRecord?> GetLastAsync(CancellationToken cancellationToken = default);
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
using DbFirst.Domain.Entities;
|
||||
using MediatR;
|
||||
|
||||
namespace DbFirst.Application.Time.Commands;
|
||||
|
||||
public record InsertTimeCommand : IRequest<TimeRecord?>;
|
||||
@@ -1,21 +0,0 @@
|
||||
using DbFirst.Application.Repositories;
|
||||
using DbFirst.Domain.Entities;
|
||||
using MediatR;
|
||||
|
||||
namespace DbFirst.Application.Time.Commands;
|
||||
|
||||
public class InsertTimeHandler : IRequestHandler<InsertTimeCommand, TimeRecord?>
|
||||
{
|
||||
private readonly ITimeRepository _repository;
|
||||
|
||||
public InsertTimeHandler(ITimeRepository repository)
|
||||
{
|
||||
_repository = repository;
|
||||
}
|
||||
|
||||
public async Task<TimeRecord?> Handle(InsertTimeCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
await _repository.InsertAsync(cancellationToken);
|
||||
return await _repository.GetLastAsync(cancellationToken);
|
||||
}
|
||||
}
|
||||
@@ -31,12 +31,6 @@
|
||||
<span class="bi bi-table-nav-menu" aria-hidden="true"></span> MassData
|
||||
</NavLink>
|
||||
</div>
|
||||
|
||||
<div class="nav-item px-3">
|
||||
<NavLink class="nav-link" href="clock">
|
||||
<span class="bi bi-clock-nav-menu" aria-hidden="true"></span> Clock
|
||||
</NavLink>
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,100 +0,0 @@
|
||||
@rendermode InteractiveServer
|
||||
@page "/clock"
|
||||
@inject TimeApiClient TimeApi
|
||||
@implements IAsyncDisposable
|
||||
|
||||
<PageTitle>Clock</PageTitle>
|
||||
|
||||
<h3>DB Server Clock</h3>
|
||||
|
||||
<div class="clock-wrapper">
|
||||
<div class="clock-display @(_error != null ? "clock-error" : "")">
|
||||
@if (_dbTime.HasValue)
|
||||
{
|
||||
<span class="clock-time">@_dbTime.Value.ToString("HH:mm:ss")</span>
|
||||
<span class="clock-date">@_dbTime.Value.ToString("dd.MM.yyyy")</span>
|
||||
}
|
||||
else if (_error != null)
|
||||
{
|
||||
<span class="clock-time">--:--:--</span>
|
||||
<span class="clock-date text-danger">@_error</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span class="clock-time">...</span>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.clock-wrapper {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 40vh;
|
||||
}
|
||||
|
||||
.clock-display {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
background: var(--bs-body-bg, #1e1e2e);
|
||||
border: 2px solid var(--bs-border-color, #444);
|
||||
border-radius: 1rem;
|
||||
padding: 2rem 4rem;
|
||||
box-shadow: 0 4px 24px rgba(0,0,0,0.3);
|
||||
}
|
||||
|
||||
.clock-time {
|
||||
font-size: 5rem;
|
||||
font-weight: 700;
|
||||
font-variant-numeric: tabular-nums;
|
||||
letter-spacing: 0.1em;
|
||||
color: var(--bs-primary, #0d6efd);
|
||||
}
|
||||
|
||||
.clock-date {
|
||||
font-size: 1.4rem;
|
||||
margin-top: 0.5rem;
|
||||
opacity: 0.75;
|
||||
}
|
||||
|
||||
.clock-error .clock-time {
|
||||
color: var(--bs-danger, #dc3545);
|
||||
}
|
||||
</style>
|
||||
|
||||
@code {
|
||||
private DateTime? _dbTime;
|
||||
private string? _error;
|
||||
private Timer? _timer;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await TickAsync();
|
||||
_timer = new Timer(async _ =>
|
||||
{
|
||||
await TickAsync();
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}, null, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1));
|
||||
}
|
||||
|
||||
private async Task TickAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
_dbTime = await TimeApi.InsertAndGetLastAsync();
|
||||
_error = null;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_error = ex.Message;
|
||||
}
|
||||
}
|
||||
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
if (_timer != null)
|
||||
await _timer.DisposeAsync();
|
||||
}
|
||||
}
|
||||
@@ -31,10 +31,6 @@ if (!string.IsNullOrWhiteSpace(apiBaseUrl))
|
||||
{
|
||||
client.BaseAddress = new Uri(apiBaseUrl);
|
||||
});
|
||||
builder.Services.AddHttpClient<TimeApiClient>(client =>
|
||||
{
|
||||
client.BaseAddress = new Uri(apiBaseUrl);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -42,7 +38,6 @@ else
|
||||
builder.Services.AddHttpClient<DashboardApiClient>();
|
||||
builder.Services.AddHttpClient<MassDataApiClient>();
|
||||
builder.Services.AddHttpClient<LayoutApiClient>();
|
||||
builder.Services.AddHttpClient<TimeApiClient>();
|
||||
}
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
using System.Net.Http.Json;
|
||||
|
||||
namespace DbFirst.BlazorWebApp.Services;
|
||||
|
||||
public class TimeApiClient
|
||||
{
|
||||
private readonly HttpClient _httpClient;
|
||||
private const string Endpoint = "api/time";
|
||||
|
||||
public TimeApiClient(HttpClient httpClient)
|
||||
{
|
||||
_httpClient = httpClient;
|
||||
}
|
||||
|
||||
public async Task<DateTime?> InsertAndGetLastAsync()
|
||||
{
|
||||
var response = await _httpClient.PostAsync(Endpoint, null);
|
||||
response.EnsureSuccessStatusCode();
|
||||
var result = await response.Content.ReadFromJsonAsync<TimeResponse>();
|
||||
return result?.Now;
|
||||
}
|
||||
|
||||
private sealed class TimeResponse
|
||||
{
|
||||
public DateTime? Now { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
namespace DbFirst.Domain.Entities;
|
||||
|
||||
public class TimeRecord
|
||||
{
|
||||
public DateTime? Now { get; set; }
|
||||
}
|
||||
@@ -16,7 +16,6 @@ public partial class ApplicationDbContext : DbContext
|
||||
|
||||
public virtual DbSet<VwmyCatalog> VwmyCatalogs { get; set; }
|
||||
public virtual DbSet<SmfLayout> SmfLayouts { get; set; }
|
||||
public virtual DbSet<TimeRecord> Times { get; set; }
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
@@ -84,16 +83,6 @@ public partial class ApplicationDbContext : DbContext
|
||||
.HasColumnName("CHANGED_WHEN");
|
||||
});
|
||||
|
||||
modelBuilder.Entity<TimeRecord>(entity =>
|
||||
{
|
||||
entity.HasNoKey();
|
||||
entity.ToTable("TIME");
|
||||
|
||||
entity.Property(e => e.Now)
|
||||
.HasColumnType("datetime")
|
||||
.HasColumnName("NOW");
|
||||
});
|
||||
|
||||
OnModelCreatingPartial(modelBuilder);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
using DbFirst.Application.Repositories;
|
||||
using DbFirst.Domain.Entities;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace DbFirst.Infrastructure.Repositories;
|
||||
|
||||
public class TimeRepository : ITimeRepository
|
||||
{
|
||||
private readonly ApplicationDbContext _db;
|
||||
|
||||
public TimeRepository(ApplicationDbContext db)
|
||||
{
|
||||
_db = db;
|
||||
}
|
||||
|
||||
public async Task InsertAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
await _db.Database.ExecuteSqlRawAsync("INSERT INTO [TIME] (NOW) VALUES (GETDATE())", cancellationToken);
|
||||
}
|
||||
|
||||
public async Task<TimeRecord?> GetLastAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
return await _db.Times
|
||||
.AsNoTracking()
|
||||
.OrderByDescending(t => t.Now)
|
||||
.FirstOrDefaultAsync(cancellationToken);
|
||||
}
|
||||
}
|
||||
1157
docs/PROJEKTDOKUMENTATION.md
Normal file
1157
docs/PROJEKTDOKUMENTATION.md
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user