-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
🆕 feat: test GetRelativeUriWithQueryParameters
- Loading branch information
Showing
9 changed files
with
346 additions
and
9 deletions.
There are no files selected for viewing
56 changes: 56 additions & 0 deletions
56
src/MASA.OfficialWebsite.WebApp/Components/InteractiveTrigger/MInteractivePopup2.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
using BlazorComponent; | ||
using Microsoft.AspNetCore.Components; | ||
using Microsoft.JSInterop; | ||
|
||
namespace Masa.Blazor; | ||
|
||
/// <summary> | ||
/// A abstract class for components that use the <see cref="MInteractiveTrigger{TValue}"/> | ||
/// or <see cref="MInteractiveTriggers{TValue}"/> component as a trigger. | ||
/// </summary> | ||
public abstract class MInteractivePopup : ComponentBase, IOutsideClickJsCallback, IAsyncDisposable | ||
{ | ||
[Inject] private OutsideClickJSModule OutsideClickJSModule { get; set; } = null!; | ||
|
||
[Inject] protected NavigationManager NavigationManager { get; set; } = null!; | ||
|
||
/// <summary> | ||
/// The query name of url for trigger a interactive popup. | ||
/// </summary> | ||
[Parameter] public string QueryName { get; set; } = null!; | ||
|
||
/// <summary> | ||
/// The activator selector. | ||
/// </summary> | ||
[Parameter] public string Activator { get; set; } = null!; | ||
|
||
protected override async Task OnAfterRenderAsync(bool firstRender) | ||
{ | ||
if (firstRender) | ||
{ | ||
await OutsideClickJSModule.InitializeAsync(this, Activator, ".m-interactive-trigger__popup"); | ||
} | ||
} | ||
|
||
public async Task HandleOnOutsideClickAsync() | ||
{ | ||
// TODO: https://github.com/dotnet/aspnetcore/issues/52705 | ||
await Task.Delay(100); | ||
NavigationManager.NavigateWithQueryParameter(QueryName, (string?)null); | ||
} | ||
|
||
async ValueTask IAsyncDisposable.DisposeAsync() | ||
{ | ||
try | ||
{ | ||
await DisposeAsync(); | ||
await OutsideClickJSModule.UnbindAndDisposeAsync(); | ||
} | ||
catch (JSDisconnectedException) | ||
{ | ||
// ignore | ||
} | ||
} | ||
|
||
protected virtual Task DisposeAsync() => Task.CompletedTask; | ||
} |
24 changes: 24 additions & 0 deletions
24
src/MASA.OfficialWebsite.WebApp/Components/InteractiveTrigger/MInteractiveTrigger2.razor
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
@namespace Masa.Blazor | ||
@typeparam TValue | ||
@using Microsoft.AspNetCore.Components.Rendering | ||
@inherits MInteractiveTriggerBase2<TValue, TValue> | ||
|
||
@base.BuildRenderTree | ||
|
||
@code { | ||
|
||
protected override string ComponentName => nameof(MInteractiveTrigger<TValue>); | ||
|
||
protected override void RenderLinkContent(RenderTreeBuilder __builder) | ||
{ | ||
var value = IsInteractive ? default : InteractiveValue; | ||
|
||
@RenderSingleLink(QueryName, value, InteractiveValue) | ||
} | ||
|
||
protected override bool CheckInteractive() | ||
{ | ||
return EqualityComparer<TValue>.Default.Equals(QueryValue, InteractiveValue); | ||
} | ||
|
||
} |
52 changes: 52 additions & 0 deletions
52
src/MASA.OfficialWebsite.WebApp/Components/InteractiveTrigger/MInteractiveTriggerBase2.razor
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
@namespace Masa.Blazor | ||
@using Microsoft.AspNetCore.Components.Rendering | ||
@inherits CssProviderComponentBase | ||
@typeparam TValue | ||
@typeparam TInteractiveValue | ||
@inject NavigationManager NavigationManager | ||
|
||
<div class="@CssProvider.GetClass()" | ||
style="@CssProvider.GetStyle()" | ||
id="@ElementId"> | ||
@RenderLinkContent | ||
@RenderPopupContent | ||
</div> | ||
|
||
@code { | ||
|
||
protected abstract void RenderLinkContent(RenderTreeBuilder __builder); | ||
|
||
protected RenderFragment RenderSingleLink(string name, TValue? value, TValue? interactiveValue) => __builder => | ||
{ | ||
<a class="@CssProvider.GetClass("link")" | ||
style="@CssProvider.GetStyle("link")" | ||
href="@NavigationManager.GetRelativeUriWithQueryParameters(new Dictionary<string, object?>() { { name, value } })"> | ||
@ChildContent?.Invoke(interactiveValue) | ||
</a> | ||
}; | ||
|
||
private void RenderPopupContent(RenderTreeBuilder __builder) | ||
{ | ||
@if (WithPopup) | ||
{ | ||
<div class="@CssProvider.GetClass("popup")" | ||
style="@CssProvider.GetStyle("popup")"> | ||
@RenderInteractiveComponent | ||
</div> | ||
} | ||
else | ||
{ | ||
@RenderInteractiveComponent | ||
} | ||
} | ||
|
||
private void RenderInteractiveComponent(RenderTreeBuilder __builder) | ||
{ | ||
@if (IsInteractive) | ||
{ | ||
<DynamicComponent Type="@InteractiveComponentType" | ||
Parameters="@ComputedInteractiveComponentParameters" /> | ||
} | ||
} | ||
|
||
} |
141 changes: 141 additions & 0 deletions
141
...SA.OfficialWebsite.WebApp/Components/InteractiveTrigger/MInteractiveTriggerBase2.razor.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
using BlazorComponent; | ||
using Microsoft.AspNetCore.Components; | ||
|
||
namespace Masa.Blazor; | ||
|
||
using BemIt; | ||
|
||
/// <summary> | ||
/// A abstract class of interactive trigger component. | ||
/// </summary> | ||
/// <typeparam name="TValue"></typeparam> | ||
/// <typeparam name="TInteractiveValue"></typeparam> | ||
|
||
#if NET8_0_OR_GREATER | ||
[StreamRendering] | ||
#endif | ||
|
||
public abstract partial class MInteractiveTriggerBase2<TValue, TInteractiveValue> : CssProviderComponentBase | ||
{ | ||
[Parameter] public bool DisableLinkOnInteractive { get; set; } | ||
|
||
/// <summary> | ||
/// The name of query parameter. | ||
/// </summary> | ||
[Parameter] [EditorRequired] public string QueryName { get; set; } = null!; | ||
|
||
/// <summary> | ||
/// The value of query parameter. | ||
/// </summary> | ||
[Parameter] public TValue? QueryValue { get; set; } | ||
|
||
/// <summary> | ||
/// A value that is used to determine whether the component is interactive. | ||
/// </summary> | ||
[Parameter] [EditorRequired] public virtual TInteractiveValue InteractiveValue { get; set; } = default!; | ||
|
||
/// <summary> | ||
/// The <see cref="Type"/> of interactive component. | ||
/// </summary> | ||
[Parameter] [EditorRequired] public Type InteractiveComponentType { get; set; } = null!; | ||
|
||
/// <summary> | ||
/// The parameters of interactive component. | ||
/// </summary> | ||
[Parameter] public IDictionary<string, object?>? InteractiveComponentParameters { get; set; } | ||
|
||
[Parameter] public RenderFragment<TValue?>? ChildContent { get; set; } | ||
|
||
/// <summary> | ||
/// Determines whether a built-in popup is needed to display the interactive component. | ||
/// </summary> | ||
[Parameter] public bool WithPopup { get; set; } | ||
|
||
[Parameter] public string? PopupClass { get; set; } | ||
|
||
[Parameter] public string? PopupStyle { get; set; } | ||
|
||
/// <summary> | ||
/// The top position of popup. | ||
/// </summary> | ||
[Parameter] public int? Top { get; set; } | ||
|
||
/// <summary> | ||
/// The right position of popup. | ||
/// </summary> | ||
[Parameter] public int? Right { get; set; } | ||
|
||
/// <summary> | ||
/// The bottom position of popup. | ||
/// </summary> | ||
[Parameter] public int? Bottom { get; set; } | ||
|
||
/// <summary> | ||
/// The left position of popup. | ||
/// </summary> | ||
[Parameter] public int? Left { get; set; } | ||
|
||
private bool _active; | ||
|
||
private string ElementId => $"_int_trigger_{QueryName}"; | ||
|
||
protected virtual string ComponentName => nameof(MInteractiveTriggerBase<TValue, TInteractiveValue>); | ||
|
||
protected string? Activator => $"#{ElementId} > a"; | ||
|
||
public bool IsInteractive { get; private set; } | ||
|
||
private IDictionary<string, object?> ComputedInteractiveComponentParameters | ||
{ | ||
get | ||
{ | ||
InteractiveComponentParameters ??= new Dictionary<string, object?>(); | ||
|
||
if (InteractiveComponentType.IsAssignableTo(typeof(MInteractivePopup))) | ||
{ | ||
InteractiveComponentParameters.TryAdd(nameof(QueryName), QueryName); | ||
InteractiveComponentParameters.TryAdd(nameof(Activator), Activator); | ||
} | ||
|
||
return InteractiveComponentParameters; | ||
} | ||
} | ||
|
||
protected override async Task OnInitializedAsync() | ||
{ | ||
QueryName.ThrowIfNull(ComponentName); | ||
InteractiveValue.ThrowIfNull(ComponentName); | ||
InteractiveComponentType.ThrowIfNull(ComponentName); | ||
|
||
IsInteractive = CheckInteractive(); | ||
|
||
if (IsInteractive) | ||
{ | ||
// The html generated from the server is rendered on the page | ||
// before a short delay. With delay and [StreamRendering], | ||
// set active to true, there will be a short transition animation. | ||
|
||
await Task.Delay(1); | ||
|
||
_active = true; | ||
} | ||
} | ||
|
||
protected abstract bool CheckInteractive(); | ||
|
||
protected override void SetComponentCss() | ||
{ | ||
CssProvider.UseBem("m-interactive-trigger") | ||
.Element("link", | ||
css => { css.Modifiers(m => m.Modifier("disabled", IsInteractive && DisableLinkOnInteractive)); }) | ||
.Element("popup", css => { css.Modifiers(m => m.Modifier("active", _active).AddClass(PopupClass)); }, | ||
style => | ||
{ | ||
style.AddIf($"top: {Top}px", () => Top.HasValue) | ||
.AddIf($"right: {Right}px", () => Right.HasValue) | ||
.AddIf($"bottom: {Bottom}px", () => Bottom.HasValue) | ||
.AddIf($"left: {Left}px", () => Left.HasValue) | ||
.Add(PopupStyle); | ||
}); | ||
} | ||
} |
33 changes: 33 additions & 0 deletions
33
src/MASA.OfficialWebsite.WebApp/Components/InteractiveTrigger/MInteractiveTriggers2.razor
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
@namespace Masa.Blazor | ||
@typeparam TValue | ||
@using Microsoft.AspNetCore.Components.Rendering | ||
@inherits MInteractiveTriggerBase2<TValue, IEnumerable<TValue>> | ||
|
||
@base.BuildRenderTree | ||
|
||
@code { | ||
|
||
protected override string ComponentName => nameof(MInteractiveTriggers<TValue>); | ||
|
||
protected override void OnInitialized() | ||
{ | ||
base.OnInitialized(); | ||
|
||
InteractiveValue.ThrowIfNull(ComponentName); | ||
} | ||
|
||
protected override void RenderLinkContent(RenderTreeBuilder __builder) | ||
{ | ||
foreach (var interactiveValue in InteractiveValue!) | ||
{ | ||
var value = EqualityComparer<TValue?>.Default.Equals(QueryValue, interactiveValue) ? default : interactiveValue; | ||
@RenderSingleLink(QueryName, value, interactiveValue) | ||
} | ||
} | ||
|
||
protected override bool CheckInteractive() | ||
{ | ||
return InteractiveValue!.Any(val => EqualityComparer<TValue>.Default.Equals(QueryValue, val)); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
src/MASA.OfficialWebsite.WebApp/Components/Layout/MobileAppBar.razor
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
31 changes: 31 additions & 0 deletions
31
src/MASA.OfficialWebsite.WebApp/NavigationManagerExtensions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
using Microsoft.AspNetCore.Components; | ||
|
||
namespace MASA.OfficialWebsite.WebApp; | ||
|
||
public static class NavigationManagerExtensions | ||
{ | ||
public static string GetRelativeUriWithQueryParameters(this NavigationManager navigationManager, IReadOnlyDictionary<string, object?> parameters) | ||
{ | ||
var uriWithQueryParameters = navigationManager.GetUriWithQueryParameters(parameters); | ||
return navigationManager.ToRelativeUriWithQueryParameters(uriWithQueryParameters); | ||
} | ||
|
||
public static string GetRelativeUriWithQueryParameter(this NavigationManager navigationManager, string name, bool? value) | ||
{ | ||
var uriWithQueryParameter = navigationManager.GetUriWithQueryParameter(name, value); | ||
return navigationManager.ToRelativeUriWithQueryParameters(uriWithQueryParameter); | ||
} | ||
|
||
public static string GetRelativeUriWithQueryParameter(this NavigationManager navigationManager, string name, string? value) | ||
{ | ||
var uriWithQueryParameter = navigationManager.GetUriWithQueryParameter(name, value); | ||
return navigationManager.ToRelativeUriWithQueryParameters(uriWithQueryParameter); | ||
} | ||
|
||
private static string ToRelativeUriWithQueryParameters(this NavigationManager navigationManager, string absoluteUriWithQueryParameters) | ||
{ | ||
var baseUri = navigationManager.BaseUri; | ||
var relativeUriWithQueryParameters = absoluteUriWithQueryParameters.Replace(baseUri, string.Empty); | ||
return relativeUriWithQueryParameters.StartsWith("/") ? relativeUriWithQueryParameters : "/" + relativeUriWithQueryParameters; | ||
} | ||
} |