Browse Source

Address second-round Copilot review and fix grid layout bug

pull/25380/head
maliming 5 months ago
parent
commit
bd02c54a60
No known key found for this signature in database GPG Key ID: A646B9CB645ECEA4
  1. 4
      docs/en/framework/ui/blazor/page-toolbar-extensions.md
  2. 2
      docs/en/ui-themes/lepton-x/blazor.md
  3. 4
      modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/DocumentParameterDto.cs
  4. 20
      modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml
  5. 43
      modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml.cs

4
docs/en/framework/ui/blazor/page-toolbar-extensions.md

@ -60,7 +60,7 @@ protected override async ValueTask SetToolbarItemsAsync()
{ {
//TODO: Write your custom code //TODO: Write your custom code
return Task.CompletedTask; return Task.CompletedTask;
}, MudBlazor.Icons.Material.Filled.FileUpload, MudBlazor.Color.Secondary); }, MudBlazor.Icons.Material.Filled.Upload, MudBlazor.Color.Secondary);
} }
``` ```
@ -120,7 +120,7 @@ namespace MyCompanyName.MyProjectName.Blazor.Pages.Identity
{ {
//TODO: Write your custom code //TODO: Write your custom code
return Task.CompletedTask; return Task.CompletedTask;
}, MudBlazor.Icons.Material.Filled.FileUpload, MudBlazor.Color.Secondary); }, MudBlazor.Icons.Material.Filled.Upload, MudBlazor.Color.Secondary);
} }
} }
} }

2
docs/en/ui-themes/lepton-x/blazor.md

@ -26,7 +26,7 @@ LeptonX theme is implemented and ready to use with ABP. No custom implementation
> * `Volo.Abp.AspNetCore.Components.{Server,WebAssembly}.MudBlazorLeptonXTheme` > * `Volo.Abp.AspNetCore.Components.{Server,WebAssembly}.MudBlazorLeptonXTheme`
> * `Volo.Abp.AspNetCore.Components.{Server,WebAssembly}.MudBlazorLeptonXTheme.Bundling` > * `Volo.Abp.AspNetCore.Components.{Server,WebAssembly}.MudBlazorLeptonXTheme.Bundling`
> * Module types: `Abp{...}MudBlazorLeptonXThemeModule`, `Abp{...}MudBlazorLeptonXThemeBundlingModule` > * Module types: `Abp{...}MudBlazorLeptonXThemeModule`, `Abp{...}MudBlazorLeptonXThemeBundlingModule`
> * Layout namespace: `Volo.Abp.AspNetCore.Components.{Server,WebAssembly}.MudBlazorLeptonXTheme.Themes.MudBlazorLeptonX` > * Layout components live under `Volo.Abp.AspNetCore.Components.{Web,Server,WebAssembly}.MudBlazorLeptonXTheme.Components.ApplicationLayout` (with `SideMenu`, `TopMenu`, and `PublicWebsiteLayout` sub-namespaces).
{{end}} {{end}}

4
modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/DocumentParameterDto.cs

@ -14,8 +14,8 @@ namespace Volo.Docs.Documents
/// Conditional visibility: this parameter is shown only when the keyed parameter's /// Conditional visibility: this parameter is shown only when the keyed parameter's
/// current value is one of the listed values. /// current value is one of the listed values.
/// Example: "DependsOn": { "UI": [ "Blazor", "BlazorServer", "BlazorWebApp" ] } /// Example: "DependsOn": { "UI": [ "Blazor", "BlazorServer", "BlazorWebApp" ] }
/// When null or empty the parameter is always shown. /// An empty dictionary means the parameter is always shown.
/// </summary> /// </summary>
public Dictionary<string, List<string>> DependsOn { get; set; } public Dictionary<string, List<string>> DependsOn { get; set; } = new Dictionary<string, List<string>>();
} }
} }

20
modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml

@ -474,7 +474,14 @@
<div class="docs-content-field"> <div class="docs-content-field">
<div class="docs-text-field"> <div class="docs-text-field">
<div class="position-relative"> <div class="position-relative">
@if (Model.DocumentPreferences != null && Model.DocumentPreferences.Parameters != null && Model.DocumentPreferences.Parameters.Any()) @{
// Filter the parameters that should actually be shown (after applying DependsOn rules)
// before computing the grid layout, otherwise hidden parameters would still occupy a column slot.
var visibleParameters = Model.DocumentPreferences?.Parameters?
.Where(p => Model.IsParameterVisible(p))
.ToList() ?? new List<DocumentParameterDto>();
}
@if (visibleParameters.Count > 0)
{ {
<div class="alert alert-primary alert-criteria"> <div class="alert alert-primary alert-criteria">
<abp-row> <abp-row>
@ -488,10 +495,12 @@
<abp-row class="gx-2"> <abp-row class="gx-2">
@{ @{
const int maxCellCount = 3; const int maxCellCount = 3;
var count = Model.DocumentPreferences.Parameters.Count; var count = visibleParameters.Count;
var rowCount = count / maxCellCount + (count % maxCellCount > 0 ? 1 : 0); var rowCount = count / maxCellCount + (count % maxCellCount > 0 ? 1 : 0);
var cellSize = 12 / (count > maxCellCount ? maxCellCount : count); var cellSize = 12 / (count > maxCellCount ? maxCellCount : count);
var latestCellSize = 12 / count - (rowCount - 1) * maxCellCount; // Last row may have fewer items than maxCellCount; size them to fill the row width.
var lastRowCellCount = count - (rowCount - 1) * maxCellCount;
var latestCellSize = 12 / lastRowCellCount;
string BuildParameterDivClass(int index) string BuildParameterDivClass(int index)
{ {
@ -503,10 +512,9 @@
for (var i = 0; i < count; ++i) for (var i = 0; i < count; ++i)
{ {
var parameter = Model.DocumentPreferences.Parameters[i]; var parameter = visibleParameters[i];
var hiddenStyle = Model.IsParameterVisible(parameter) ? null : "display:none;";
<div class="@BuildParameterDivClass(i)" style="@hiddenStyle"> <div class="@BuildParameterDivClass(i)">
<div class="custom-input-group"> <div class="custom-input-group">
<span class="input-group-text" id="@("Section" + parameter.Name + "ComboboxAddonId")">@(parameter.DisplayName)</span> <span class="input-group-text" id="@("Section" + parameter.Name + "ComboboxAddonId")">@(parameter.DisplayName)</span>
<select class="doc-section-combobox form-select" <select class="doc-section-combobox form-select"

43
modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml.cs

@ -95,22 +95,27 @@ namespace Volo.Docs.Pages.Documents.Project
_renderedParameterNamesCache ??= (DocumentPreferences?.Parameters?.Select(p => p.Name).ToHashSet() ?? new HashSet<string>()); _renderedParameterNamesCache ??= (DocumentPreferences?.Parameters?.Select(p => p.Name).ToHashSet() ?? new HashSet<string>());
public virtual bool IsParameterVisible(DocumentParameterDto parameter) public virtual bool IsParameterVisible(DocumentParameterDto parameter)
{
return IsParameterVisibleGiven(parameter, UserPreferences);
}
// Per-rule semantics for a (parameter, current selection) context:
// - rule.Value == null : malformed list, skip the rule (fail-open)
// - key not in current document : rule references an unknown parameter, skip (fail-open)
// - rule.Value.Count == 0 : explicit empty allow-list, hide the parameter (author intent: "never show")
// - selected value not in allow-list: hide
// - selected value in allow-list : pass this rule
protected virtual bool IsParameterVisibleGiven(DocumentParameterDto parameter, IReadOnlyDictionary<string, string> selectedValues)
{ {
if (parameter.DependsOn == null || parameter.DependsOn.Count == 0) if (parameter.DependsOn == null || parameter.DependsOn.Count == 0)
{ {
return true; return true;
} }
// Per-rule semantics:
// - rule.Value == null : malformed list, skip the rule (fail-open)
// - key not in current document : rule references an unknown parameter, skip (fail-open)
// - rule.Value.Count == 0 : explicit empty allow-list, hide the parameter (author intent: "never show")
// - current value not in allow-list: hide
// - current value in allow-list : pass this rule
return parameter.DependsOn.All(rule => return parameter.DependsOn.All(rule =>
rule.Value == null || !RenderedParameterNames.Contains(rule.Key) rule.Value == null || !RenderedParameterNames.Contains(rule.Key)
|| (rule.Value.Count > 0 || (rule.Value.Count > 0
&& UserPreferences.TryGetValue(rule.Key, out var current) && selectedValues.TryGetValue(rule.Key, out var current)
&& rule.Value.Contains(current))); && rule.Value.Contains(current)));
} }
@ -872,13 +877,16 @@ namespace Volo.Docs.Pages.Documents.Project
{ {
if (!DocumentPreferences?.Parameters?.Any() ?? true) if (!DocumentPreferences?.Parameters?.Any() ?? true)
{ {
return; return;
} }
AlternativeOptionLinkQueries = CollectAlternativeOptionLinksRecursively(); AlternativeOptionLinkQueries = CollectAlternativeOptionLinksRecursively(0, new Dictionary<string, string>());
} }
private List<string> CollectAlternativeOptionLinksRecursively(int index = 0) // Generates all parameter combinations as query strings, but skips parameters whose DependsOn rules
// aren't satisfied by the partially-built selection. This avoids producing nonsensical combinations
// (e.g. UI=MVC&BlazorUI=MudBlazor when BlazorUI depends on UI ∈ {Blazor, BlazorServer, BlazorWebApp}).
private List<string> CollectAlternativeOptionLinksRecursively(int index, Dictionary<string, string> selected)
{ {
if (index >= DocumentPreferences.Parameters.Count) if (index >= DocumentPreferences.Parameters.Count)
{ {
@ -886,13 +894,22 @@ namespace Volo.Docs.Pages.Documents.Project
} }
var option = DocumentPreferences.Parameters[index]; var option = DocumentPreferences.Parameters[index];
// If this parameter is hidden in the current selection context, omit it from the query
// and continue with the next parameter (no Cartesian fan-out for this option).
if (!IsParameterVisibleGiven(option, selected))
{
return CollectAlternativeOptionLinksRecursively(index + 1, selected);
}
var queries = new List<string>(); var queries = new List<string>();
foreach (var key in option.Values.Keys) foreach (var key in option.Values.Keys)
{ {
var linkQuery = new StringBuilder($"{option.Name}={key}"); var linkQuery = $"{option.Name}={key}";
var restOfQueries = CollectAlternativeOptionLinksRecursively(index + 1); var nextSelected = new Dictionary<string, string>(selected) { [option.Name] = key };
var restOfQueries = CollectAlternativeOptionLinksRecursively(index + 1, nextSelected);
if (restOfQueries.Any()) if (restOfQueries.Any())
{ {
@ -903,7 +920,7 @@ namespace Volo.Docs.Pages.Documents.Project
} }
else else
{ {
queries.Add($"{linkQuery}"); queries.Add(linkQuery);
} }
} }

Loading…
Cancel
Save