Skip to content

fix: make work item IDs incremental#71

Merged
martian56 merged 2 commits intomainfrom
70-make-work-item-ids-increamental
Mar 25, 2026
Merged

fix: make work item IDs incremental#71
martian56 merged 2 commits intomainfrom
70-make-work-item-ids-increamental

Conversation

@martian56
Copy link
Copy Markdown
Member

This pull request introduces several improvements across both the backend and frontend. The most significant changes are the enforcement of a 7-character maximum for project identifiers (with user feedback in both API and UI), enhanced transactional integrity for issue creation with per-project sequence numbers, and improved accessibility and usability of UI tooltips.

Backend improvements:

  • Enforced a maximum length of 7 characters for project identifiers in both project creation and update logic, returning a specific error if the limit is exceeded. [1] [2] [3]
  • Updated the API handlers to return a 400 Bad Request with a descriptive error when the identifier is too long, instead of a generic error. [1] [2]
  • Added transactional issue creation: issue creation now uses a database transaction to atomically assign the next per-project sequence ID (with advisory lock) and create the issue, ensuring unique and sequential issue numbers even under concurrency. [1] [2]

Frontend improvements:

  • Updated the project creation modal to enforce a 7-character limit on the project identifier input, provide a clearer placeholder, and add a tooltip explaining the identifier field.
  • Replaced static title attributes with accessible Tooltip components for various UI buttons and controls, improving usability and accessibility across the application. [1] [2] [3] [4] [5] [6] [7]

Other changes:

  • Updated package metadata and scripts in package.json and version bumps for UI packages. [1] [2] [3]
  • Minor code refactoring and icon update in the project modal. [1] [2]

These changes collectively improve data integrity, user experience, and accessibility throughout the application.

Closes #70

@martian56 martian56 added this to the Deadline milestone Mar 25, 2026
@martian56 martian56 self-assigned this Mar 25, 2026
@martian56 martian56 added bug Something isn't working API UI labels Mar 25, 2026
Copilot AI review requested due to automatic review settings March 25, 2026 20:32
@martian56 martian56 requested review from a team, Javenn0, Rafetikus and nazarli-shabnam March 25, 2026 20:34
Comment thread ui/src/components/layout/PageHeader.tsx Fixed
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR aims to make work item IDs incremental (per project) and improve project identifier validation and UI accessibility by introducing a reusable tooltip component and enforcing a 7-character project identifier limit across API + UI.

Changes:

  • Backend: enforce a 7-character max project identifier and return a 400 with a specific error.
  • Backend: create issues with a per-project incremental sequence_id assigned inside a DB transaction (with advisory locking).
  • Frontend: add a Tooltip component and replace several title attributes; enforce 7-character limit on the project identifier input.

Reviewed changes

Copilot reviewed 10 out of 11 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
ui/src/components/ui/index.ts Exports the new Tooltip component from the UI barrel.
ui/src/components/ui/Tooltip.tsx Introduces a portal-based tooltip component with hover/focus behavior.
ui/src/components/layout/PageHeader.tsx Replaces title tooltips with Tooltip wrappers for various header controls.
ui/src/components/CreateProjectModal.tsx Enforces 7-char project ID in the input and adds a tooltip hint button.
ui/package.json Bumps UI package version.
ui/package-lock.json Updates lockfile version metadata accordingly.
package.json Marks repo private and changes test to run the validate pipeline.
api/internal/store/issue.go Adds transactional helper + per-project sequence_id allocation using advisory locks.
api/internal/service/project.go Adds max-length validation for project identifiers.
api/internal/service/issue.go Uses transaction + NextSequenceID to assign SequenceID on create.
api/internal/handler/project.go Maps identifier-too-long to a 400 Bad Request response.
Files not reviewed (1)
  • ui/package-lock.json: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

}
var max int
err := tx.WithContext(ctx).Raw(
`SELECT COALESCE(MAX(sequence_id), 0) FROM issues WHERE project_id = ? AND deleted_at IS NULL`,
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

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

NextSequenceID filters on deleted_at IS NULL when computing MAX(sequence_id), which will reuse sequence IDs after a soft-deleted issue is removed (e.g., deleting the highest-numbered issue allows that number to be reassigned). For work-item IDs, sequence numbers generally must be monotonic and never reused; include soft-deleted rows in the max calculation (or use an unscoped query) so new issues always get a brand-new sequence ID.

Suggested change
`SELECT COALESCE(MAX(sequence_id), 0) FROM issues WHERE project_id = ? AND deleted_at IS NULL`,
`SELECT COALESCE(MAX(sequence_id), 0) FROM issues WHERE project_id = ?`,

Copilot uses AI. Check for mistakes.
Comment on lines +129 to +136
if err := s.is.Transaction(ctx, func(tx *gorm.DB) error {
seq, err := s.is.NextSequenceID(ctx, tx, projectID)
if err != nil {
return err
}
issue.SequenceID = seq
return tx.WithContext(ctx).Create(issue).Error
}); err != nil {
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

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

The new transaction only covers sequence assignment + the issues insert; assignee/label mutations happen after the transaction and their errors are ignored, so a partially-created issue can be returned without its requested relationships and the sequence number can be consumed even though the overall create request effectively failed. To match the stated atomicity goal, perform relationship writes inside the same transaction and propagate any errors (returning a failure so the whole create rolls back).

Copilot uses AI. Check for mistakes.
Comment on lines +117 to +127
<span
ref={triggerRef}
className="inline-flex max-w-full"
onMouseEnter={show}
onMouseLeave={hide}
onFocusCapture={show}
onBlurCapture={hideIfLeavingTrigger}
aria-describedby={open ? id : undefined}
>
{children}
</span>
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

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

aria-describedby is applied to the wrapping <span>, but focus is typically on the child control (e.g., a <button>), so assistive tech won’t associate the tooltip content with the focused element. Consider constraining children to a single ReactElement and cloning it to inject aria-describedby (and the mouse/focus handlers) onto the actual trigger element (and forward the ref), so the tooltip is correctly announced on focus.

Copilot uses AI. Check for mistakes.
Comment thread ui/src/components/layout/PageHeader.tsx Outdated
Copy link
Copy Markdown
Member

@nazarli-shabnam nazarli-shabnam left a comment

Choose a reason for hiding this comment

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

bien joué, monsieur.
Fix linting and good to go

@martian56 martian56 force-pushed the 70-make-work-item-ids-increamental branch from 1fd7293 to da43c9d Compare March 25, 2026 20:53
@martian56 martian56 merged commit 10c3884 into main Mar 25, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

API bug Something isn't working UI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Make Work item IDs increamental

4 participants