AyCode.Blazor/AyCode.Blazor.Components/Components/Grids/MgGridWithInfoPanel.razor

210 lines
5.7 KiB
Plaintext

@using DevExpress.Blazor
@inject Microsoft.JSInterop.IJSRuntime JSRuntime
<CascadingValue Value="this">
@if (_isFullscreen)
{
<div class="mg-fullscreen-overlay">
<div class="mg-fullscreen-header">
<span class="mg-fullscreen-title">@(_currentGrid?.Caption ?? "Grid")</span>
<button type="button" class="btn-close btn-close-white" aria-label="Close" @onclick="ExitFullscreen"></button>
</div>
<div class="mg-fullscreen-body">
@RenderMainContent()
</div>
</div>
}
else
{
@RenderMainContent()
}
</CascadingValue>
@code {
private IInfoPanelBase? _infoPanelInstance;
private IMgGridBase? _currentGrid;
private bool _isFullscreen;
private string _currentInfoPanelSize = "400px";
private bool _sizeLoaded;
/// <summary>
/// The grid content to display in the left pane
/// </summary>
[Parameter]
public RenderFragment? GridContent { get; set; }
/// <summary>
/// InfoPanel content (e.g., GridShippingDocumentInfoPanel) to display in the right pane.
/// If not set, the default MgGridInfoPanel is used.
/// </summary>
[Parameter]
public RenderFragment? ChildContent { get; set; }
/// <summary>
/// Initial size of the InfoPanel pane. Default is "400px".
/// </summary>
[Parameter]
public string InfoPanelSize { get; set; } = "400px";
/// <summary>
/// Whether to show the InfoPanel. Default is true.
/// </summary>
[Parameter]
public bool ShowInfoPanel { get; set; } = true;
/// <summary>
/// Whether the wrapper is currently in fullscreen mode
/// </summary>
public bool IsFullscreen => _isFullscreen;
/// <summary>
/// Gets or sets the InfoPanel instance for grid-InfoPanel communication
/// </summary>
public IInfoPanelBase? InfoPanelInstance
{
get => _infoPanelInstance;
set => _infoPanelInstance = value;
}
/// <summary>
/// Registers an InfoPanel instance (called by child InfoPanel components)
/// </summary>
public void RegisterInfoPanel(IInfoPanelBase infoPanel)
{
_infoPanelInstance = infoPanel;
}
/// <summary>
/// Registers the grid instance (called by MgGridBase)
/// </summary>
public void RegisterGrid(IMgGridBase grid)
{
_currentGrid = grid;
// Load saved size when grid is registered
if (!_sizeLoaded)
{
_ = LoadSavedSizeAsync();
}
}
/// <summary>
/// Toggles fullscreen mode
/// </summary>
public void ToggleFullscreen()
{
_isFullscreen = !_isFullscreen;
StateHasChanged();
}
/// <summary>
/// Enters fullscreen mode
/// </summary>
public void EnterFullscreen()
{
_isFullscreen = true;
StateHasChanged();
}
/// <summary>
/// Exits fullscreen mode
/// </summary>
public void ExitFullscreen()
{
_isFullscreen = false;
StateHasChanged();
}
private string GetStorageKey() => _currentGrid != null
? $"Splitter_{_currentGrid.LayoutStorageKey}"
: null!;
private async Task LoadSavedSizeAsync()
{
if (_currentGrid == null) return;
try
{
var storageKey = GetStorageKey();
var savedSize = await JSRuntime.InvokeAsync<string>("localStorage.getItem", storageKey);
if (!string.IsNullOrWhiteSpace(savedSize))
{
_currentInfoPanelSize = savedSize;
_sizeLoaded = true;
await InvokeAsync(StateHasChanged);
}
else
{
_currentInfoPanelSize = InfoPanelSize;
_sizeLoaded = true;
}
}
catch
{
// Mute exceptions for the server prerender stage
_currentInfoPanelSize = InfoPanelSize;
_sizeLoaded = true;
}
}
private async Task SaveSizeAsync(string size)
{
if (_currentGrid == null) return;
try
{
var storageKey = GetStorageKey();
await JSRuntime.InvokeVoidAsync("localStorage.setItem", storageKey, size);
}
catch
{
// Mute exceptions for the server prerender stage
}
}
private async Task OnInfoPanelSizeChanged(string newSize)
{
_currentInfoPanelSize = newSize;
await SaveSizeAsync(newSize);
}
protected override void OnParametersSet()
{
if (!_sizeLoaded)
{
_currentInfoPanelSize = InfoPanelSize;
}
base.OnParametersSet();
}
private RenderFragment RenderMainContent() => __builder =>
{
if (ShowInfoPanel)
{
<DxSplitter Width="100%" Height="@(_isFullscreen ? "100%" : null)" CssClass="mg-grid-with-info-panel" Orientation="Orientation.Horizontal">
<Panes>
<DxSplitterPane>
@GridContent
</DxSplitterPane>
<DxSplitterPane Size="@_currentInfoPanelSize" MinSize="0px" MaxSize="100%" AllowCollapse="false" CssClass="mg-info-panel-pane"
SizeChanged="OnInfoPanelSizeChanged">
@if (ChildContent != null)
{
@ChildContent
}
else
{
<MgGridInfoPanel />
}
</DxSplitterPane>
</Panes>
</DxSplitter>
}
else
{
@GridContent
}
};
}