Skip to content

Implement edit and delete operations for custom menu entries (US2)#3308

Draft
Copilot wants to merge 12 commits intomainfrom
copilot/add-custom-menu-entries
Draft

Implement edit and delete operations for custom menu entries (US2)#3308
Copilot wants to merge 12 commits intomainfrom
copilot/add-custom-menu-entries

Conversation

Copy link
Contributor

Copilot AI commented Jan 31, 2026

Description

What's new?

Adds full CRUD capabilities to custom menu entries feature. User Story 1 (create/list) was complete; this implements User Story 2 (edit/delete).

Backend changes:

  • PUT /api/menu-entries/{id} - Updates entry with validation (name uniqueness excluding self, URL format, 100 char limit)
  • DELETE /api/menu-entries/{id} - Hard deletes entry after existence check
  • Both endpoints require menuentry:write authorization
  • Returns proper status codes: 200 OK (update), 204 No Content (delete), 404 (not found), 400 (validation), 409 (duplicate)

Frontend changes:

  • Edit button opens pre-filled dialog with real-time validation and external/internal URL indicator
  • Delete button shows confirmation dialog before permanent removal
  • List refreshes automatically after operations
  • NavMenu handles deleted entries gracefully

Test coverage:

  • Service layer: update/delete with validation scenarios (duplicates, invalid URLs, missing entries)
  • Controller layer: PUT/DELETE endpoints with authorization and error responses
  • Client service layer: HTTP client wrapper tests for all operations
  • All 1610 tests passing (100% pass rate)
  • Fixed HTTP content type assertions in MenuEntryClientService tests to match PostAsJsonAsync/PutAsJsonAsync/PatchAsJsonAsync implementation
  • Added IMenuEntryClientService mock to NavMenu and MainLayout test fixtures to support component rendering

Validation enforced:

  • Name: required, max 100 chars, unique (excluding self on update)
  • URL: required, valid HTTP/HTTPS or relative path
  • ID matching between URL parameter and request body
  • Entity existence before update/delete

What kind of change does this PR introduce?

  • Bugfix
  • Feature
  • Code style update (formatting, local variables)
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • CI related changes
  • Documentation content changes
  • Tests
  • Other
Original prompt

This section details on the original issue you should resolve

<issue_title>Feature: Creation of custom menu entries</issue_title>
<issue_description>Is your feature request related to a problem? Please describe.
It could be nice to be able to add custom menu entries, either with quick links to specific internal resources, or resources external to the portal (monitoring solution, documentation, ticketing site, ...)

Describe the solution you'd like
Make it possible to create the aforementioned menu entries from the UI (with RBAC when implemented) and from the API. The links would be in a separate section. We should be able to decide the order of the menu entries in this section, and also where to put this section (first, last, somewhere between existing menu entries...)

Describe alternatives you've considered
N/A

Additional context
We have a lot of web resources linked to our IoT solution on-site and we would like to make it easier for our user to navigate to them if they don't have all the links</issue_description>

Comments on the Issue (you are @copilot in this section)

Custom agent used: speckit.specify
Create or update the feature specification from a natural language feature description.


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI changed the title [WIP] Add feature for custom menu entries creation Add feature specification for custom menu entries Jan 31, 2026
Copilot AI requested a review from kbeaugrand January 31, 2026 16:20
Copilot AI changed the title Add feature specification for custom menu entries Add feature specification and implementation plan for custom menu entries Jan 31, 2026
Copilot AI changed the title Add feature specification and implementation plan for custom menu entries Add complete feature planning for custom menu entries Jan 31, 2026
Copilot AI changed the title Add complete feature planning for custom menu entries Add custom menu entries backend (REST API, domain model, migrations) Jan 31, 2026
Copilot AI changed the title Add custom menu entries backend (REST API, domain model, migrations) Add custom menu entries for external and internal resource links Feb 1, 2026
Copilot AI changed the title Add custom menu entries for external and internal resource links Add unit tests for custom menu entries feature Feb 1, 2026
Copilot AI changed the title Add unit tests for custom menu entries feature Document remaining user stories for custom menu entries feature Feb 1, 2026
Copilot AI changed the title Document remaining user stories for custom menu entries feature Add User Story 2 implementation planning for custom menu entries Feb 1, 2026
@kbeaugrand kbeaugrand force-pushed the copilot/add-custom-menu-entries branch from 8476d5e to 1dcd3c8 Compare February 1, 2026 12:51
Copilot AI changed the title Add User Story 2 implementation planning for custom menu entries Implement edit and delete operations for custom menu entries (US2) Feb 1, 2026
Copy link
Contributor

@github-advanced-security github-advanced-security bot left a comment

Choose a reason for hiding this comment

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

CodeQL found more than 20 potential problems in the proposed changes. Check the Files changed tab for more details.

@kbeaugrand
Copy link
Member

@copilot fix unit tests

Copy link
Contributor Author

Copilot AI commented Feb 2, 2026

@copilot fix unit tests

Fixed in commit e315ced. All 29 MenuEntry tests now passing (was 26/29).

The issue was incorrect HTTP content type assertions - tests expected StringContent but PostAsJsonAsync/PutAsJsonAsync/PatchAsJsonAsync create ObjectContent<T> or JsonContent. Updated to match patterns used in other client service tests.

@kbeaugrand
Copy link
Member

@copilot some tests still failed

Copy link
Contributor Author

Copilot AI commented Feb 2, 2026

@copilot some tests still failed

Fixed in commit 8ea8478. All 1610 tests now passing (was 1577/1610).

The issue was that NavMenu and MainLayout tests were missing the IMenuEntryClientService mock. When NavMenu was updated to load custom menu entries, it injected this service, but the test fixtures didn't register it. Added mock setup to both NavMenuTests and MainLayoutTests following the same pattern used for other client services in the codebase.

@codecov
Copy link

codecov bot commented Feb 2, 2026

Codecov Report

❌ Patch coverage is 33.81443% with 321 lines in your changes missing coverage. Please review.
✅ Project coverage is 79.83%. Comparing base (d991cb6) to head (67ebf97).

Files with missing lines Patch % Lines
...l.Client/Pages/MenuEntries/MenuEntryListPage.razor 0.00% 85 Missing ⚠️
...ient/Dialogs/MenuEntries/EditMenuEntryDialog.razor 0.00% 79 Missing ⚠️
...nt/Dialogs/MenuEntries/CreateMenuEntryDialog.razor 0.00% 68 Missing ⚠️
...l.Server/Controllers/v1.0/MenuEntriesController.cs 58.44% 30 Missing and 2 partials ⚠️
...Portal.Infrastructure/Services/MenuEntryService.cs 72.04% 20 Missing and 6 partials ⚠️
src/IoTHub.Portal.Client/Shared/NavMenu.razor 33.33% 13 Missing and 1 partial ⚠️
...Infrastructure/Repositories/MenuEntryRepository.cs 0.00% 7 Missing ⚠️
...Hub.Portal.Client/Dialogs/DeleteConfirmation.razor 0.00% 6 Missing ⚠️
...b.Portal.Client/Services/MenuEntryClientService.cs 92.59% 0 Missing and 2 partials ⚠️
...b.Portal.Shared/Extensions/PermissionsExtension.cs 0.00% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3308      +/-   ##
==========================================
- Coverage   81.38%   79.83%   -1.56%     
==========================================
  Files         376      387      +11     
  Lines       14360    14845     +485     
  Branches     1224     1282      +58     
==========================================
+ Hits        11687    11851     +164     
- Misses       2295     2605     +310     
- Partials      378      389      +11     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copilot AI and others added 12 commits February 3, 2026 11:17
…tries)

Co-authored-by: kbeaugrand <9513635+kbeaugrand@users.noreply.github.com>
Co-authored-by: kbeaugrand <9513635+kbeaugrand@users.noreply.github.com>
Co-authored-by: kbeaugrand <9513635+kbeaugrand@users.noreply.github.com>
…d migrations for MenuEntry

- Added MenuEntryRead and MenuEntryWrite permissions to PortalPermissions enum
- Added menu entry policies (GetAllMenuEntries, GetMenuEntry, CreateMenuEntry, UpdateMenuEntry, DeleteMenuEntry, UpdateMenuEntryOrder)
- Created MenuEntry entity with properties: Id, Name, Url, Order, IsEnabled, IsExternal, CreatedAt, UpdatedAt
- Created MenuEntryDto with validation attributes
- Created IMenuEntryRepository interface with GetByNameAsync method
- Implemented MenuEntryRepository
- Added MenuEntries DbSet to PortalDbContext
- Created database migrations for PostgreSQL and MySQL
- Registered MenuEntryRepository in DI container

Completed tasks: T001-T009
- Created IMenuEntryService interface with CRUD and order management methods
- Created MenuEntryProfile AutoMapper configuration
- Implemented MenuEntryService with validation:
  * Name required, max 100 chars
  * Valid HTTP/HTTPS URL format
  * Duplicate name check
  * Auto-detect external URLs
- Created MenuEntriesController with REST API endpoints:
  * POST /api/menu-entries - Create menu entry (menuentry:write)
  * GET /api/menu-entries - List all menu entries (menuentry:read)
  * GET /api/menu-entries/{id} - Get single menu entry (menuentry:read)
  * PUT /api/menu-entries/{id} - Update menu entry (menuentry:write)
  * DELETE /api/menu-entries/{id} - Delete menu entry (menuentry:write)
  * PATCH /api/menu-entries/{id}/order - Update order (menuentry:write)
- Registered MenuEntryService in DI container
- Added proper error handling: 400 Bad Request, 401 Unauthorized, 404 Not Found, 409 Conflict, 500 Internal Server Error

Completed tasks: T015-T022
- Created IMenuEntryClientService interface with all CRUD methods
- Implemented MenuEntryClientService using HttpClient:
  * CreateMenuEntry - POST to /api/menu-entries
  * GetMenuEntries - GET /api/menu-entries
  * GetMenuEntryById - GET /api/menu-entries/{id}
  * UpdateMenuEntry - PUT /api/menu-entries/{id}
  * DeleteMenuEntry - DELETE /api/menu-entries/{id}
  * UpdateMenuEntryOrder - PATCH /api/menu-entries/{id}/order
- Registered MenuEntryClientService in Program.cs DI container
- Added proper error handling with EnsureSuccessStatusCode

Completed tasks: T023-T025
…u integration)

Co-authored-by: kbeaugrand <9513635+kbeaugrand@users.noreply.github.com>
Co-authored-by: kbeaugrand <9513635+kbeaugrand@users.noreply.github.com>
…tries)

Co-authored-by: kbeaugrand <9513635+kbeaugrand@users.noreply.github.com>
- Add edit and delete functionality for menu entries
- Implement PUT and DELETE endpoints in MenuEntriesController
- Add UpdateMenuEntry and DeleteMenuEntry methods to MenuEntryService
- Create EditMenuEntryDialog component for editing entries
- Add edit and delete buttons to MenuEntryListPage with confirmation
- Update MenuEntryClientService with update and delete operations
- Fix migration files to follow code style conventions
- Update controller to return 204 No Content for successful updates
- Reorganize validation order in MenuEntryService (URL before duplicate check)
- Add proper error handling for 404 Not Found responses
- Mark tasks T036-T056 as complete in tasks.md

All core US2 tests passing (26/29 total MenuEntry tests pass)
…ntService

Co-authored-by: kbeaugrand <9513635+kbeaugrand@users.noreply.github.com>
Co-authored-by: kbeaugrand <9513635+kbeaugrand@users.noreply.github.com>
@kbeaugrand kbeaugrand force-pushed the copilot/add-custom-menu-entries branch from 8ea8478 to 67ebf97 Compare February 3, 2026 10:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature: Creation of custom menu entries

2 participants