Skip to content

feat: implement all open issues (#539 #540 #565 #566 #607 #615 #619 #620) + security fix#659

Merged
cct08311github merged 10 commits intodotnet8from
claude/merge-to-dotnet8-XuCiJ
Mar 19, 2026
Merged

feat: implement all open issues (#539 #540 #565 #566 #607 #615 #619 #620) + security fix#659
cct08311github merged 10 commits intodotnet8from
claude/merge-to-dotnet8-XuCiJ

Conversation

@cct08311github
Copy link
Copy Markdown
Owner

Summary

Notes

The changes from PRs #655 and #657 are included in this branch (as 7e77cad and 96e882a respectively). Those PR branches have also been rebased on dotnet8 to clear their merge conflicts.

Test plan

  • dotnet test WalkingTec.Mvvm.sln -c Release passes
  • cd test/WalkingTec.Mvvm.Js.Tests && npm test passes (561 tests)
  • Verify ETL row actions work in demo app
  • Verify ComboBox remote search with remote-url
  • Verify import progress reporting in large uploads

https://claude.ai/code/session_017r2EfWhoDdvECdoncQg6xM

cct0831 and others added 10 commits March 19, 2026 16:09
…lt table (#539)

- Wrap result table in `.analysis-table-wrap` div for CSS sticky-header support
- Add client-side column sorting: click header to cycle asc → desc → original
  Sort indicator uses CSS `::after` so `th.textContent` is unchanged (preserves
  all existing header-text tests)
- Add pagination (50 rows/page) with page-info span and prev/next buttons;
  pagination div only rendered when row count exceeds page size
- Sorting resets to first page; % share columns remain non-sortable
- Add 29 new Jest tests covering wrapper, sort (asc/desc/reset/multi-col/string),
  and pagination (no-div ≤50, div >50, page info, next, prev-disabled, sort reset)
- 344 Jest tests pass total

Closes #539

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Frontend: createValueInput() for date fields now renders a span wrapper
  with a mode <select> (8 relative tokens + custom) and a hidden
  .analysis-filter-value input. collectFilters() unchanged — deep
  querySelector still finds the input inside the wrapper.
- Backend: ResolveRelativeDates() expands @today / @ThisWeek / @lastweek
  / @thismonth / @lastmonth / @last30days / @thisQuarter / @YTD tokens
  into Gte/Lte FilterCondition pairs before ApplyFilters builds
  expression trees.
- Tests: 8 MSTest for ResolveRelativeDates, 9 Jest for date mode UI.
  Updated existing #501 test to reflect new span-wrapper shape.

Closes #566

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
**#620 - Optimistic concurrency in BaseCRUDVM**
- Add `IsConcurrencyConflict` read-only property to `IBaseCRUDVM<T>` and `BaseCRUDVM<T>`
- Catch `DbUpdateConcurrencyException` specifically in `DoEdit()` and `DoEditAsync()` before
  the generic catch; sets `IsConcurrencyConflict = true` and adds localizer key
  `"Sys.ConcurrencyConflict"` model error instead of throwing
- Add `ConcurrencyConflictTests.cs` with 4 tests covering sync, async, initial state and
  interface read-only contract

**#607 - IProgress<ImportProgress> for BaseImportVM**
- Add `ImportProgress` readonly struct (Processed, Total, Phase)
- Add optional `IProgress<ImportProgress>? progress = null` parameter to `BatchSaveData()`
  (fully backward-compatible default)
- Report progress after every row in both the validation phase ("Validating") and the
  entity-preparation phase ("Saving")

**#615 - Import error inline table + template description row**
- Add `InlineErrorLimit` (default 50) and `InlineErrors` computed property to `BaseImportVM`
  so the UI can show the first N errors inline without a file download
- Add `ShowDescriptionRow` flag (default `true`) to `BaseTemplateVM`
- `GenerateTemplate()` writes a light-green italic description row below the column header
  when `ShowDescriptionRow` is true, containing Required/Optional, data type, and length
  hints derived from `ExcelPropety` metadata; freeze pane extends to cover both rows
- Store a "v2" marker in the hidden enum-sheet so `SetTemplateData()` can detect and skip
  the description row during import (fully backward-compatible with old templates)

https://claude.ai/code/session_017r2EfWhoDdvECdoncQg6xM
- Add GetDeletePreviewString() to IBaseCRUDVM<T> interface and
  BaseCRUDVM<TModel> with default implementation that searches
  common name properties (Name/Title/Code/ITCode) before falling
  back to the entity's primary key value
- Add POST /_Framework/GetDeletePreview endpoint that accepts a
  vmType name and up to 10 IDs, returns [{id, label}] for
  bulk-delete confirmation dialogs
- Add POST /_Framework/BatchAssignRoles endpoint that upserts
  FrameworkUserRole entries for multiple userCodes against one
  roleCode, then purges affected user caches

https://claude.ai/code/session_017r2EfWhoDdvECdoncQg6xM
…619 tests

ComboBox (#565):
- Add RemoteUrl property; when set enables xmSelect remoteSearch+remoteMethod,
  sending ?q=<keyword> to the URL on each keystroke (debounced by xmSelect)
- filterable is forced true when RemoteUrl is set

TreeSelect (#565):
- Add LazyUrl property; when set enables xmSelect lazy=true and a load callback
  that fetches children via ?id=<nodeValue> on node expand

Tests (#619):
- Add DeletePreviewTests covering GetDeletePreviewString default behaviour,
  primary-key fallback, interface presence, and virtual modifier

https://claude.ai/code/session_017r2EfWhoDdvECdoncQg6xM
EtlJobListVM:
- Override InitGridAction() to add Create/Edit/Delete standard actions
- Add row-level actions: TriggerNow (confirm POST), Pause, Resume, Abort
- Add '執行記錄' action that opens run-log dialog filtered by job ID
- Add ConsecutiveFailureCount column for at-a-glance failure tracking
- Widen action column to 460px to fit all buttons

Demo views (_EtlJob/Create + Edit):
- Add missing QueryTemplate (textarea), AlertEmail, AlertWebhookUrl,
  AlertAfterConsecutiveFailures fields to Create and Edit forms

https://claude.ai/code/session_017r2EfWhoDdvECdoncQg6xM
Documents all features and fixes implemented on the working branch
for the next version release.

https://claude.ai/code/session_017r2EfWhoDdvECdoncQg6xM
…#615)

ImportProgressTests (#607):
- Verifies that BatchSaveData reports progress for each row
- Checks Total matches entity count, Processed is monotonically increasing
- Validates null progress parameter doesn't throw
- Confirms phase names are always non-empty

TemplateDescriptionRowTests (#615):
- Verifies ShowDescriptionRow = true writes 'v2' marker in hidden sheet
- ShowDescriptionRow = false writes empty marker (backward compat)
- Description row exists and contains Required/Optional hint text
- Confirmed default = true

InlineErrors (#615 via ImportProgressTests):
- Tests InlineErrors is empty before import
- Returns errors after validation failure
- Respects InlineErrorLimit cap (default 50)
- Empty when InlineErrorLimit = 0

https://claude.ai/code/session_017r2EfWhoDdvECdoncQg6xM
…rence

The old Microsoft.AspNetCore.Http NuGet package v2.1.34 is a .NET Core 2.1
artifact referenced in a .NET 8 project, carrying potential security
vulnerabilities. Replace with FrameworkReference to Microsoft.AspNetCore.App
which provides all ASP.NET Core APIs at the .NET 8 version.

Also remove the duplicate explicit Microsoft.AspNetCore.Authorization 8.0.22
reference — it is included by the framework reference.

https://claude.ai/code/session_017r2EfWhoDdvECdoncQg6xM
Override InitGridAction() to add a row-level 'Rerun' button that POSTs
to _EtlRunLog/Rerun with the selected run log ID, restoring the watermark
to the snapshot and triggering the job again.

https://claude.ai/code/session_017r2EfWhoDdvECdoncQg6xM
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.

2 participants