Skip to content

Commit 0380d54

Browse files
committed
Refactor cell display properties and UI
Add notebook-change handling and refactor display properties. CellPropertiesPanel now subscribes to OnNotebookChanged and invokes LoadSectionsAsync via a new HandleNotebookChanged to refresh when the notebook changes (also fixes subscription/unsubscription scoping). Cell.razor removes the hardcoded "Export" prefix from action button titles. PropertyFieldComponent improves checkbox handling by using IsToggleChecked to support bool, JsonElement and string boolean values. CellDisplayPropertyProvider now builds the fields list incrementally, only exposes input-collapse-related fields for code cells (SupportsInputCollapse), and simplifies preview-style normalization/persistence. A unit test was added to ensure input fields are omitted for non-code cells.
1 parent 548a4c8 commit 0380d54

5 files changed

Lines changed: 97 additions & 48 deletions

File tree

src/Verso.Blazor.Shared/Components/Notebook/Cell.razor

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@
9898
var act = action;
9999
<button class="verso-cell-btn verso-cell-btn--action"
100100
@onclick="() => ExecuteCellActionAsync(act)"
101-
title="Export @act.DisplayName">
101+
title="@act.DisplayName">
102102
@if (act.Icon is not null)
103103
{
104104
@((MarkupString)act.Icon)

src/Verso.Blazor.Shared/Components/Notebook/CellPropertiesPanel.razor

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,13 @@
5151
if (_subscribedService != Service)
5252
{
5353
if (_subscribedService is not null)
54+
{
5455
_subscribedService.OnCellExecuted -= HandleCellChanged;
56+
_subscribedService.OnNotebookChanged -= HandleNotebookChanged;
57+
}
5558
_subscribedService = Service;
5659
Service.OnCellExecuted += HandleCellChanged;
60+
Service.OnNotebookChanged += HandleNotebookChanged;
5761
}
5862

5963
if (SelectedCellId != _lastLoadedCellId)
@@ -107,9 +111,21 @@
107111
});
108112
}
109113

114+
private async void HandleNotebookChanged()
115+
{
116+
await InvokeAsync(async () =>
117+
{
118+
await LoadSectionsAsync(showLoading: false);
119+
StateHasChanged();
120+
});
121+
}
122+
110123
public void Dispose()
111124
{
112125
if (_subscribedService is not null)
126+
{
113127
_subscribedService.OnCellExecuted -= HandleCellChanged;
128+
_subscribedService.OnNotebookChanged -= HandleNotebookChanged;
129+
}
114130
}
115131
}

src/Verso.Blazor.Shared/Components/Notebook/PropertyFieldComponent.razor

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
case PropertyFieldType.Toggle:
2525
<input type="checkbox"
2626
class="verso-properties-toggle"
27-
checked="@(Field.CurrentValue is true)"
27+
checked="@IsToggleChecked()"
2828
disabled="@Field.IsReadOnly"
2929
@onchange="e => OnValueChanged.InvokeAsync(e.Value)" />
3030
break;
@@ -154,6 +154,15 @@
154154
StateHasChanged();
155155
}
156156

157+
private bool IsToggleChecked() => Field.CurrentValue switch
158+
{
159+
bool b => b,
160+
JsonElement { ValueKind: JsonValueKind.True } => true,
161+
JsonElement { ValueKind: JsonValueKind.False } => false,
162+
string s when bool.TryParse(s, out var parsed) => parsed,
163+
_ => false
164+
};
165+
157166
private bool IsSelected(string optionValue) =>
158167
string.Equals(Field.CurrentValue?.ToString(), optionValue, StringComparison.OrdinalIgnoreCase);
159168

src/Verso/Extensions/CellDisplayPropertyProvider.cs

Lines changed: 54 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -21,54 +21,68 @@ public sealed class CellDisplayPropertyProvider : ICellPropertyProvider
2121

2222
public Task<PropertySection> GetPropertiesSectionAsync(CellModel cell, ICellRenderContext context)
2323
{
24-
var fields = new List<PropertyField>
24+
var fields = new List<PropertyField>();
25+
26+
if (SupportsInputCollapse(cell))
2527
{
26-
new(
28+
fields.Add(new(
2729
CellViewStateMetadata.InputCollapsedProperty,
2830
"Collapse input",
2931
PropertyFieldType.Toggle,
30-
ReadBool(cell, CellViewStateMetadata.InputCollapsedKey)),
31-
new(
32-
CellViewStateMetadata.OutputVisibilityProperty,
33-
"Output",
34-
PropertyFieldType.Select,
35-
ReadOutputVisibility(cell),
36-
Options: new[]
37-
{
38-
new PropertyFieldOption(CellViewStateMetadata.OutputExpanded, "Full"),
39-
new PropertyFieldOption(CellViewStateMetadata.OutputPreview, "Preview"),
40-
new PropertyFieldOption(CellViewStateMetadata.OutputHidden, "Hidden"),
41-
}),
42-
new(
32+
ReadBool(cell, CellViewStateMetadata.InputCollapsedKey)));
33+
}
34+
35+
fields.Add(new(
36+
CellViewStateMetadata.OutputVisibilityProperty,
37+
"Output",
38+
PropertyFieldType.Select,
39+
ReadOutputVisibility(cell),
40+
Options: new[]
41+
{
42+
new PropertyFieldOption(CellViewStateMetadata.OutputExpanded, "Full"),
43+
new PropertyFieldOption(CellViewStateMetadata.OutputPreview, "Preview"),
44+
new PropertyFieldOption(CellViewStateMetadata.OutputHidden, "Hidden"),
45+
}));
46+
47+
if (SupportsInputCollapse(cell))
48+
{
49+
fields.Add(new(
4350
CellViewStateMetadata.InputPreviewLineCountProperty,
4451
"Input preview lines",
4552
PropertyFieldType.Number,
4653
ReadPositiveInt(
4754
cell,
4855
CellViewStateMetadata.InputPreviewLineCountKey,
49-
CellViewStateMetadata.DefaultInputPreviewLineCount)),
50-
new(
51-
CellViewStateMetadata.OutputPreviewLineCountProperty,
52-
"Output preview lines",
53-
PropertyFieldType.Number,
54-
ReadPositiveInt(
55-
cell,
56-
CellViewStateMetadata.OutputPreviewLineCountKey,
57-
CellViewStateMetadata.DefaultOutputPreviewLineCount)),
58-
new(
59-
CellViewStateMetadata.PreviewStyleProperty,
60-
"Preview style",
61-
PropertyFieldType.Select,
62-
ReadPreviewStyle(cell),
63-
Options: new[]
64-
{
65-
new PropertyFieldOption(CellViewStateMetadata.PreviewStyleLines, "Lines"),
66-
}),
67-
};
56+
CellViewStateMetadata.DefaultInputPreviewLineCount)));
57+
}
58+
59+
fields.Add(new(
60+
CellViewStateMetadata.OutputPreviewLineCountProperty,
61+
"Output preview lines",
62+
PropertyFieldType.Number,
63+
ReadPositiveInt(
64+
cell,
65+
CellViewStateMetadata.OutputPreviewLineCountKey,
66+
CellViewStateMetadata.DefaultOutputPreviewLineCount)));
67+
68+
fields.Add(new(
69+
CellViewStateMetadata.PreviewStyleProperty,
70+
"Preview style",
71+
PropertyFieldType.Select,
72+
ReadPreviewStyle(cell),
73+
Options: new[]
74+
{
75+
new PropertyFieldOption(CellViewStateMetadata.PreviewStyleLines, "Lines"),
76+
}));
6877

6978
return Task.FromResult(new PropertySection("Display", null, fields));
7079
}
7180

81+
// Matches Cell.razor's SupportsInputCollapse: only code cells render the gutter chevron
82+
// and the collapsed-source preview, so only code cells should expose the related fields.
83+
private static bool SupportsInputCollapse(CellModel cell) =>
84+
string.Equals(cell.Type, "code", StringComparison.OrdinalIgnoreCase);
85+
7286
public Task OnPropertyChangedAsync(CellModel cell, string propertyName, object? value, ICellRenderContext context)
7387
{
7488
switch (propertyName)
@@ -116,14 +130,9 @@ private static void SetOutputVisibility(CellModel cell, string? value)
116130

117131
private static void SetPreviewStyle(CellModel cell, string? value)
118132
{
119-
var normalized = string.Equals(value, CellViewStateMetadata.PreviewStyleLines, StringComparison.OrdinalIgnoreCase)
120-
? CellViewStateMetadata.PreviewStyleLines
121-
: CellViewStateMetadata.PreviewStyleLines;
122-
123-
if (string.Equals(normalized, CellViewStateMetadata.PreviewStyleLines, StringComparison.Ordinal))
124-
cell.Metadata.Remove(CellViewStateMetadata.PreviewStyleKey);
125-
else
126-
cell.Metadata[CellViewStateMetadata.PreviewStyleKey] = normalized;
133+
// TODO: replace with a real normalize-and-persist when a second preview style is added.
134+
_ = value;
135+
cell.Metadata.Remove(CellViewStateMetadata.PreviewStyleKey);
127136
}
128137

129138
private static void SetBoolMetadata(CellModel cell, string key, bool value)
@@ -148,10 +157,9 @@ private static string ReadOutputVisibility(CellModel cell) =>
148157

149158
private static string ReadPreviewStyle(CellModel cell)
150159
{
151-
var value = ReadString(cell, CellViewStateMetadata.PreviewStyleKey);
152-
return string.Equals(value, CellViewStateMetadata.PreviewStyleLines, StringComparison.OrdinalIgnoreCase)
153-
? CellViewStateMetadata.PreviewStyleLines
154-
: CellViewStateMetadata.PreviewStyleLines;
160+
// TODO: normalize against the supported set when a second preview style is added.
161+
_ = cell;
162+
return CellViewStateMetadata.PreviewStyleLines;
155163
}
156164

157165
private static string NormalizeOutputVisibility(string? value)

tests/Verso.Tests/Extensions/CellDisplayPropertyProviderTests.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,22 @@ public async Task GetPropertiesSection_ReturnsDisplayFields()
4141
section.Fields.Select(f => f.Name).ToArray());
4242
}
4343

44+
[TestMethod]
45+
public async Task GetPropertiesSection_OmitsInputFields_ForNonCodeCells()
46+
{
47+
var section = await _provider.GetPropertiesSectionAsync(new CellModel { Type = "markdown" }, _renderContext);
48+
49+
Assert.AreEqual("Display", section.Title);
50+
CollectionAssert.AreEqual(
51+
new[]
52+
{
53+
CellViewStateMetadata.OutputVisibilityProperty,
54+
CellViewStateMetadata.OutputPreviewLineCountProperty,
55+
CellViewStateMetadata.PreviewStyleProperty,
56+
},
57+
section.Fields.Select(f => f.Name).ToArray());
58+
}
59+
4460
[TestMethod]
4561
public async Task GetPropertiesSection_UsesDefaults_WhenMetadataIsAbsent()
4662
{

0 commit comments

Comments
 (0)