|
1 | 1 | @typeparam TItem where TItem : notnull |
2 | 2 | @implements IDisposable |
| 3 | +@using System.Globalization |
3 | 4 |
|
4 | 5 | @{ |
5 | 6 | PagedNodesResult pagedNodes = GetPagedNodes(); |
|
16 | 17 | else |
17 | 18 | { |
18 | 19 | <label class="d-inline-flex align-items-center gap-2 small text-muted"> |
19 | | - <span>Rows per page</span> |
| 20 | + <span>@ResolvedRowsPerPageLabel</span> |
20 | 21 | <select class="form-select form-select-sm w-auto" value="@PaginationPageSize" @onchange="OnPageSizeChanged"> |
21 | 22 | @foreach (int option in EffectivePageSizeOptions) |
22 | 23 | { |
23 | | - <option value="@option">@(option == 0 ? "All" : option.ToString())</option> |
| 24 | + <option value="@option">@(option == 0 ? ResolvedAllItemsLabel : option.ToString(CultureInfo.CurrentCulture))</option> |
24 | 25 | } |
25 | 26 | </select> |
26 | 27 | </label> |
|
37 | 38 | else |
38 | 39 | { |
39 | 40 | <div class="@GetToolbarContainerClass()"> |
40 | | - <input class="form-control form-control-md" placeholder="@SearchPlaceholder" value="@SearchText" @oninput="OnSearchInput" @onkeyup="HandleSearchKeyPress" /> |
| 41 | + <input class="form-control form-control-md" placeholder="@ResolvedSearchPlaceholder" value="@SearchText" @oninput="OnSearchInput" @onkeyup="HandleSearchKeyPress" /> |
41 | 42 |
|
42 | 43 | @if (string.IsNullOrWhiteSpace(SearchText)) |
43 | 44 | { |
|
102 | 103 | RowLeadingContentTemplate="RowLeadingContentTemplate" |
103 | 104 | RowTemplate="RowTemplate" |
104 | 105 | RowTemplateSelector="RowTemplateSelector" |
105 | | - ExpandLabel="ExpandLabel" |
106 | | - CollapseLabel="CollapseLabel" /> |
| 106 | + ExpandLabel="ResolvedExpandLabel" |
| 107 | + CollapseLabel="ResolvedCollapseLabel" /> |
107 | 108 | } |
108 | 109 | </tbody> |
109 | 110 | </table> |
|
112 | 113 | @if (HiddenColumns.Count > 0) |
113 | 114 | { |
114 | 115 | <div class="mt-2 ps-2 py-1"> |
115 | | - <small class="text-muted me-2">Hidden columns:</small> |
| 116 | + <small class="text-muted me-2">@ResolvedHiddenColumnsLabel</small> |
116 | 117 | @foreach (string key in HiddenColumns) |
117 | 118 | { |
118 | 119 | FancyColumn<TItem>? column = Columns.FirstOrDefault(c => c.Key == key); |
|
148 | 149 |
|
149 | 150 | @if (pagedNodes.Context.PageCount > 1) |
150 | 151 | { |
151 | | - <div class="btn-group btn-group-sm" role="group" aria-label="Pagination"> |
| 152 | + <div class="btn-group btn-group-sm" role="group" aria-label="@ResolvedPaginationAriaLabel"> |
152 | 153 | <button type="button" |
153 | 154 | class="btn btn-outline-secondary" |
154 | 155 | disabled="@(!pagedNodes.Context.HasPreviousPage)" |
155 | 156 | @onclick="pagedNodes.Context.GoToPreviousPage"> |
156 | | - Previous |
| 157 | + @ResolvedPreviousPageLabel |
157 | 158 | </button> |
158 | 159 | @foreach (int pageNumber in GetVisiblePageNumbers(pagedNodes.Context)) |
159 | 160 | { |
|
167 | 168 | class="btn btn-outline-secondary" |
168 | 169 | disabled="@(!pagedNodes.Context.HasNextPage)" |
169 | 170 | @onclick="pagedNodes.Context.GoToNextPage"> |
170 | | - Next |
| 171 | + @ResolvedNextPageLabel |
171 | 172 | </button> |
172 | 173 | </div> |
173 | 174 | } |
|
191 | 192 | public Func<TItem, bool>? HasChildrenSelector { get; set; } |
192 | 193 |
|
193 | 194 | [Parameter] |
194 | | - public string SearchPlaceholder { get; set; } = "Search"; |
195 | | - |
196 | | - [Parameter] |
197 | | - public string ExpandLabel { get; set; } = "Expand"; |
198 | | - |
199 | | - [Parameter] |
200 | | - public string CollapseLabel { get; set; } = "Collapse"; |
| 195 | + public FancyTableTexts? Texts { get; set; } |
201 | 196 |
|
202 | 197 | [Parameter] |
203 | 198 | public RenderFragment? ToolbarTemplate { get; set; } |
|
286 | 281 | private int paginationPageSize = 25; |
287 | 282 | private bool paginationStateInitialized; |
288 | 283 |
|
| 284 | + private FancyTableTexts ResolvedTexts => Texts ?? FancyTableTexts.Default; |
| 285 | + private string ResolvedSearchPlaceholder => ResolvedTexts.SearchPlaceholder; |
| 286 | + private string ResolvedRowsPerPageLabel => ResolvedTexts.RowsPerPageLabel; |
| 287 | + private string ResolvedAllItemsLabel => ResolvedTexts.AllItemsLabel; |
| 288 | + private string ResolvedHiddenColumnsLabel => ResolvedTexts.HiddenColumnsLabel; |
| 289 | + private string ResolvedPaginationAriaLabel => ResolvedTexts.PaginationAriaLabel; |
| 290 | + private string ResolvedPreviousPageLabel => ResolvedTexts.PreviousPageLabel; |
| 291 | + private string ResolvedNextPageLabel => ResolvedTexts.NextPageLabel; |
| 292 | + private string ResolvedExpandLabel => ResolvedTexts.ExpandLabel; |
| 293 | + private string ResolvedCollapseLabel => ResolvedTexts.CollapseLabel; |
| 294 | + |
289 | 295 | private IEnumerable<FancyColumn<TItem>> VisibleColumns => |
290 | 296 | Columns.Where(c => !HiddenColumns.Contains(c.Key)); |
291 | 297 |
|
|
432 | 438 | visibleNodes.Add(node); |
433 | 439 |
|
434 | 440 | if (!node.IsExpanded) |
| 441 | + { |
435 | 442 | return; |
| 443 | + } |
436 | 444 |
|
437 | 445 | foreach (TreeNodeState<TItem> child in node.Children) |
| 446 | + { |
438 | 447 | CollectExpandedNodes(child, visibleNodes); |
| 448 | + } |
439 | 449 | } |
440 | 450 |
|
441 | 451 | private bool CollectSearchNodes( |
|
456 | 466 |
|
457 | 467 | includeNode = matchesSelf || childMatches.Count > 0; |
458 | 468 | if (!includeNode) |
| 469 | + { |
459 | 470 | return false; |
| 471 | + } |
460 | 472 |
|
461 | 473 | visibleNodes.Insert(insertIndex, node); |
462 | 474 | visibleNodes.AddRange(childMatches); |
|
466 | 478 | private void SortBy(string columnKey) |
467 | 479 | { |
468 | 480 | if (SortColumnKey == columnKey) |
| 481 | + { |
469 | 482 | SortAscending = !SortAscending; |
| 483 | + } |
470 | 484 | else |
471 | 485 | { |
472 | 486 | SortColumnKey = columnKey; |
|
478 | 492 |
|
479 | 493 | private string GetSortIcon(string key) |
480 | 494 | { |
481 | | - if (SortColumnKey != key) return "bi-arrow-down-up"; |
| 495 | + if (SortColumnKey != key) |
| 496 | + { |
| 497 | + return "bi-arrow-down-up"; |
| 498 | + } |
| 499 | + |
482 | 500 | return SortAscending ? "bi-sort-up" : "bi-sort-down"; |
483 | 501 | } |
484 | 502 |
|
485 | 503 | private void HideColumn(string key) => HiddenColumns.Add(key); |
| 504 | + |
486 | 505 | private void ShowColumn(string key) => HiddenColumns.Remove(key); |
487 | 506 |
|
488 | 507 | private Task ToggleNodeAsync(TreeNodeState<TItem> node) |
|
742 | 761 | { |
743 | 762 | if (context.FilteredItemCount == 0) |
744 | 763 | { |
745 | | - return context.TotalItemCount == 0 ? "No rows" : $"No matching rows ({context.TotalItemCount} total root items)"; |
| 764 | + return context.TotalItemCount == 0 |
| 765 | + ? ResolvedTexts.NoRowsLabel |
| 766 | + : FormatResolvedText(ResolvedTexts.NoMatchingRootItemsFormat, context.TotalItemCount); |
746 | 767 | } |
747 | 768 |
|
748 | 769 | return context.FilteredItemCount == context.TotalItemCount |
749 | | - ? $"Showing {context.StartItemIndex}-{context.EndItemIndex} of {context.FilteredItemCount}" |
750 | | - : $"Showing {context.StartItemIndex}-{context.EndItemIndex} of {context.FilteredItemCount} visible rows"; |
| 770 | + ? FormatResolvedText(ResolvedTexts.ShowingItemsFormat, context.StartItemIndex, context.EndItemIndex, context.FilteredItemCount) |
| 771 | + : FormatResolvedText(ResolvedTexts.ShowingVisibleRowsFormat, context.StartItemIndex, context.EndItemIndex, context.FilteredItemCount); |
751 | 772 | } |
752 | 773 |
|
753 | 774 | private IReadOnlyList<int> GetVisiblePageNumbers(FancyPaginationContext<TItem> context) |
|
779 | 800 | private static string CombineClasses(string baseClass, string? additionalClass) => |
780 | 801 | string.IsNullOrWhiteSpace(additionalClass) ? baseClass : $"{baseClass} {additionalClass}"; |
781 | 802 |
|
| 803 | + private static string FormatResolvedText(string format, params object[] args) => |
| 804 | + string.Format(CultureInfo.CurrentCulture, format, args); |
| 805 | + |
782 | 806 | private sealed class PagedNodesResult |
783 | 807 | { |
784 | 808 | public required IReadOnlyList<TreeNodeState<TItem>> Items { get; init; } |
|
794 | 818 |
|
795 | 819 | public void Dispose() => debounceTimer?.Dispose(); |
796 | 820 | } |
797 | | - |
798 | | - |
|
0 commit comments