|
18 | 18 | <div class="menu-left-buttons"> |
19 | 19 | <button class="btn-small" @onclick="ToggleFileMenu" id="btnOpen1" aria-expanded="@open">File</button> |
20 | 20 | <FluentMenu Anchor="btnOpen1" Open="@open" OpenChanged="@(val => open = val)" OnMenuChange="OnMenuChange" VerticalThreshold="170"> |
21 | | - <FluentMenuItem OnClick="@(() => TriggerAndClose(OnNew))">New</FluentMenuItem> |
| 21 | + <FluentMenuItem OnClick="@ShowNewInstructionDialog">New</FluentMenuItem> |
| 22 | + <FluentDivider Style="width: 100%;" Orientation=Orientation.Horizontal></FluentDivider> |
22 | 23 | <FluentMenuItem OnClick="@(() => TriggerImport())">Import</FluentMenuItem> |
23 | 24 | <FluentMenuItem OnClick="@(() => TriggerExport())" Disabled="@(!HasInstruction)">Export</FluentMenuItem> |
| 25 | + <FluentDivider Style="width: 100%;" Orientation=Orientation.Horizontal></FluentDivider> |
24 | 26 | <FluentMenuItem OnClick="@(() => TriggerAndClose(OnSave))" Disabled="@(!IsDirty)">Save</FluentMenuItem> |
25 | | - <FluentMenuItem OnClick="@(() => LogAndClose("Save As"))">Save As</FluentMenuItem> |
26 | | - <FluentMenuItem OnClick="@(() => TriggerAndClose(OnRevertChanges))" Disabled="@(!IsDirty)">Revert Changes</FluentMenuItem> |
| 27 | + <FluentMenuItem OnClick="@ShowSaveAsDialog" Disabled="@(!HasInstruction)">Save As</FluentMenuItem> |
27 | 28 | <AuthorizeView Roles="Administrator"> |
| 29 | + <FluentDivider Style="width: 100%;" Orientation=Orientation.Horizontal></FluentDivider> |
28 | 30 | <FluentMenuItem OnClick="@(() => TriggerAndClose(OnDelete))">Delete</FluentMenuItem> |
29 | 31 | </AuthorizeView> |
30 | 32 | </FluentMenu> |
|
38 | 40 | </FluentMenu> |
39 | 41 | </div> |
40 | 42 |
|
41 | | - <div class="inputs-container"> |
| 43 | + <div class="inputs-container title-version-container"> |
42 | 44 | <input |
43 | 45 | type="text" |
44 | 46 | class="menu-input" |
|
70 | 72 | </div> |
71 | 73 |
|
72 | 74 | <div class="menu-right-content"> |
73 | | - <button class="btn-small" title="Version History" @onclick="ToggleVersionHistorySidebar">⏲</button> |
| 75 | + <button class="btn-small" title="Version History" @onclick="ToggleVersionHistorySidebar"> |
| 76 | + <i class="bi bi-clock-history"></i> |
| 77 | + </button> |
74 | 78 | <div class="save-button-container"> |
75 | 79 | <button class="btn-small" title="Save" @onclick="HandleSave" disabled="@(!IsDirty)"> |
76 | | - 🖫 |
| 80 | + <i class="bi bi-floppy"></i> |
77 | 81 | @if (IsDirty) |
78 | 82 | { |
79 | 83 | <span class="red-dot"></span> |
80 | 84 | } |
81 | 85 | </button> |
82 | 86 | </div> |
83 | | - <button class="btn-small dark-toggle-btn" title="Dark Mode" @onclick="ToggleDarkMode">@darkModeIcon</button> |
| 87 | + |
| 88 | + <button class="btn-small dark-toggle-btn" title="Dark Mode" @onclick="ToggleDarkMode"> |
| 89 | + @((darkModeIcon == "bi bi-moon-stars") ? |
| 90 | + (MarkupString)"<i class=\"bi bi-moon-stars\"></i>" : |
| 91 | + (MarkupString)"<i class=\"bi bi-sun\"></i>") |
| 92 | + </button> |
84 | 93 |
|
85 | 94 | @if (!string.IsNullOrWhiteSpace(ActiveLineOperator)) |
86 | 95 | { |
87 | 96 | <div class="logout-container"> |
88 | 97 | <span>@ActiveLineOperator</span> |
89 | 98 | <form method="post" action="/api/auth/logout" class="logout-form"> |
90 | | - <button type="submit" class="btn-small" title="Logout">Logout</button> |
| 99 | + <button type="submit" class="btn-small" title="Logout"> |
| 100 | + Logout <i class="bi bi-box-arrow-right ms-1"></i> |
| 101 | + </button> |
91 | 102 | </form> |
92 | 103 | </div> |
93 | 104 | } |
|
114 | 125 | Visible="@showExportDialog" |
115 | 126 | VisibleChanged="@(val => showExportDialog = val)" /> |
116 | 127 |
|
| 128 | +<ProductAssociationDialog |
| 129 | + AllProducts="@Products" |
| 130 | + SelectedProducts="@DialogSelectedProducts" |
| 131 | + SelectedProductsChanged="OnDialogSelectedProductsChanged" |
| 132 | + IsVisible="@isAnyDialogVisible" |
| 133 | + IsVisibleChanged="@(val => isAnyDialogVisible = val)" |
| 134 | + HeaderText="@dialogHeaderText" |
| 135 | + ConfirmButtonText="@confirmButtonText" |
| 136 | + OnConfirmed="@OnDialogConfirmed" /> |
| 137 | + |
117 | 138 | @code { |
118 | 139 | private string? ActiveLineOperator { get; set; } |
119 | 140 |
|
|
125 | 146 | public EventCallback OnSidebarToggle { get; set; } |
126 | 147 |
|
127 | 148 | /// <summary> |
128 | | - /// Event callback triggered when the user selects "New" to create a new work instruction. |
| 149 | + /// Event callback triggered when the user selects "New" to create a new work instruction. This passes up a work |
| 150 | + /// instruction title and list of associated products. |
129 | 151 | /// </summary> |
130 | | - [Parameter] public EventCallback OnNew { get; set; } |
| 152 | + [Parameter] public EventCallback<(string Title, List<Product> Products)> OnNewConfirmed { get; set; } |
131 | 153 |
|
132 | 154 | /// <summary> |
133 | 155 | /// Event callback triggered when the user selects "Save" to persist current edits to the work instruction either |
134 | 156 | /// via versioning or direct edits. |
135 | 157 | /// </summary> |
136 | 158 | [Parameter] |
137 | 159 | public EventCallback OnSave { get; set; } |
| 160 | + |
| 161 | + /// <summary> |
| 162 | + /// Callback invoked when the user confirms the "Save As" action from the dialog. |
| 163 | + /// The associated products and work instruction title are passed up. |
| 164 | + /// </summary> |
| 165 | + [Parameter] public EventCallback<(string Title, List<Product> Products)> OnSaveAsConfirmed { get; set; } |
138 | 166 |
|
139 | 167 | /// <summary> |
140 | 168 | /// Event callback triggered when the user selects "Delete" to completely remove a work instruction. |
141 | 169 | /// </summary> |
142 | 170 | [Parameter] |
143 | 171 | public EventCallback OnDelete { get; set; } |
144 | | - |
145 | | - /// <summary> |
146 | | - /// Event callback triggered when the user selects "Revert Changes" to discard unsaved edits and restore the last saved state. |
147 | | - /// </summary> |
148 | | - [Parameter] |
149 | | - public EventCallback OnRevertChanges { get; set; } |
150 | 172 |
|
151 | 173 | /// <summary> |
152 | 174 | /// Event callback triggered when the user restores a previous version from the version history sidebar. |
|
162 | 184 |
|
163 | 185 | /// <summary> |
164 | 186 | /// Indicates whether there are unsaved changes in the current work instruction editor session. |
165 | | - /// Used to enable or disable menu actions like Save or Revert Changes. |
| 187 | + /// Used to enable or disable menu actions like Save. |
166 | 188 | /// </summary> |
167 | 189 | [Parameter] public bool IsDirty { get; set; } |
168 | 190 |
|
|
198 | 220 |
|
199 | 221 | private bool open = false; |
200 | 222 | private bool openOptions = false; |
201 | | - private string darkModeIcon = "🌙"; |
| 223 | + private string darkModeIcon = "bi bi-moon-stars"; |
202 | 224 | private bool HasInstruction => CurrentInstruction != null; |
203 | 225 |
|
204 | 226 | private List<WorkInstruction> _versionHistoryList = new(); |
205 | 227 | private bool _isLoadingVersions = false; |
206 | 228 |
|
207 | 229 | private bool showImportDialog; |
208 | | - |
209 | 230 | private bool showExportDialog = false; |
| 231 | + |
| 232 | + private bool isAnyDialogVisible; |
| 233 | + private string dialogHeaderText = ""; |
| 234 | + private string confirmButtonText = ""; |
| 235 | + private EventCallback<(string Title, List<Product> Products)> OnDialogConfirmed; |
| 236 | + |
| 237 | + private List<Product> DialogSelectedProducts { get; set; } = new List<Product>(); |
210 | 238 |
|
211 | 239 | /// <summary> |
212 | 240 | /// The list of products to show in the dropdown. |
|
282 | 310 | { |
283 | 311 | await JS.InvokeVoidAsync("document.body.classList.toggle", "dark-mode"); |
284 | 312 | var isDark = await JS.InvokeAsync<bool>("document.body.classList.contains", "dark-mode"); |
285 | | - darkModeIcon = isDark ? "☀️" : "🌙"; |
| 313 | + darkModeIcon = isDark ? "bi bi-sun" : "bi bi-moon-stars"; |
286 | 314 | } |
287 | 315 |
|
288 | 316 | private async Task ToggleSidebar() |
|
427 | 455 | { |
428 | 456 | showImportDialog = isOpen; |
429 | 457 | } |
| 458 | + |
| 459 | + private void ShowNewInstructionDialog() |
| 460 | + { |
| 461 | + isAnyDialogVisible = true; |
| 462 | + dialogHeaderText = "Create New Work Instruction"; |
| 463 | + confirmButtonText = "Open New"; |
| 464 | + OnDialogConfirmed = EventCallback.Factory.Create<(string, List<Product>)>(this, HandleNewDialogConfirmed); |
| 465 | + } |
| 466 | + |
| 467 | + private void ShowSaveAsDialog() |
| 468 | + { |
| 469 | + isAnyDialogVisible = true; |
| 470 | + DialogSelectedProducts = CurrentInstruction?.Products?.ToList() ?? new(); |
| 471 | + dialogHeaderText = "Save Work Instruction As"; |
| 472 | + confirmButtonText = "Save New"; |
| 473 | + OnDialogConfirmed = EventCallback.Factory.Create<(string, List<Product>)>(this, HandleSaveAsDialogConfirmed); |
| 474 | + } |
| 475 | + |
| 476 | + private async Task HandleNewDialogConfirmed((string Title, List<Product> Products) data) |
| 477 | + { |
| 478 | + Log.Information("[MenuBarPhoebe] HandleNewDialogConfirmed called: {DataTitle}, {ProductsCount} products", data.Title, data.Products.Count); |
| 479 | + isAnyDialogVisible = false; |
| 480 | + if (OnNewConfirmed.HasDelegate) |
| 481 | + await OnNewConfirmed.InvokeAsync(data); |
| 482 | + } |
| 483 | + |
| 484 | + private async Task HandleSaveAsDialogConfirmed((string Title, List<Product> Products) data) |
| 485 | + { |
| 486 | + Log.Information("[MenuBarPhoebe] HandleSaveAsDialogConfirmed called: {DataTitle}, {ProductsCount} products", data.Title, data.Products.Count); |
| 487 | + isAnyDialogVisible = false; |
| 488 | + if (OnSaveAsConfirmed.HasDelegate) |
| 489 | + await OnSaveAsConfirmed.InvokeAsync(data); |
| 490 | + } |
| 491 | + |
| 492 | + private Task OnDialogSelectedProductsChanged(List<Product> products) |
| 493 | + { |
| 494 | + DialogSelectedProducts = products; |
| 495 | + return Task.CompletedTask; |
| 496 | + } |
430 | 497 | } |
0 commit comments