Conversation
…itPage handlers Agent-Logs-Url: https://github.com/mpaulosky/IssueManager/sessions/21c1599b-6f0d-46c7-8001-d550af731d1e Co-authored-by: mpaulosky <60372079+mpaulosky@users.noreply.github.com>
Agent-Logs-Url: https://github.com/mpaulosky/IssueManager/sessions/21c1599b-6f0d-46c7-8001-d550af731d1e Co-authored-by: mpaulosky <60372079+mpaulosky@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Fixes incomplete field mapping when updating issues/categories/statuses by ensuring update commands include all relevant fields and the API resolves category/status DTOs when IDs are provided.
Changes:
- Extend
UpdateIssueCommandwith optionalCategoryId/StatusIdand map them from the edit UI. - Update
UpdateIssueHandlerto resolve and apply category/status DTOs (or returnNotFoundif missing). - Update unit/integration tests to use the new handler constructor and add coverage for category/status update paths.
Reviewed changes
Copilot reviewed 7 out of 8 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
src/Shared/Contracts/UpdateIssueCommand.cs |
Adds CategoryId / StatusId fields to support updating related entities. |
src/Api/Handlers/Issues/UpdateIssueHandler.cs |
Injects category/status repositories and resolves DTOs before updating the issue. |
src/Web/Components/Features/Issues/EditIssuePage.razor |
Maps Title, CategoryId, and StatusId into UpdateIssueCommand during submit. |
src/Web/Components/Features/Categories/EditCategoryPage.razor |
Ensures CategoryName is included in UpdateCategoryCommand. |
src/Web/Components/Features/Statuses/EditStatusPage.razor |
Ensures StatusName is included in UpdateStatusCommand. |
tests/Api.Tests.Unit/Handlers/Issues/UpdateIssueHandlerTests.cs |
Updates constructor usage and adds category/status update/not-found tests. |
tests/Api.Tests.Integration/Handlers/UpdateIssueHandlerIntegrationTests.cs |
Updates handler construction to include substituted category/status repositories. |
src/Web/package-lock.json |
Reformatted lockfile (appears whitespace-only), increasing diff size/noise. |
| var statusResult = await _statusRepository.GetByIdAsync(command.StatusId.Value, cancellationToken); | ||
| if (!statusResult.Success || statusResult.Value is null) | ||
| return Result.Fail<IssueDto>($"Status with ID '{command.StatusId}' was not found.", ResultErrorCode.NotFound); | ||
| status = statusResult.Value; |
There was a problem hiding this comment.
Same concern for status resolution: if StatusId is posted but unchanged, UpdateIssueHandler will still hit the status repository. Adding an ID equality check before fetching can reduce DB traffic in the common "edit title/description" path.
| var statusResult = await _statusRepository.GetByIdAsync(command.StatusId.Value, cancellationToken); | |
| if (!statusResult.Success || statusResult.Value is null) | |
| return Result.Fail<IssueDto>($"Status with ID '{command.StatusId}' was not found.", ResultErrorCode.NotFound); | |
| status = statusResult.Value; | |
| var currentStatusId = getResult.Value.Status.Id; | |
| if (command.StatusId.Value != currentStatusId) | |
| { | |
| var statusResult = await _statusRepository.GetByIdAsync(command.StatusId.Value, cancellationToken); | |
| if (!statusResult.Success || statusResult.Value is null) | |
| return Result.Fail<IssueDto>($"Status with ID '{command.StatusId}' was not found.", ResultErrorCode.NotFound); | |
| status = statusResult.Value; | |
| } |
| { | ||
| "name": "Web", | ||
| "lockfileVersion": 3, | ||
| "requires": true, | ||
| "packages": { | ||
| "": { | ||
| "dependencies": { | ||
| "@tailwindcss/cli": "^4.2.1", | ||
| "tailwindcss": "^4.2.1" | ||
| } | ||
| }, | ||
| "node_modules/@jridgewell/gen-mapping": { | ||
| "version": "0.3.13", | ||
| "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", | ||
| "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", | ||
| "license": "MIT", | ||
| "dependencies": { | ||
| "@jridgewell/sourcemap-codec": "^1.5.0", | ||
| "@jridgewell/trace-mapping": "^0.3.24" | ||
| } | ||
| }, | ||
| "node_modules/@jridgewell/remapping": { | ||
| "version": "2.3.5", | ||
| "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", | ||
| "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", | ||
| "license": "MIT", | ||
| "dependencies": { | ||
| "@jridgewell/gen-mapping": "^0.3.5", | ||
| "@jridgewell/trace-mapping": "^0.3.24" | ||
| } | ||
| }, | ||
| "node_modules/@jridgewell/resolve-uri": { | ||
| "version": "3.1.2", | ||
| "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", | ||
| "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", | ||
| "license": "MIT", | ||
| "engines": { | ||
| "node": ">=6.0.0" | ||
| } | ||
| }, | ||
| "node_modules/@jridgewell/sourcemap-codec": { | ||
| "version": "1.5.5", | ||
| "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", | ||
| "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", | ||
| "license": "MIT" | ||
| }, | ||
| "node_modules/@jridgewell/trace-mapping": { | ||
| "version": "0.3.31", | ||
| "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", | ||
| "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", | ||
| "license": "MIT", | ||
| "dependencies": { | ||
| "@jridgewell/resolve-uri": "^3.1.0", | ||
| "@jridgewell/sourcemap-codec": "^1.4.14" | ||
| } | ||
| }, | ||
| "node_modules/@parcel/watcher": { | ||
| "version": "2.5.6", | ||
| "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.6.tgz", | ||
| "integrity": "sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==", | ||
| "hasInstallScript": true, | ||
| "license": "MIT", | ||
| "dependencies": { | ||
| "detect-libc": "^2.0.3", | ||
| "is-glob": "^4.0.3", | ||
| "node-addon-api": "^7.0.0", | ||
| "picomatch": "^4.0.3" | ||
| }, | ||
| "engines": { | ||
| "node": ">= 10.0.0" | ||
| }, | ||
| "funding": { | ||
| "type": "opencollective", | ||
| "url": "https://opencollective.com/parcel" | ||
| }, | ||
| "optionalDependencies": { | ||
| "@parcel/watcher-android-arm64": "2.5.6", | ||
| "@parcel/watcher-darwin-arm64": "2.5.6", | ||
| "@parcel/watcher-darwin-x64": "2.5.6", | ||
| "@parcel/watcher-freebsd-x64": "2.5.6", | ||
| "@parcel/watcher-linux-arm-glibc": "2.5.6", | ||
| "@parcel/watcher-linux-arm-musl": "2.5.6", | ||
| "@parcel/watcher-linux-arm64-glibc": "2.5.6", | ||
| "@parcel/watcher-linux-arm64-musl": "2.5.6", | ||
| "@parcel/watcher-linux-x64-glibc": "2.5.6", | ||
| "@parcel/watcher-linux-x64-musl": "2.5.6", | ||
| "@parcel/watcher-win32-arm64": "2.5.6", | ||
| "@parcel/watcher-win32-ia32": "2.5.6", | ||
| "@parcel/watcher-win32-x64": "2.5.6" | ||
| } | ||
| }, | ||
| "node_modules/@parcel/watcher-android-arm64": { | ||
| "version": "2.5.6", | ||
| "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.6.tgz", | ||
| "integrity": "sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A==", | ||
| "cpu": [ | ||
| "arm64" | ||
| ], | ||
| "license": "MIT", | ||
| "optional": true, | ||
| "os": [ | ||
| "android" | ||
| ], | ||
| "engines": { | ||
| "node": ">= 10.0.0" | ||
| }, | ||
| "funding": { | ||
| "type": "opencollective", | ||
| "url": "https://opencollective.com/parcel" | ||
| } | ||
| }, | ||
| "node_modules/@parcel/watcher-darwin-arm64": { | ||
| "version": "2.5.6", | ||
| "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.6.tgz", | ||
| "integrity": "sha512-Z2ZdrnwyXvvvdtRHLmM4knydIdU9adO3D4n/0cVipF3rRiwP+3/sfzpAwA/qKFL6i1ModaabkU7IbpeMBgiVEA==", | ||
| "cpu": [ | ||
| "arm64" | ||
| ], | ||
| "license": "MIT", | ||
| "optional": true, | ||
| "os": [ | ||
| "darwin" | ||
| ], | ||
| "engines": { | ||
| "node": ">= 10.0.0" | ||
| }, | ||
| "funding": { | ||
| "type": "opencollective", | ||
| "url": "https://opencollective.com/parcel" | ||
| } | ||
| }, | ||
| "node_modules/@parcel/watcher-darwin-x64": { | ||
| "version": "2.5.6", | ||
| "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.6.tgz", | ||
| "integrity": "sha512-HgvOf3W9dhithcwOWX9uDZyn1lW9R+7tPZ4sug+NGrGIo4Rk1hAXLEbcH1TQSqxts0NYXXlOWqVpvS1SFS4fRg==", | ||
| "cpu": [ | ||
| "x64" | ||
| ], | ||
| "license": "MIT", | ||
| "optional": true, | ||
| "os": [ | ||
| "darwin" | ||
| ], | ||
| "engines": { | ||
| "node": ">= 10.0.0" | ||
| }, | ||
| "funding": { | ||
| "type": "opencollective", | ||
| "url": "https://opencollective.com/parcel" | ||
| } | ||
| }, | ||
| "node_modules/@parcel/watcher-freebsd-x64": { | ||
| "version": "2.5.6", | ||
| "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.6.tgz", | ||
| "integrity": "sha512-vJVi8yd/qzJxEKHkeemh7w3YAn6RJCtYlE4HPMoVnCpIXEzSrxErBW5SJBgKLbXU3WdIpkjBTeUNtyBVn8TRng==", | ||
| "cpu": [ | ||
| "x64" | ||
| ], | ||
| "license": "MIT", | ||
| "optional": true, | ||
| "os": [ | ||
| "freebsd" | ||
| ], | ||
| "engines": { | ||
| "node": ">= 10.0.0" | ||
| }, | ||
| "funding": { | ||
| "type": "opencollective", | ||
| "url": "https://opencollective.com/parcel" | ||
| } | ||
| }, | ||
| "node_modules/@parcel/watcher-linux-arm-glibc": { | ||
| "version": "2.5.6", | ||
| "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.6.tgz", | ||
| "integrity": "sha512-9JiYfB6h6BgV50CCfasfLf/uvOcJskMSwcdH1PHH9rvS1IrNy8zad6IUVPVUfmXr+u+Km9IxcfMLzgdOudz9EQ==", | ||
| "cpu": [ | ||
| "arm" | ||
| ], | ||
| "license": "MIT", | ||
| "optional": true, | ||
| "os": [ | ||
| "linux" | ||
| ], | ||
| "engines": { | ||
| "node": ">= 10.0.0" | ||
| }, | ||
| "funding": { | ||
| "type": "opencollective", | ||
| "url": "https://opencollective.com/parcel" | ||
| } | ||
| }, | ||
| "node_modules/@parcel/watcher-linux-arm-musl": { | ||
| "version": "2.5.6", | ||
| "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.6.tgz", | ||
| "integrity": "sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg==", | ||
| "cpu": [ | ||
| "arm" | ||
| ], | ||
| "license": "MIT", | ||
| "optional": true, | ||
| "os": [ | ||
| "linux" | ||
| ], | ||
| "engines": { | ||
| "node": ">= 10.0.0" | ||
| }, | ||
| "funding": { | ||
| "type": "opencollective", | ||
| "url": "https://opencollective.com/parcel" | ||
| } | ||
| }, | ||
| "node_modules/@parcel/watcher-linux-arm64-glibc": { | ||
| "version": "2.5.6", | ||
| "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.6.tgz", | ||
| "integrity": "sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA==", | ||
| "cpu": [ | ||
| "arm64" | ||
| ], | ||
| "license": "MIT", | ||
| "optional": true, | ||
| "os": [ | ||
| "linux" | ||
| ], | ||
| "engines": { | ||
| "node": ">= 10.0.0" | ||
| }, | ||
| "funding": { | ||
| "type": "opencollective", | ||
| "url": "https://opencollective.com/parcel" | ||
| } | ||
| }, | ||
| "node_modules/@parcel/watcher-linux-arm64-musl": { | ||
| "version": "2.5.6", | ||
| "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.6.tgz", | ||
| "integrity": "sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA==", | ||
| "cpu": [ | ||
| "arm64" | ||
| ], | ||
| "license": "MIT", | ||
| "optional": true, | ||
| "os": [ | ||
| "linux" | ||
| ], | ||
| "engines": { | ||
| "node": ">= 10.0.0" | ||
| }, | ||
| "funding": { | ||
| "type": "opencollective", | ||
| "url": "https://opencollective.com/parcel" | ||
| } | ||
| }, | ||
| "node_modules/@parcel/watcher-linux-x64-glibc": { | ||
| "version": "2.5.6", | ||
| "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.6.tgz", | ||
| "integrity": "sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==", | ||
| "cpu": [ | ||
| "x64" | ||
| ], | ||
| "license": "MIT", | ||
| "optional": true, | ||
| "os": [ | ||
| "linux" | ||
| ], | ||
| "engines": { | ||
| "node": ">= 10.0.0" | ||
| }, | ||
| "funding": { | ||
| "type": "opencollective", | ||
| "url": "https://opencollective.com/parcel" | ||
| } | ||
| }, | ||
| "node_modules/@parcel/watcher-linux-x64-musl": { | ||
| "version": "2.5.6", | ||
| "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.6.tgz", | ||
| "integrity": "sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==", | ||
| "cpu": [ | ||
| "x64" | ||
| ], | ||
| "license": "MIT", | ||
| "optional": true, | ||
| "os": [ | ||
| "linux" | ||
| ], | ||
| "engines": { | ||
| "node": ">= 10.0.0" | ||
| }, | ||
| "funding": { | ||
| "type": "opencollective", | ||
| "url": "https://opencollective.com/parcel" | ||
| } | ||
| }, | ||
| "node_modules/@parcel/watcher-win32-arm64": { | ||
| "version": "2.5.6", | ||
| "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.6.tgz", | ||
| "integrity": "sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q==", | ||
| "cpu": [ | ||
| "arm64" | ||
| ], | ||
| "license": "MIT", | ||
| "optional": true, | ||
| "os": [ | ||
| "win32" | ||
| ], | ||
| "engines": { | ||
| "node": ">= 10.0.0" | ||
| }, | ||
| "funding": { | ||
| "type": "opencollective", | ||
| "url": "https://opencollective.com/parcel" | ||
| } | ||
| }, | ||
| "node_modules/@parcel/watcher-win32-ia32": { | ||
| "version": "2.5.6", | ||
| "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.6.tgz", | ||
| "integrity": "sha512-k35yLp1ZMwwee3Ez/pxBi5cf4AoBKYXj00CZ80jUz5h8prpiaQsiRPKQMxoLstNuqe2vR4RNPEAEcjEFzhEz/g==", | ||
| "cpu": [ | ||
| "ia32" | ||
| ], | ||
| "license": "MIT", | ||
| "optional": true, | ||
| "os": [ | ||
| "win32" | ||
| ], | ||
| "engines": { | ||
| "node": ">= 10.0.0" | ||
| }, | ||
| "funding": { | ||
| "type": "opencollective", | ||
| "url": "https://opencollective.com/parcel" | ||
| } | ||
| }, | ||
| "node_modules/@parcel/watcher-win32-x64": { | ||
| "version": "2.5.6", | ||
| "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.6.tgz", | ||
| "integrity": "sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw==", | ||
| "cpu": [ | ||
| "x64" | ||
| ], | ||
| "license": "MIT", | ||
| "optional": true, | ||
| "os": [ | ||
| "win32" | ||
| ], | ||
| "engines": { | ||
| "node": ">= 10.0.0" | ||
| }, | ||
| "funding": { | ||
| "type": "opencollective", | ||
| "url": "https://opencollective.com/parcel" | ||
| } | ||
| }, | ||
| "node_modules/@tailwindcss/cli": { | ||
| "version": "4.2.1", | ||
| "resolved": "https://registry.npmjs.org/@tailwindcss/cli/-/cli-4.2.1.tgz", | ||
| "integrity": "sha512-b7MGn51IA80oSG+7fuAgzfQ+7pZBgjzbqwmiv6NO7/+a1sev32cGqnwhscT7h0EcAvMa9r7gjRylqOH8Xhc4DA==", | ||
| "license": "MIT", | ||
| "dependencies": { | ||
| "@parcel/watcher": "^2.5.1", | ||
| "@tailwindcss/node": "4.2.1", | ||
| "@tailwindcss/oxide": "4.2.1", | ||
| "enhanced-resolve": "^5.19.0", | ||
| "mri": "^1.2.0", | ||
| "picocolors": "^1.1.1", | ||
| "tailwindcss": "4.2.1" | ||
| }, | ||
| "bin": { | ||
| "tailwindcss": "dist/index.mjs" | ||
| } | ||
| }, | ||
| "node_modules/@tailwindcss/node": { | ||
| "version": "4.2.1", | ||
| "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.2.1.tgz", | ||
| "integrity": "sha512-jlx6sLk4EOwO6hHe1oCGm1Q4AN/s0rSrTTPBGPM0/RQ6Uylwq17FuU8IeJJKEjtc6K6O07zsvP+gDO6MMWo7pg==", | ||
| "license": "MIT", | ||
| "dependencies": { | ||
| "@jridgewell/remapping": "^2.3.5", | ||
| "enhanced-resolve": "^5.19.0", | ||
| "jiti": "^2.6.1", | ||
| "lightningcss": "1.31.1", | ||
| "magic-string": "^0.30.21", | ||
| "source-map-js": "^1.2.1", | ||
| "tailwindcss": "4.2.1" | ||
| } | ||
| }, | ||
| "node_modules/@tailwindcss/oxide": { | ||
| "version": "4.2.1", | ||
| "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.2.1.tgz", | ||
| "integrity": "sha512-yv9jeEFWnjKCI6/T3Oq50yQEOqmpmpfzG1hcZsAOaXFQPfzWprWrlHSdGPEF3WQTi8zu8ohC9Mh9J470nT5pUw==", | ||
| "license": "MIT", | ||
| "engines": { | ||
| "node": ">= 20" | ||
| }, | ||
| "optionalDependencies": { | ||
| "@tailwindcss/oxide-android-arm64": "4.2.1", | ||
| "@tailwindcss/oxide-darwin-arm64": "4.2.1", | ||
| "@tailwindcss/oxide-darwin-x64": "4.2.1", | ||
| "@tailwindcss/oxide-freebsd-x64": "4.2.1", | ||
| "@tailwindcss/oxide-linux-arm-gnueabihf": "4.2.1", | ||
| "@tailwindcss/oxide-linux-arm64-gnu": "4.2.1", | ||
| "@tailwindcss/oxide-linux-arm64-musl": "4.2.1", | ||
| "@tailwindcss/oxide-linux-x64-gnu": "4.2.1", | ||
| "@tailwindcss/oxide-linux-x64-musl": "4.2.1", | ||
| "@tailwindcss/oxide-wasm32-wasi": "4.2.1", | ||
| "@tailwindcss/oxide-win32-arm64-msvc": "4.2.1", | ||
| "@tailwindcss/oxide-win32-x64-msvc": "4.2.1" | ||
| } | ||
| }, | ||
| "node_modules/@tailwindcss/oxide-android-arm64": { | ||
| "version": "4.2.1", | ||
| "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.2.1.tgz", | ||
| "integrity": "sha512-eZ7G1Zm5EC8OOKaesIKuw77jw++QJ2lL9N+dDpdQiAB/c/B2wDh0QPFHbkBVrXnwNugvrbJFk1gK2SsVjwWReg==", | ||
| "cpu": [ | ||
| "arm64" | ||
| ], | ||
| "license": "MIT", | ||
| "optional": true, | ||
| "os": [ | ||
| "android" | ||
| ], | ||
| "engines": { | ||
| "node": ">= 20" | ||
| } | ||
| }, | ||
| "node_modules/@tailwindcss/oxide-darwin-arm64": { | ||
| "version": "4.2.1", | ||
| "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.2.1.tgz", | ||
| "integrity": "sha512-q/LHkOstoJ7pI1J0q6djesLzRvQSIfEto148ppAd+BVQK0JYjQIFSK3JgYZJa+Yzi0DDa52ZsQx2rqytBnf8Hw==", | ||
| "cpu": [ | ||
| "arm64" | ||
| ], | ||
| "license": "MIT", | ||
| "optional": true, | ||
| "os": [ | ||
| "darwin" | ||
| ], | ||
| "engines": { | ||
| "node": ">= 20" | ||
| } | ||
| }, | ||
| "node_modules/@tailwindcss/oxide-darwin-x64": { | ||
| "version": "4.2.1", | ||
| "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.2.1.tgz", | ||
| "integrity": "sha512-/f/ozlaXGY6QLbpvd/kFTro2l18f7dHKpB+ieXz+Cijl4Mt9AI2rTrpq7V+t04nK+j9XBQHnSMdeQRhbGyt6fw==", | ||
| "cpu": [ | ||
| "x64" | ||
| ], | ||
| "license": "MIT", | ||
| "optional": true, | ||
| "os": [ | ||
| "darwin" | ||
| ], | ||
| "engines": { | ||
| "node": ">= 20" | ||
| } | ||
| }, | ||
| "node_modules/@tailwindcss/oxide-freebsd-x64": { | ||
| "version": "4.2.1", | ||
| "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.2.1.tgz", | ||
| "integrity": "sha512-5e/AkgYJT/cpbkys/OU2Ei2jdETCLlifwm7ogMC7/hksI2fC3iiq6OcXwjibcIjPung0kRtR3TxEITkqgn0TcA==", | ||
| "cpu": [ | ||
| "x64" | ||
| ], | ||
| "license": "MIT", | ||
| "optional": true, | ||
| "os": [ | ||
| "freebsd" | ||
| ], | ||
| "engines": { | ||
| "node": ">= 20" | ||
| } | ||
| }, | ||
| "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { | ||
| "version": "4.2.1", | ||
| "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.2.1.tgz", | ||
| "integrity": "sha512-Uny1EcVTTmerCKt/1ZuKTkb0x8ZaiuYucg2/kImO5A5Y/kBz41/+j0gxUZl+hTF3xkWpDmHX+TaWhOtba2Fyuw==", | ||
| "cpu": [ | ||
| "arm" | ||
| ], | ||
| "license": "MIT", | ||
| "optional": true, | ||
| "os": [ | ||
| "linux" | ||
| ], | ||
| "engines": { | ||
| "node": ">= 20" | ||
| } | ||
| }, | ||
| "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { | ||
| "version": "4.2.1", | ||
| "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.2.1.tgz", | ||
| "integrity": "sha512-CTrwomI+c7n6aSSQlsPL0roRiNMDQ/YzMD9EjcR+H4f0I1SQ8QqIuPnsVp7QgMkC1Qi8rtkekLkOFjo7OlEFRQ==", | ||
| "cpu": [ | ||
| "arm64" | ||
| ], | ||
| "license": "MIT", | ||
| "optional": true, | ||
| "os": [ | ||
| "linux" | ||
| ], | ||
| "engines": { | ||
| "node": ">= 20" | ||
| } | ||
| }, | ||
| "node_modules/@tailwindcss/oxide-linux-arm64-musl": { | ||
| "version": "4.2.1", | ||
| "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.2.1.tgz", | ||
| "integrity": "sha512-WZA0CHRL/SP1TRbA5mp9htsppSEkWuQ4KsSUumYQnyl8ZdT39ntwqmz4IUHGN6p4XdSlYfJwM4rRzZLShHsGAQ==", | ||
| "cpu": [ | ||
| "arm64" | ||
| ], | ||
| "license": "MIT", | ||
| "optional": true, | ||
| "os": [ | ||
| "linux" | ||
| ], | ||
| "engines": { | ||
| "node": ">= 20" | ||
| } | ||
| }, | ||
| "node_modules/@tailwindcss/oxide-linux-x64-gnu": { | ||
| "version": "4.2.1", | ||
| "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.2.1.tgz", | ||
| "integrity": "sha512-qMFzxI2YlBOLW5PhblzuSWlWfwLHaneBE0xHzLrBgNtqN6mWfs+qYbhryGSXQjFYB1Dzf5w+LN5qbUTPhW7Y5g==", | ||
| "cpu": [ | ||
| "x64" | ||
| ], | ||
| "license": "MIT", | ||
| "optional": true, | ||
| "os": [ | ||
| "linux" | ||
| ], | ||
| "engines": { | ||
| "node": ">= 20" | ||
| } | ||
| }, | ||
| "node_modules/@tailwindcss/oxide-linux-x64-musl": { | ||
| "version": "4.2.1", | ||
| "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.2.1.tgz", | ||
| "integrity": "sha512-5r1X2FKnCMUPlXTWRYpHdPYUY6a1Ar/t7P24OuiEdEOmms5lyqjDRvVY1yy9Rmioh+AunQ0rWiOTPE8F9A3v5g==", | ||
| "cpu": [ | ||
| "x64" | ||
| ], | ||
| "license": "MIT", | ||
| "optional": true, | ||
| "os": [ | ||
| "linux" | ||
| ], | ||
| "engines": { | ||
| "node": ">= 20" | ||
| } | ||
| }, | ||
| "node_modules/@tailwindcss/oxide-wasm32-wasi": { | ||
| "version": "4.2.1", | ||
| "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.2.1.tgz", | ||
| "integrity": "sha512-MGFB5cVPvshR85MTJkEvqDUnuNoysrsRxd6vnk1Lf2tbiqNlXpHYZqkqOQalydienEWOHHFyyuTSYRsLfxFJ2Q==", | ||
| "bundleDependencies": [ | ||
| "@napi-rs/wasm-runtime", | ||
| "@emnapi/core", | ||
| "@emnapi/runtime", | ||
| "@tybys/wasm-util", | ||
| "@emnapi/wasi-threads", | ||
| "tslib" | ||
| ], | ||
| "cpu": [ | ||
| "wasm32" | ||
| ], | ||
| "license": "MIT", | ||
| "optional": true, | ||
| "dependencies": { | ||
| "@emnapi/core": "^1.8.1", | ||
| "@emnapi/runtime": "^1.8.1", | ||
| "@emnapi/wasi-threads": "^1.1.0", | ||
| "@napi-rs/wasm-runtime": "^1.1.1", | ||
| "@tybys/wasm-util": "^0.10.1", | ||
| "tslib": "^2.8.1" | ||
| }, | ||
| "engines": { | ||
| "node": ">=14.0.0" | ||
| } | ||
| }, | ||
| "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/core": { | ||
| "version": "1.8.1", | ||
| "inBundle": true, | ||
| "license": "MIT", | ||
| "optional": true, | ||
| "dependencies": { | ||
| "@emnapi/wasi-threads": "1.1.0", | ||
| "tslib": "^2.4.0" | ||
| } | ||
| }, | ||
| "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/runtime": { | ||
| "version": "1.8.1", | ||
| "inBundle": true, | ||
| "license": "MIT", | ||
| "optional": true, | ||
| "dependencies": { | ||
| "tslib": "^2.4.0" | ||
| } | ||
| }, | ||
| "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/wasi-threads": { | ||
| "version": "1.1.0", | ||
| "inBundle": true, | ||
| "license": "MIT", | ||
| "optional": true, | ||
| "dependencies": { | ||
| "tslib": "^2.4.0" | ||
| } | ||
| }, | ||
| "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@napi-rs/wasm-runtime": { | ||
| "version": "1.1.1", | ||
| "inBundle": true, | ||
| "license": "MIT", | ||
| "optional": true, | ||
| "dependencies": { | ||
| "@emnapi/core": "^1.7.1", | ||
| "@emnapi/runtime": "^1.7.1", | ||
| "@tybys/wasm-util": "^0.10.1" | ||
| }, | ||
| "funding": { | ||
| "type": "github", | ||
| "url": "https://github.com/sponsors/Brooooooklyn" | ||
| } | ||
| }, | ||
| "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@tybys/wasm-util": { | ||
| "version": "0.10.1", | ||
| "inBundle": true, | ||
| "license": "MIT", | ||
| "optional": true, | ||
| "dependencies": { | ||
| "tslib": "^2.4.0" | ||
| } | ||
| }, | ||
| "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/tslib": { | ||
| "version": "2.8.1", | ||
| "inBundle": true, | ||
| "license": "0BSD", | ||
| "optional": true | ||
| }, | ||
| "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { | ||
| "version": "4.2.1", | ||
| "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.2.1.tgz", | ||
| "integrity": "sha512-YlUEHRHBGnCMh4Nj4GnqQyBtsshUPdiNroZj8VPkvTZSoHsilRCwXcVKnG9kyi0ZFAS/3u+qKHBdDc81SADTRA==", | ||
| "cpu": [ | ||
| "arm64" | ||
| ], | ||
| "license": "MIT", | ||
| "optional": true, | ||
| "os": [ | ||
| "win32" | ||
| ], | ||
| "engines": { | ||
| "node": ">= 20" | ||
| } | ||
| }, | ||
| "node_modules/@tailwindcss/oxide-win32-x64-msvc": { | ||
| "version": "4.2.1", | ||
| "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.2.1.tgz", | ||
| "integrity": "sha512-rbO34G5sMWWyrN/idLeVxAZgAKWrn5LiR3/I90Q9MkA67s6T1oB0xtTe+0heoBvHSpbU9Mk7i6uwJnpo4u21XQ==", | ||
| "cpu": [ | ||
| "x64" | ||
| ], | ||
| "license": "MIT", | ||
| "optional": true, | ||
| "os": [ | ||
| "win32" | ||
| ], | ||
| "engines": { | ||
| "node": ">= 20" | ||
| } | ||
| }, | ||
| "node_modules/detect-libc": { | ||
| "version": "2.1.2", | ||
| "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", | ||
| "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", | ||
| "license": "Apache-2.0", | ||
| "engines": { | ||
| "node": ">=8" | ||
| } | ||
| }, | ||
| "node_modules/enhanced-resolve": { | ||
| "version": "5.20.0", | ||
| "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.20.0.tgz", | ||
| "integrity": "sha512-/ce7+jQ1PQ6rVXwe+jKEg5hW5ciicHwIQUagZkp6IufBoY3YDgdTTY1azVs0qoRgVmvsNB+rbjLJxDAeHHtwsQ==", | ||
| "license": "MIT", | ||
| "dependencies": { | ||
| "graceful-fs": "^4.2.4", | ||
| "tapable": "^2.3.0" | ||
| }, | ||
| "engines": { | ||
| "node": ">=10.13.0" | ||
| } | ||
| }, | ||
| "node_modules/graceful-fs": { | ||
| "version": "4.2.11", | ||
| "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", | ||
| "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", | ||
| "license": "ISC" | ||
| }, | ||
| "node_modules/is-extglob": { | ||
| "version": "2.1.1", | ||
| "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", | ||
| "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", | ||
| "license": "MIT", | ||
| "engines": { | ||
| "node": ">=0.10.0" | ||
| } | ||
| }, | ||
| "node_modules/is-glob": { | ||
| "version": "4.0.3", | ||
| "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", | ||
| "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", | ||
| "license": "MIT", | ||
| "dependencies": { | ||
| "is-extglob": "^2.1.1" | ||
| }, | ||
| "engines": { | ||
| "node": ">=0.10.0" | ||
| } | ||
| }, | ||
| "node_modules/jiti": { | ||
| "version": "2.6.1", | ||
| "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", | ||
| "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", | ||
| "license": "MIT", | ||
| "bin": { | ||
| "jiti": "lib/jiti-cli.mjs" | ||
| } | ||
| }, | ||
| "node_modules/lightningcss": { | ||
| "version": "1.31.1", | ||
| "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.31.1.tgz", | ||
| "integrity": "sha512-l51N2r93WmGUye3WuFoN5k10zyvrVs0qfKBhyC5ogUQ6Ew6JUSswh78mbSO+IU3nTWsyOArqPCcShdQSadghBQ==", | ||
| "license": "MPL-2.0", | ||
| "dependencies": { | ||
| "detect-libc": "^2.0.3" | ||
| }, | ||
| "engines": { | ||
| "node": ">= 12.0.0" | ||
| }, | ||
| "funding": { | ||
| "type": "opencollective", | ||
| "url": "https://opencollective.com/parcel" | ||
| }, | ||
| "optionalDependencies": { | ||
| "lightningcss-android-arm64": "1.31.1", | ||
| "lightningcss-darwin-arm64": "1.31.1", | ||
| "lightningcss-darwin-x64": "1.31.1", | ||
| "lightningcss-freebsd-x64": "1.31.1", | ||
| "lightningcss-linux-arm-gnueabihf": "1.31.1", | ||
| "lightningcss-linux-arm64-gnu": "1.31.1", | ||
| "lightningcss-linux-arm64-musl": "1.31.1", | ||
| "lightningcss-linux-x64-gnu": "1.31.1", | ||
| "lightningcss-linux-x64-musl": "1.31.1", | ||
| "lightningcss-win32-arm64-msvc": "1.31.1", | ||
| "lightningcss-win32-x64-msvc": "1.31.1" | ||
| } | ||
| }, | ||
| "node_modules/lightningcss-android-arm64": { | ||
| "version": "1.31.1", | ||
| "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.31.1.tgz", | ||
| "integrity": "sha512-HXJF3x8w9nQ4jbXRiNppBCqeZPIAfUo8zE/kOEGbW5NZvGc/K7nMxbhIr+YlFlHW5mpbg/YFPdbnCh1wAXCKFg==", | ||
| "cpu": [ | ||
| "arm64" | ||
| ], | ||
| "license": "MPL-2.0", | ||
| "optional": true, | ||
| "os": [ | ||
| "android" | ||
| ], | ||
| "engines": { | ||
| "node": ">= 12.0.0" | ||
| }, | ||
| "funding": { | ||
| "type": "opencollective", | ||
| "url": "https://opencollective.com/parcel" | ||
| } | ||
| }, | ||
| "node_modules/lightningcss-darwin-arm64": { | ||
| "version": "1.31.1", | ||
| "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.31.1.tgz", | ||
| "integrity": "sha512-02uTEqf3vIfNMq3h/z2cJfcOXnQ0GRwQrkmPafhueLb2h7mqEidiCzkE4gBMEH65abHRiQvhdcQ+aP0D0g67sg==", | ||
| "cpu": [ | ||
| "arm64" | ||
| ], | ||
| "license": "MPL-2.0", | ||
| "optional": true, | ||
| "os": [ | ||
| "darwin" | ||
| ], | ||
| "engines": { | ||
| "node": ">= 12.0.0" | ||
| }, | ||
| "funding": { | ||
| "type": "opencollective", | ||
| "url": "https://opencollective.com/parcel" | ||
| } | ||
| }, | ||
| "node_modules/lightningcss-darwin-x64": { | ||
| "version": "1.31.1", | ||
| "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.31.1.tgz", | ||
| "integrity": "sha512-1ObhyoCY+tGxtsz1lSx5NXCj3nirk0Y0kB/g8B8DT+sSx4G9djitg9ejFnjb3gJNWo7qXH4DIy2SUHvpoFwfTA==", | ||
| "cpu": [ | ||
| "x64" | ||
| ], | ||
| "license": "MPL-2.0", | ||
| "optional": true, | ||
| "os": [ | ||
| "darwin" | ||
| ], | ||
| "engines": { | ||
| "node": ">= 12.0.0" | ||
| }, | ||
| "funding": { | ||
| "type": "opencollective", | ||
| "url": "https://opencollective.com/parcel" | ||
| } | ||
| }, | ||
| "node_modules/lightningcss-freebsd-x64": { | ||
| "version": "1.31.1", | ||
| "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.31.1.tgz", | ||
| "integrity": "sha512-1RINmQKAItO6ISxYgPwszQE1BrsVU5aB45ho6O42mu96UiZBxEXsuQ7cJW4zs4CEodPUioj/QrXW1r9pLUM74A==", | ||
| "cpu": [ | ||
| "x64" | ||
| ], | ||
| "license": "MPL-2.0", | ||
| "optional": true, | ||
| "os": [ | ||
| "freebsd" | ||
| ], | ||
| "engines": { | ||
| "node": ">= 12.0.0" | ||
| }, | ||
| "funding": { | ||
| "type": "opencollective", | ||
| "url": "https://opencollective.com/parcel" | ||
| } | ||
| }, | ||
| "node_modules/lightningcss-linux-arm-gnueabihf": { | ||
| "version": "1.31.1", | ||
| "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.31.1.tgz", | ||
| "integrity": "sha512-OOCm2//MZJ87CdDK62rZIu+aw9gBv4azMJuA8/KB74wmfS3lnC4yoPHm0uXZ/dvNNHmnZnB8XLAZzObeG0nS1g==", | ||
| "cpu": [ | ||
| "arm" | ||
| ], | ||
| "license": "MPL-2.0", | ||
| "optional": true, | ||
| "os": [ | ||
| "linux" | ||
| ], | ||
| "engines": { | ||
| "node": ">= 12.0.0" | ||
| }, | ||
| "funding": { | ||
| "type": "opencollective", | ||
| "url": "https://opencollective.com/parcel" | ||
| } | ||
| }, | ||
| "node_modules/lightningcss-linux-arm64-gnu": { | ||
| "version": "1.31.1", | ||
| "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.31.1.tgz", | ||
| "integrity": "sha512-WKyLWztD71rTnou4xAD5kQT+982wvca7E6QoLpoawZ1gP9JM0GJj4Tp5jMUh9B3AitHbRZ2/H3W5xQmdEOUlLg==", | ||
| "cpu": [ | ||
| "arm64" | ||
| ], | ||
| "license": "MPL-2.0", | ||
| "optional": true, | ||
| "os": [ | ||
| "linux" | ||
| ], | ||
| "engines": { | ||
| "node": ">= 12.0.0" | ||
| }, | ||
| "funding": { | ||
| "type": "opencollective", | ||
| "url": "https://opencollective.com/parcel" | ||
| } | ||
| }, | ||
| "node_modules/lightningcss-linux-arm64-musl": { | ||
| "version": "1.31.1", | ||
| "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.31.1.tgz", | ||
| "integrity": "sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg==", | ||
| "cpu": [ | ||
| "arm64" | ||
| ], | ||
| "license": "MPL-2.0", | ||
| "optional": true, | ||
| "os": [ | ||
| "linux" | ||
| ], | ||
| "engines": { | ||
| "node": ">= 12.0.0" | ||
| }, | ||
| "funding": { | ||
| "type": "opencollective", | ||
| "url": "https://opencollective.com/parcel" | ||
| } | ||
| }, | ||
| "node_modules/lightningcss-linux-x64-gnu": { | ||
| "version": "1.31.1", | ||
| "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.31.1.tgz", | ||
| "integrity": "sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA==", | ||
| "cpu": [ | ||
| "x64" | ||
| ], | ||
| "license": "MPL-2.0", | ||
| "optional": true, | ||
| "os": [ | ||
| "linux" | ||
| ], | ||
| "engines": { | ||
| "node": ">= 12.0.0" | ||
| }, | ||
| "funding": { | ||
| "type": "opencollective", | ||
| "url": "https://opencollective.com/parcel" | ||
| } | ||
| }, | ||
| "node_modules/lightningcss-linux-x64-musl": { | ||
| "version": "1.31.1", | ||
| "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.31.1.tgz", | ||
| "integrity": "sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA==", | ||
| "cpu": [ | ||
| "x64" | ||
| ], | ||
| "license": "MPL-2.0", | ||
| "optional": true, | ||
| "os": [ | ||
| "linux" | ||
| ], | ||
| "engines": { | ||
| "node": ">= 12.0.0" | ||
| }, | ||
| "funding": { | ||
| "type": "opencollective", | ||
| "url": "https://opencollective.com/parcel" | ||
| } | ||
| }, | ||
| "node_modules/lightningcss-win32-arm64-msvc": { | ||
| "version": "1.31.1", | ||
| "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.31.1.tgz", | ||
| "integrity": "sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w==", | ||
| "cpu": [ | ||
| "arm64" | ||
| ], | ||
| "license": "MPL-2.0", | ||
| "optional": true, | ||
| "os": [ | ||
| "win32" | ||
| ], | ||
| "engines": { | ||
| "node": ">= 12.0.0" | ||
| }, | ||
| "funding": { | ||
| "type": "opencollective", | ||
| "url": "https://opencollective.com/parcel" | ||
| } | ||
| }, | ||
| "node_modules/lightningcss-win32-x64-msvc": { | ||
| "version": "1.31.1", | ||
| "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.31.1.tgz", | ||
| "integrity": "sha512-I9aiFrbd7oYHwlnQDqr1Roz+fTz61oDDJX7n9tYF9FJymH1cIN1DtKw3iYt6b8WZgEjoNwVSncwF4wx/ZedMhw==", | ||
| "cpu": [ | ||
| "x64" | ||
| ], | ||
| "license": "MPL-2.0", | ||
| "optional": true, | ||
| "os": [ | ||
| "win32" | ||
| ], | ||
| "engines": { | ||
| "node": ">= 12.0.0" | ||
| }, | ||
| "funding": { | ||
| "type": "opencollective", | ||
| "url": "https://opencollective.com/parcel" | ||
| } | ||
| }, | ||
| "node_modules/magic-string": { | ||
| "version": "0.30.21", | ||
| "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", | ||
| "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", | ||
| "license": "MIT", | ||
| "dependencies": { | ||
| "@jridgewell/sourcemap-codec": "^1.5.5" | ||
| } | ||
| }, | ||
| "node_modules/mri": { | ||
| "version": "1.2.0", | ||
| "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", | ||
| "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", | ||
| "license": "MIT", | ||
| "engines": { | ||
| "node": ">=4" | ||
| } | ||
| }, | ||
| "node_modules/node-addon-api": { | ||
| "version": "7.1.1", | ||
| "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", | ||
| "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", | ||
| "license": "MIT" | ||
| }, | ||
| "node_modules/picocolors": { | ||
| "version": "1.1.1", | ||
| "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", | ||
| "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", | ||
| "license": "ISC" | ||
| }, | ||
| "node_modules/picomatch": { | ||
| "version": "4.0.4", | ||
| "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", | ||
| "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", | ||
| "license": "MIT", | ||
| "engines": { | ||
| "node": ">=12" | ||
| }, | ||
| "funding": { | ||
| "url": "https://github.com/sponsors/jonschlinkert" | ||
| } | ||
| }, | ||
| "node_modules/source-map-js": { | ||
| "version": "1.2.1", | ||
| "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", | ||
| "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", | ||
| "license": "BSD-3-Clause", | ||
| "engines": { | ||
| "node": ">=0.10.0" | ||
| } | ||
| }, | ||
| "node_modules/tailwindcss": { | ||
| "version": "4.2.1", | ||
| "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.2.1.tgz", | ||
| "integrity": "sha512-/tBrSQ36vCleJkAOsy9kbNTgaxvGbyOamC30PRePTQe/o1MFwEKHQk4Cn7BNGaPtjp+PuUrByJehM1hgxfq4sw==", | ||
| "license": "MIT" | ||
| }, | ||
| "node_modules/tapable": { | ||
| "version": "2.3.0", | ||
| "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", | ||
| "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", | ||
| "license": "MIT", | ||
| "engines": { | ||
| "node": ">=6" | ||
| }, | ||
| "funding": { | ||
| "type": "opencollective", | ||
| "url": "https://opencollective.com/webpack" | ||
| } | ||
| } | ||
| } | ||
| "name": "Web", | ||
| "lockfileVersion": 3, | ||
| "requires": true, | ||
| "packages": { | ||
| "": { | ||
| "dependencies": { | ||
| "@tailwindcss/cli": "^4.2.1", | ||
| "tailwindcss": "^4.2.1" | ||
| } | ||
| }, |
There was a problem hiding this comment.
This change appears to reformat the entire package-lock.json (tabs -> spaces) without changing dependencies, which creates a very large/noisy diff and increases merge-conflict risk. If there were no actual dependency updates intended in this PR, consider reverting the lockfile reformat or moving it to a separate dedicated PR.
| var updatedIssue = existingIssue with { Title = command.Title, Description = string.Empty, Category = newCategory }; | ||
| _repository.UpdateAsync(Arg.Any<IssueDto>(), Arg.Any<CancellationToken>()) | ||
| .Returns(Result.Ok(updatedIssue)); | ||
|
|
||
| // Act | ||
| var result = await _handler.Handle(command, CancellationToken.None); | ||
|
|
||
| // Assert | ||
| result.Success.Should().BeTrue(); | ||
| result.Value!.Category.CategoryName.Should().Be("New Category"); | ||
| await _categoryRepository.Received(1).GetByIdAsync(categoryId, Arg.Any<CancellationToken>()); | ||
| } |
There was a problem hiding this comment.
The new "Handle_WithCategoryId_UpdatesCategory" test doesn't actually verify that UpdateIssueHandler passes the resolved category into IIssueRepository.UpdateAsync. Since UpdateAsync is stubbed with Arg.Any(), the test would still pass even if the handler ignored CategoryId. Consider asserting the argument to UpdateAsync (e.g., Arg.Is(i => i.Category.Id == categoryId)) so the test genuinely exercises the new behavior.
| var updatedIssue = existingIssue with { Title = command.Title, Description = string.Empty, Status = newStatus }; | ||
| _repository.UpdateAsync(Arg.Any<IssueDto>(), Arg.Any<CancellationToken>()) | ||
| .Returns(Result.Ok(updatedIssue)); | ||
|
|
||
| // Act | ||
| var result = await _handler.Handle(command, CancellationToken.None); | ||
|
|
||
| // Assert | ||
| result.Success.Should().BeTrue(); | ||
| result.Value!.Status.StatusName.Should().Be("In Progress"); | ||
| await _statusRepository.Received(1).GetByIdAsync(statusId, Arg.Any<CancellationToken>()); | ||
| } |
There was a problem hiding this comment.
Same issue as the category test: "Handle_WithStatusId_UpdatesStatus" stubs UpdateAsync with Arg.Any(), so it doesn't prove the handler applied the resolved status. Add an assertion on the IssueDto passed to UpdateAsync (and optionally also assert Category remains unchanged).
| _categoryRepository.GetByIdAsync(categoryId, Arg.Any<CancellationToken>()) | ||
| .Returns(Result.Fail<CategoryDto>("Not found")); | ||
|
|
||
| // Act | ||
| var result = await _handler.Handle(command, CancellationToken.None); | ||
|
|
||
| // Assert | ||
| result.Success.Should().BeFalse(); | ||
| result.ErrorCode.Should().Be(ResultErrorCode.NotFound); | ||
| } |
There was a problem hiding this comment.
For the invalid CategoryId path, it would be good to assert that IIssueRepository.UpdateAsync is not called when the category lookup fails. Without this, the test won't catch a bug where the handler continues updating with the old category after a lookup failure.
|
|
||
| // Assert | ||
| result.Success.Should().BeFalse(); | ||
| result.ErrorCode.Should().Be(ResultErrorCode.NotFound); |
There was a problem hiding this comment.
For the invalid StatusId path, consider asserting IIssueRepository.UpdateAsync is not called when the status lookup fails, to ensure the handler short-circuits correctly on lookup errors.
| result.ErrorCode.Should().Be(ResultErrorCode.NotFound); | |
| result.ErrorCode.Should().Be(ResultErrorCode.NotFound); | |
| _repository.ReceivedCalls() | |
| .Should() | |
| .NotContain(call => call.GetMethodInfo().Name == nameof(IIssueRepository.UpdateAsync)); |
| var category = getResult.Value.Category; | ||
| if (command.CategoryId.HasValue) | ||
| { | ||
| var categoryResult = await _categoryRepository.GetByIdAsync(command.CategoryId.Value, cancellationToken); | ||
| if (!categoryResult.Success || categoryResult.Value is null) | ||
| return Result.Fail<IssueDto>($"Category with ID '{command.CategoryId}' was not found.", ResultErrorCode.NotFound); | ||
| category = categoryResult.Value; | ||
| } |
There was a problem hiding this comment.
UpdateIssueHandler now always performs a category lookup whenever CategoryId is provided, even when it matches the issue's current category ID. Since the edit UI typically posts the selected CategoryId even when unchanged, this adds an extra DB call on most updates. Consider skipping the repository lookup when command.CategoryId.Value == getResult.Value.Category.Id (and similarly for StatusId) to avoid unnecessary reads.
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #131 +/- ##
==========================================
+ Coverage 55.52% 55.76% +0.24%
==========================================
Files 124 124
Lines 2826 2853 +27
Branches 313 318 +5
==========================================
+ Hits 1569 1591 +22
- Misses 1027 1031 +4
- Partials 230 231 +1
🚀 New features to boost your workflow:
|
|
✅ Ralph (Work Monitor): All test suites pass (unit, integration, bunit, architecture). The E2E failure is a pre-existing CI infrastructure issue (DB init failure, Redis SSL errors) unrelated to this PR's changes. Merging. |
EditIssuePage.HandleSubmitbuiltUpdateIssueCommandwith onlyDescription, silently droppingTitle,CategoryId, andStatusId. The same pattern affectedEditCategoryPage(missingCategoryName) andEditStatusPage(missingStatusName).Changes
UpdateIssueCommand— new fieldsCategoryId: ObjectId?andStatusId: ObjectId?UpdateIssueHandler— category/status lookupICategoryRepositoryandIStatusRepositoryCategoryId/StatusIdare set, resolves full DTOs from their respective repos before updating the issue; returnsNotFoundif either lookup failsEdit pages — complete field mapping
Before (
EditIssuePage.razor):After:
EditCategoryPage:UpdateCategoryCommandnow includesCategoryNameEditStatusPage:UpdateStatusCommandnow includesStatusNameTests
UpdateIssueHandlerTests: updated for 4-arg constructor; added coverage forCategoryId/StatusIdhappy paths and invalid-ID not-found casesUpdateIssueHandlerIntegrationTests: updated constructor call with substituted category/status repos