|
4 | 4 | @using Quartz |
5 | 5 | @using Humanizer |
6 | 6 | @using NBitcoin |
| 7 | +@using Blazorise.Components |
7 | 8 | @using NodeGuard.Jobs |
8 | 9 | @using Google.Protobuf |
9 | 10 | @using NBXplorer.Models |
|
287 | 288 | </Tooltip> |
288 | 289 | </h3> |
289 | 290 | <br/> |
| 291 | +<Row Class="mb-3"> |
| 292 | + <Column ColumnSize="ColumnSize.Is1"> |
| 293 | + <Field> |
| 294 | + <FieldLabel>Status</FieldLabel> |
| 295 | + <Autocomplete TItem="ChannelOperationRequestStatus?" |
| 296 | + TValue="ChannelOperationRequestStatus?" |
| 297 | + Data="@_statusOptions" |
| 298 | + TextField="@(item => item?.Humanize() ?? "All")" |
| 299 | + ValueField="@(item => item)" |
| 300 | + @bind-SelectedValue="@_statusFilter" |
| 301 | + @bind-SelectedValue:after="OnFiltersChanged" |
| 302 | + Placeholder="All" |
| 303 | + FreeTyping="false" |
| 304 | + MinLength="0" /> |
| 305 | + </Field> |
| 306 | + </Column> |
| 307 | + <Column ColumnSize="ColumnSize.Is1"> |
| 308 | + <Field> |
| 309 | + <FieldLabel>Type</FieldLabel> |
| 310 | + <Autocomplete TItem="OperationRequestType?" |
| 311 | + TValue="OperationRequestType?" |
| 312 | + Data="@_requestTypeOptions" |
| 313 | + TextField="@(item => item?.Humanize() ?? "All")" |
| 314 | + ValueField="@(item => item)" |
| 315 | + @bind-SelectedValue="@_requestTypeFilter" |
| 316 | + @bind-SelectedValue:after="OnFiltersChanged" |
| 317 | + Placeholder="All" |
| 318 | + FreeTyping="false" |
| 319 | + MinLength="0" /> |
| 320 | + </Field> |
| 321 | + </Column> |
| 322 | + <Column ColumnSize="ColumnSize.Is2"> |
| 323 | + <Field> |
| 324 | + <FieldLabel>Source Node</FieldLabel> |
| 325 | + <Autocomplete TItem="Node" |
| 326 | + TValue="int?" |
| 327 | + Data="@_availableNodes" |
| 328 | + TextField="@(item => item?.Name ?? "All")" |
| 329 | + ValueField="@(item => (int?)item?.Id)" |
| 330 | + @bind-SelectedValue="@_sourceNodeFilter" |
| 331 | + @bind-SelectedValue:after="OnFiltersChanged" |
| 332 | + Placeholder="All" |
| 333 | + FreeTyping="false" |
| 334 | + MinLength="0" /> |
| 335 | + </Field> |
| 336 | + </Column> |
| 337 | + <Column ColumnSize="ColumnSize.Is2"> |
| 338 | + <Field> |
| 339 | + <FieldLabel>Dest Node</FieldLabel> |
| 340 | + <Autocomplete TItem="Node" |
| 341 | + TValue="int?" |
| 342 | + Data="@_availableNodes" |
| 343 | + TextField="@(item => item?.Name ?? "All")" |
| 344 | + ValueField="@(item => (int?)item?.Id)" |
| 345 | + @bind-SelectedValue="@_destNodeFilter" |
| 346 | + @bind-SelectedValue:after="OnFiltersChanged" |
| 347 | + Placeholder="All" |
| 348 | + FreeTyping="false" |
| 349 | + MinLength="0" /> |
| 350 | + </Field> |
| 351 | + </Column> |
| 352 | + <Column ColumnSize="ColumnSize.Is2"> |
| 353 | + <Field> |
| 354 | + <FieldLabel>Wallet</FieldLabel> |
| 355 | + <Autocomplete TItem="Wallet" |
| 356 | + TValue="int?" |
| 357 | + Data="@_allWallets" |
| 358 | + TextField="@(item => item?.Name ?? "All")" |
| 359 | + ValueField="@(item => (int?)item?.Id)" |
| 360 | + @bind-SelectedValue="@_walletFilter" |
| 361 | + @bind-SelectedValue:after="OnFiltersChanged" |
| 362 | + Placeholder="All" |
| 363 | + FreeTyping="false" |
| 364 | + MinLength="0" /> |
| 365 | + </Field> |
| 366 | + </Column> |
| 367 | + <Column ColumnSize="ColumnSize.Is1"> |
| 368 | + <Field> |
| 369 | + <FieldLabel>User</FieldLabel> |
| 370 | + <Autocomplete TItem="ApplicationUser" |
| 371 | + TValue="string?" |
| 372 | + Data="@_availableUsers" |
| 373 | + TextField="@(item => item?.UserName ?? "All")" |
| 374 | + ValueField="@(item => item?.Id)" |
| 375 | + @bind-SelectedValue="@_userFilter" |
| 376 | + @bind-SelectedValue:after="OnFiltersChanged" |
| 377 | + Placeholder="All" |
| 378 | + FreeTyping="false" |
| 379 | + MinLength="0" /> |
| 380 | + </Field> |
| 381 | + </Column> |
| 382 | + <Column ColumnSize="ColumnSize.Is1"> |
| 383 | + <Field> |
| 384 | + <FieldLabel>From</FieldLabel> |
| 385 | + <DatePicker TValue="DateTime?" @bind-Date="@_fromDate" @bind-Date:after="OnFiltersChanged" InputMode="DateInputMode.Date" Placeholder="Start" /> |
| 386 | + </Field> |
| 387 | + </Column> |
| 388 | + <Column ColumnSize="ColumnSize.Is1"> |
| 389 | + <Field> |
| 390 | + <FieldLabel>To</FieldLabel> |
| 391 | + <DatePicker TValue="DateTime?" @bind-Date="@_toDate" @bind-Date:after="OnFiltersChanged" InputMode="DateInputMode.Date" Placeholder="End" /> |
| 392 | + </Field> |
| 393 | + </Column> |
| 394 | + <Column ColumnSize="ColumnSize.Is1" Class="d-flex align-items-end pb-3"> |
| 395 | + <Button Color="Color.Secondary" Clicked="ClearAllFilters"> |
| 396 | + <Icon Name="IconName.Times" /> Clear |
| 397 | + </Button> |
| 398 | + </Column> |
| 399 | +</Row> |
| 400 | +@* TODO: Convert this grid to paginated ReadData to avoid loading all records in memory. *@ |
290 | 401 | <DataGrid TItem="ChannelOperationRequest" |
291 | 402 | @ref="@_allRequestsDatagrid" |
292 | 403 | Data="@_allRequests" |
293 | | - Filterable="true" |
| 404 | + ReadData="@OnAllRequestsReadData" |
| 405 | + TotalItems="@_totalAllRequests" |
294 | 406 | ShowPager="true" |
295 | 407 | ShowPageSizes="true" |
296 | 408 | Striped="true"> |
|
455 | 567 | @inject IPriceConversionService PriceConversionService |
456 | 568 | @inject IAuditService AuditService |
457 | 569 | @inject IHttpContextAccessor HttpContextAccessor |
| 570 | +@inject IApplicationUserRepository ApplicationUserRepository |
458 | 571 |
|
459 | 572 | @code { |
460 | 573 | private List<ChannelOperationRequest>? _channelRequests; |
461 | 574 | private List<ChannelOperationRequest>? _allRequests; |
| 575 | + private int _totalAllRequests; |
| 576 | + private List<ApplicationUser> _availableUsers = new(); |
| 577 | + private List<Node> _availableNodes = new(); |
| 578 | + |
| 579 | + // Filter state |
| 580 | + private ChannelOperationRequestStatus? _statusFilter; |
| 581 | + private OperationRequestType? _requestTypeFilter; |
| 582 | + private int? _sourceNodeFilter; |
| 583 | + private int? _destNodeFilter; |
| 584 | + private int? _walletFilter; |
| 585 | + private string? _userFilter; |
| 586 | + private DateTime? _fromDate; |
| 587 | + private DateTime? _toDate; |
| 588 | + |
| 589 | + // Filter options |
| 590 | + private List<ChannelOperationRequestStatus?> _statusOptions = new() { null }; |
| 591 | + private List<OperationRequestType?> _requestTypeOptions = new() { null }; |
| 592 | + |
462 | 593 | private ChannelOperationRequest? _selectedRequest; |
463 | 594 | private ChannelOperationRequestStatus _selectedStatus; |
464 | 595 | private ChannelOperationRequest _selectedRequestForMarkingAsFailed; |
|
1136 | 1267 | private async Task RefreshChannelRequestsInformation() |
1137 | 1268 | { |
1138 | 1269 | await FetchRequests(); |
| 1270 | + if (_allRequestsDatagrid != null) |
| 1271 | + { |
| 1272 | + await _allRequestsDatagrid.Reload(); |
| 1273 | + } |
1139 | 1274 | StateHasChanged(); |
1140 | 1275 | } |
| 1276 | + |
| 1277 | + private async Task OnAllRequestsReadData(DataGridReadDataEventArgs<ChannelOperationRequest> e) |
| 1278 | + { |
| 1279 | + if (!e.CancellationToken.IsCancellationRequested) |
| 1280 | + { |
| 1281 | + var fromDateOffset = _fromDate.HasValue ? new DateTimeOffset(_fromDate.Value, TimeSpan.Zero) : (DateTimeOffset?)null; |
| 1282 | + var toDateOffset = _toDate.HasValue ? new DateTimeOffset(_toDate.Value.AddDays(1).AddSeconds(-1), TimeSpan.Zero) : (DateTimeOffset?)null; |
| 1283 | + |
| 1284 | + var excludedIds = _channelRequests?.Select(r => r.Id) ?? Enumerable.Empty<int>(); |
| 1285 | + |
| 1286 | + var (requests, totalCount) = await ChannelOperationRequestRepository.GetPaginatedAsync( |
| 1287 | + e.Page, |
| 1288 | + e.PageSize, |
| 1289 | + _statusFilter, |
| 1290 | + _requestTypeFilter, |
| 1291 | + _sourceNodeFilter, |
| 1292 | + _destNodeFilter, |
| 1293 | + _walletFilter, |
| 1294 | + _userFilter, |
| 1295 | + fromDateOffset, |
| 1296 | + toDateOffset, |
| 1297 | + excludedIds); |
| 1298 | + |
| 1299 | + _allRequests = requests; |
| 1300 | + _totalAllRequests = totalCount; |
| 1301 | + } |
| 1302 | + } |
| 1303 | + |
| 1304 | + private async Task OnFiltersChanged() |
| 1305 | + { |
| 1306 | + if (_allRequestsDatagrid != null) |
| 1307 | + { |
| 1308 | + await _allRequestsDatagrid.Reload(); |
| 1309 | + } |
| 1310 | + } |
| 1311 | + |
| 1312 | + private async Task ClearAllFilters() |
| 1313 | + { |
| 1314 | + _statusFilter = null; |
| 1315 | + _requestTypeFilter = null; |
| 1316 | + _sourceNodeFilter = null; |
| 1317 | + _destNodeFilter = null; |
| 1318 | + _walletFilter = null; |
| 1319 | + _userFilter = null; |
| 1320 | + _fromDate = null; |
| 1321 | + _toDate = null; |
| 1322 | + |
| 1323 | + if (_allRequestsDatagrid != null) |
| 1324 | + { |
| 1325 | + await _allRequestsDatagrid.Reload(); |
| 1326 | + } |
| 1327 | + } |
1141 | 1328 |
|
1142 | 1329 | private async Task OnChangelessChanged(bool value) |
1143 | 1330 | { |
|
0 commit comments