Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
@namespace BootstrapBlazor.Server.Components.Samples.Tutorials
@inject IStringLocalizer<BarCodeGenerator> Localizer
@page "/tutorials/barcode"

<div class="bc-main">
<div class="row g-3">
<div class="col-12 col-sm-6">
<h5>@Localizer["SelectType"]</h5>
<div class="bc-type-list">
@foreach (var item in _contents)
{
<span class="@GetItemClassString(item)" @onclick="@(() => OnActiveType(item))">@item</span>
}
</div>
<div class="bc-content-main">
@if (_activeContentType == "Text")
{
<ValidateForm Model="_textContent" OnValidSubmit="OnTextSubmit">
<EditorForm TModel="TextContent" ItemsPerRow="1">
<FieldItems>
<EditorItem @bind-Field="@context.Content" Rows="3" Text="Text"></EditorItem>
</FieldItems>
</EditorForm>
<div class="form-footer">
<Button ButtonType="@ButtonType.Submit" Text="Submit" />
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: Consider localizing the button text for consistency.

Use the Localizer to fetch the “Submit” button text from resource files to match other localized UI elements.

Suggested implementation:

<Button ButtonType="@ButtonType.Submit" Text="@Localizer["Submit"]" />

Ensure a valid Localizer instance is available in the component. If not already injected, add an @Inject statement at the top of the file, such as:
@Inject IStringLocalizer Localizer
This change will provide the required localization functionality.

</div>
</ValidateForm>
}
else if (_activeContentType == "Url")
{
<ValidateForm Model="_urlContent" OnValidSubmit="OnUrlSubmit">
<EditorForm TModel="TextContent" ItemsPerRow="1">
<FieldItems>
<EditorItem @bind-Field="@context.Content" PlaceHolder="https://" Text="Url"></EditorItem>
</FieldItems>
</EditorForm>
<div class="form-footer">
<Button ButtonType="@ButtonType.Submit" Text="Submit" />
</div>
</ValidateForm>
}
else if (_activeContentType == "Wi-Fi")
{
<ValidateForm Model="_wifiContent" OnValidSubmit="OnWiFiSubmit">
<EditorForm TModel="WiFiContent" ItemsPerRow="1">
<FieldItems>
<EditorItem @bind-Field="@context.Password" ComponentType="typeof(BootstrapPassword)"></EditorItem>
Copy link

Copilot AI May 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Wi‑Fi form currently only provides an input for Password while the SSID property (which is required) is missing. Please add an EditorItem to input the SSID.

Copilot uses AI. Check for mistakes.
</FieldItems>
</EditorForm>
<div class="form-footer">
<Button ButtonType="@ButtonType.Submit" Text="Submit" />
</div>
</ValidateForm>
}
else if (_activeContentType == "Email")
{
<ValidateForm Model="_emailContent" OnValidSubmit="OnEmailSubmit">
<EditorForm TModel="EmailContent" ItemsPerRow="1"></EditorForm>
Copy link

Copilot AI May 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Email form is missing input fields for Email, Subject, and Message. Consider adding the appropriate EditorItems to allow users to enter these required details.

Suggested change
<EditorForm TModel="EmailContent" ItemsPerRow="1"></EditorForm>
<EditorForm TModel="EmailContent" ItemsPerRow="1">
<FieldItems>
<EditorItem @bind-Field="@context.Email" PlaceHolder="Enter your email" Text="Email"></EditorItem>
<EditorItem @bind-Field="@context.Subject" PlaceHolder="Enter the subject" Text="Subject"></EditorItem>
<EditorItem @bind-Field="@context.Message" Rows="5" PlaceHolder="Enter your message" Text="Message"></EditorItem>
</FieldItems>
</EditorForm>

Copilot uses AI. Check for mistakes.
<div class="form-footer">
<Button ButtonType="@ButtonType.Submit" Text="Submit" />
</div>
</ValidateForm>
}
</div>
</div>
<div class="col-12 col-sm-6">
<h5>@Localizer["Preview"]</h5>
<p>@((MarkupString)_desc)</p>
<div class="bc-qr-content">
@if (!string.IsNullOrEmpty(_content))
{
<QRCode Content="@_content" Width="256"></QRCode>
}
</div>
</div>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the Apache 2.0 License
// See the LICENSE file in the project root for more information.
// Maintainer: Argo Zhang([email protected]) Website: https://www.blazor.zone

using Microsoft.AspNetCore.Components.Forms;

namespace BootstrapBlazor.Server.Components.Samples.Tutorials;

/// <summary>
/// BarCodeGenerator 组件示例代码
/// </summary>
public partial class BarCodeGenerator
{
private string _activeContentType = "Text";

private readonly List<string> _contents = ["Text", "Url", "Wi-Fi", "Email"];

private readonly WiFiContent _wifiContent = new();

private readonly EmailContent _emailContent = new();

private readonly TextContent _textContent = new();

private readonly TextContent _urlContent = new();

private string? _content;

private string _desc => _activeContentType switch
{
"Text" => Localizer["TextDesc"],
"Url" => Localizer["UrlDesc"],
"Wi-Fi" => Localizer["WiFiDesc"],
"Email" => Localizer["EmailDesc"],
_ => string.Empty
};

private string? GetItemClassString(string item) => CssBuilder.Default("bc-type-item")
.AddClass("active", _activeContentType == item)
.Build();

private void OnActiveType(string item)
{
_activeContentType = item;
}

private Task OnTextSubmit(EditContext context)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (complexity): Consider refactoring the four submit handlers into a single generic handler to reduce code duplication.

Consider refactoring the four submit handlers into one generic handler that selects the appropriate content based on _activeContentType. For example, you can replace them with:

private Task OnSubmit(EditContext context)
{
    _content = _activeContentType switch
    {
        "Text"   => _textContent.ToString(),
        "Url"    => _urlContent.ToString(),
        "Wi-Fi"  => _wifiContent.ToString(),
        "Email"  => _emailContent.ToString(),
        _        => string.Empty,
    };
    StateHasChanged();
    return Task.CompletedTask;
}

Then update the event bindings in your UI code to use this single handler. This reduces duplication while preserving all functionality.

{
_content = _textContent.ToString();
StateHasChanged();
return Task.CompletedTask;
}

private Task OnUrlSubmit(EditContext context)
{
_content = _urlContent.ToString();
StateHasChanged();
return Task.CompletedTask;
}

private Task OnWiFiSubmit(EditContext context)
{
_content = _wifiContent.ToString();
StateHasChanged();
return Task.CompletedTask;
}

private Task OnEmailSubmit(EditContext context)
{
_content = _emailContent.ToString();
StateHasChanged();
return Task.CompletedTask;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
.bc-type-list {
display: flex;
align-items: center;
gap: 0.5rem 0.5rem;
margin-bottom: 1rem;
}

.bc-type-item {
padding: .25rem 1rem;
border: 2px solid var(--bb-primary-color);
border-radius: 50px;
line-height: 1.8em;
cursor: pointer;
}

.bc-type-item.active {
background-color: var(--bb-primary-color);
color: var(--bs-white);
}

.bc-qr-content {
border: 2px solid var(--bb-primary-color);
border-radius: var(--bs-border-radius);
padding: .25rem;
display: flex;
height: calc(256px + .5rem + 4px);
width: calc(256px + .5rem + 4px);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the Apache 2.0 License
// See the LICENSE file in the project root for more information.
// Maintainer: Argo Zhang([email protected]) Website: https://www.blazor.zone

namespace BootstrapBlazor.Server.Components.Samples.Tutorials;

/// <summary>
/// EmailContent
/// </summary>
public class EmailContent
{
/// <summary>
/// Gets or sets Email
/// </summary>
[Required]
public string? Email { get; set; }

/// <summary>
/// Gets or sets Subject
/// </summary>
[Required]
public string? Subject { get; set; }

/// <summary>
/// Gets or sets Message
/// </summary>
[Required]
[AutoGenerateColumn(Rows = 3)]
public string? Message { get; set; }

/// <summary>
/// <inheritdoc/>
/// </summary>
/// <returns></returns>
public override string ToString()
{
return $"mailto:{Email}?subject={Uri.EscapeDataString(Subject ?? "")}&body={Uri.EscapeDataString(Message ?? "")}";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the Apache 2.0 License
// See the LICENSE file in the project root for more information.
// Maintainer: Argo Zhang([email protected]) Website: https://www.blazor.zone

namespace BootstrapBlazor.Server.Components.Samples.Tutorials;

/// <summary>
/// TextContent
/// </summary>
public class TextContent
{
/// <summary>
/// Gets or sets the content.
/// </summary>
[Required]
public string? Content { get; set; }

/// <summary>
/// <inheritdoc/>
/// </summary>
/// <returns></returns>
public override string? ToString() => Content;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the Apache 2.0 License
// See the LICENSE file in the project root for more information.
// Maintainer: Argo Zhang([email protected]) Website: https://www.blazor.zone

using System.ComponentModel;

namespace BootstrapBlazor.Server.Components.Samples.Tutorials;

/// <summary>
/// WiFiAuthentication enum
/// </summary>
public enum WiFiAuthentication
{
/// <summary>
///
/// </summary>
[Description("None")]
None,

/// <summary>
///
/// </summary>
[Description("WEP")]
WEP,

/// <summary>
///
/// </summary>
[Description("WPA")]
WPA
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the Apache 2.0 License
// See the LICENSE file in the project root for more information.
// Maintainer: Argo Zhang([email protected]) Website: https://www.blazor.zone

namespace BootstrapBlazor.Server.Components.Samples.Tutorials;

/// <summary>
/// WiFi content class
/// </summary>
public class WiFiContent
{
/// <summary>
/// Gets or sets the authentication type.
/// </summary>
public WiFiAuthentication Authentication { get; set; } = WiFiAuthentication.WPA;

/// <summary>
/// Gets or sets the SSID.
/// </summary>
[Required]
public string? SSID { get; set; }

/// <summary>
/// Gets or sets the password.
/// </summary>
[Required]
public string? Password { get; set; }

/// <summary>
/// <inheritdoc/>
/// </summary>
/// <returns></returns>
public override string ToString()
{
return $"WIFI:S:{EscapeInput(SSID ?? "")};T:{Authentication};P:{Password};;";
}

private static string EscapeInput(string content)
{
char[] array = ['\\', ';', ',', ':'];
foreach (char c in array)
{
content = content.Replace(c.ToString(), "\\" + c);
}
return content;
}
}
8 changes: 8 additions & 0 deletions src/BootstrapBlazor.Server/Locales/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -7108,5 +7108,13 @@
"SubTitle": "An implementation TOTP RFC 6238 and HOTP RFC 4226 Authenticator service.",
"BaseUsageTitle": "Basic usage",
"BaseUsageIntro": "By calling the <code>Compute</code> method of the <code>ITotpService</code> service instance, you can get the password in the current time window. By calling the <code>Instance.GetRemainingSeconds</code> method, you can display the remaining validity time of the current password. In this example, the progress bar is used for dynamic display."
},
"BootstrapBlazor.Server.Components.Samples.Tutorials.BarCodeGenerator": {
"SelectType": "Select content type",
"Preview": "Preview",
"TextDesc": "Use your iPhone's camera or the QR code scanning function to scan the QR code below, then open the <code>Safari</code> browser and search for the current text using the default search engine.",
"UrlDesc": "Use your iPhone's camera or the QR code scanning function to scan the QR code below, then open the <code>Safari</code> browser and open the current address",
"WiFiDesc": "Use your iPhone's camera or the QR code scanner to scan the QR code below to automatically join the <code>WiFi</code> network.",
"EmailDesc": "Use your iPhone's camera or the QR code scanner to scan the QR code below, then open the <code>Email</code> app to send an email."
}
}
8 changes: 8 additions & 0 deletions src/BootstrapBlazor.Server/Locales/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -7108,5 +7108,13 @@
"SubTitle": "实现 TOTP RFC 6238 和 HOTP RFC 4226 认证器服务",
"BaseUsageTitle": "基本用法",
"BaseUsageIntro": "通过调用 <code>ITotpService</code> 服务实例方法 <code>Compute</code> 得到当前时间窗口内密码, 通过调用 <code>Instance.GetRemainingSeconds</code> 方法可以显示当前密码剩余有效时间,本例中通过进度条进行动态显示"
},
"BootstrapBlazor.Server.Components.Samples.Tutorials.BarCodeGenerator": {
"SelectType": "选择一个类型",
"Preview": "预览",
"TextDesc": "使用 <code>iPhone</code> 手机相机或者扫描二维码功能扫描下方二维码后,打开 <code>Safari</code> 浏览器使用默认搜索引擎搜索当前文本",
"UrlDesc": "使用 <code>iPhone</code> 手机相机或者扫描二维码功能扫描下方二维码后,打开 <code>Safari</code> 浏览器并且打开当前地址",
"WiFiDesc": "使用 <code>iPhone</code> 手机相机或者扫描二维码功能扫描下方二维码后,自动加入 <code>WiFi</code> 网络",
"EmailDesc": "使用 <code>iPhone</code> 手机相机或者扫描二维码功能扫描下方二维码后,打开 <code>Email</code> 应用发送邮件"
}
}