Stubbing Setting::WorkPackageIdentifier predicates bypasses the real
flag + setting resolution chain. Flip the actual flag and setting via
RSpec metadata so the spec exercises the real guard path.
The full-screen icon link in the shared work-package-details tab component
constructed its href from work_package.id (numeric PK). All hosts of the
primerized split view — Boards, Notifications, etc. — inherited the numeric
URL. Switch to work_package.display_id so the full-view URL carries the
semantic identifier when one is configured.
Covers semantic mode, semantic-mode-with-nil-identifier fallback, and
classic mode. Also exercises the pre-existing rendering paths (type,
status, link) that previously had no component-level coverage.
The setting previously used "numeric" and "alphanumeric" as its allowed
values. Rename them to "classic" and "semantic" to better align with the
product terminology for the work package identifier modes.
Includes a migration to update any stored setting values in the database,
updated constants and helper methods on Setting::WorkPackageIdentifier,
and all corresponding references across models, components, forms,
frontend controllers, locales, and specs.
Aligns the class name and all internal terminology with the domain
language: "handle" → "identifier" throughout. Renames the file, class,
constants (HANDLE_MAX_LENGTH → IDENTIFIER_MAX_LENGTH, FALLBACK_HANDLE →
FALLBACK_IDENTIFIER), public API (suggest_handle → suggest_identifier,
suggested_handle hash key → suggested_identifier), keyword arguments
(in_use_handles → in_use_identifiers, reserved_handles →
reserved_identifiers), and private helper methods accordingly. All
call-sites and specs updated to match.
The autofix button is now a link (<a> tag), so update the component spec
to use have_link/have_no_link instead of have_button. Also replace all
I18n.t() calls with raw English strings throughout the spec.
Previously only the first radio button was checked by label. Now both
"Instance-wide numerical sequence" and "Project-based alphanumerical
identifiers" are asserted for completeness.
Replace CSS role selectors with capybara_accessible_selectors helpers
and substitute raw English strings for I18n.t() calls where the value
serves as a contract on the exact locale text.
- Move DISPLAY_COUNT constant from IdentifierAutofixSectionComponent to
PreviewQuery, eliminating a service-layer dependency on a view component.
The component now forwards to PreviewQuery::DISPLAY_COUNT.
- Guard PreviewQuery.new.call to only run in the :edit state.
Previously it executed on every render, hitting the DB twice per
Hotwire status-poll during the :change_in_progress phase.
- Replace nil guard in error_label with I18n.t default: "" to cover
any unrecognised error reason, not just nil.
- Add component spec for IdentifierSettingsFormComponent covering all
three states (:change_in_progress, :completed, :edit) including the
autofix-section visibility branch.
- Update preview_query_spec to reference PreviewQuery::DISPLAY_COUNT
directly instead of the UI component constant.
- Swap wrapper_data_attrs condition: poll-for-changes must only be
active in :change_in_progress state, not :edit/:completed
- Replace update_to_alphanumeric? with autofix_requested? keyed on
confirm_dangerous_action param (DangerDialog checkbox signal)
- Use ActiveRecord::Type::Boolean cast for truthy check
- Fix spec: radio group label renders as <legend>, not <h2>; add
visible: :all for hidden element assertion
IdentifierAutofixPreviewComponent → IdentifierAutofixSectionComponent.
The banner (existing_identifiers_notice) and the preview table always appear
together, so they are now co-located in a single component. The parent
template renders one component instead of a banner + separate component.
Changes:
- git mv preview → section for all three files (rb, erb, spec)
- Add @total_count to the initializer for the banner's project_count
- Template: banner rendered above the border-box table
- Parent template: remove inline banner render, call SectionComponent
- Spec: update described_class; add banner count assertion
Replace the hardcoded '-1' suffix with a deterministic sample number
derived from the handle string (range 1–500, zero-padded for single
digits). Each handle consistently produces the same example ID on every
render, but IDs look naturally varied across different projects.
Adds the admin settings page for choosing between numeric and
project-based alphanumeric work package identifiers (#72461):
- ProjectHandleSuggestionGenerator service that scans projects for
identifiers that don't meet alphanumeric handle requirements and
generates uppercase acronym suggestions (e.g. "PROJ" from "My Project")
- IdentifierAutofixPreviewComponent: Primer BorderBox table showing the
first 5 problematic projects with their suggestions and a "... N more"
footer row
- work-packages-identifier Stimulus controller that shows/hides the
autofix section and updates the submit button label on radio change
- Updated IdentifierSettingsFormComponent wired to the Stimulus
controller, showing the warning banner and preview table when
"Project-based alphanumerical identifiers" is selected
When we do focus another input field on the page, the debounced preview logic kicks in and passes the fields name to the `frmaeSrc`. Since the search field is not whitelisted, we are throwing an argument error. This seems a bit strict.
The new logic accepts all field values. The modal is closed immediately afterwards anyways and this cancels the loading.
* check if there is a screen reader active on page load
* hide the flat picker for screen readers
* make the banner focusable
* change the focus color in banner
* change disabled to readonly input fields
* change replace_via_turbo_stream to add a message to it
* add live region of github to out project
* add a method to send the aria message
* make it possible to pass the attributes
* pass type of aria live region to front-end based on the action
* remove focused field from date picker
* focus on tabs when there is no banner
* Revert "remove focused field from date picker"
This reverts commit ab5e3060343860e9c34514818f6d9eee59e91ee1.
* focus on the first element when opening the dialog
* remove auto-focus
* undo changes for adding a message
* add a new input method for adding a date and select today as a date
* remove label and name from form input
* change readonly to disabled
* undo changes for date-form
* delete dateform file
* add aria-live for fields in date pickr
* add a turbo stream to the component to load the messages for aria live regions
* undo changes for check f there is an active screen reader
* use settimeout instead of add event listener, so turbo frame also can be used hare
* undo changes for text with link form input
* remove text with link form input
* add documentation for aria-live region
* add an example for using current method in relation creation
* add aria live region in date-pickr dialog
* add some delay for polite messages to make sure it is caught
* send a message to be gotten by screen reader in date picker while changing inputs
* remove aria-live form inputs in date pickr
* show update message after any change in inputs of date picker
* fix rubocup errors in relation controller
* fix rubocup errors in datepicker controller
* fix eslint error
* update docs
* add some details to the aria live doc
* remove test for aria-live on inputs of date pickr
* remove unnecessary live region polite for date picker
* Update lookbook/docs/patterns/18-aria-live.md.erb
Co-authored-by: Henriette Darge <h.darge@openproject.com>
* Update lookbook/docs/patterns/18-aria-live.md.erb
Co-authored-by: Henriette Darge <h.darge@openproject.com>
* fix comment in preview controller
* remove role: alert
* set correct value for target
* move aria turbo stream below live region
* add missing spaces and a better headline for js handling turbo aria action
* move the exception of modals and dialogs to the end of doc file
* Update lookbook/docs/patterns/accessibility/18-aria-live.md.erb
Co-authored-by: Alexander Brandon Coles <a.coles@openproject.com>
* Update frontend/src/turbo/aria-stream-action.ts
Co-authored-by: Alexander Brandon Coles <a.coles@openproject.com>
* Update lookbook/docs/patterns/accessibility/18-aria-live.md.erb
Co-authored-by: Alexander Brandon Coles <a.coles@openproject.com>
* Update app/controllers/work_packages/date_picker_controller.rb
Co-authored-by: Alexander Brandon Coles <a.coles@openproject.com>
* Update lookbook/docs/patterns/accessibility/18-aria-live.md.erb
Co-authored-by: Alexander Brandon Coles <a.coles@openproject.com>
* Update app/controllers/concerns/op_turbo/component_stream.rb
Co-authored-by: Alexander Brandon Coles <a.coles@openproject.com>
* Update app/controllers/work_packages/date_picker_controller.rb
Co-authored-by: Alexander Brandon Coles <a.coles@openproject.com>
* Update app/controllers/work_packages/date_picker_controller.rb
Co-authored-by: Alexander Brandon Coles <a.coles@openproject.com>
* Update lookbook/docs/patterns/accessibility/18-aria-live.md.erb
Co-authored-by: Alexander Brandon Coles <a.coles@openproject.com>
* Update lookbook/docs/patterns/accessibility/18-aria-live.md.erb
Co-authored-by: Alexander Brandon Coles <a.coles@openproject.com>
* Update lookbook/docs/patterns/accessibility/18-aria-live.md.erb
Co-authored-by: Alexander Brandon Coles <a.coles@openproject.com>
* Update lookbook/docs/patterns/accessibility/18-aria-live.md.erb
Co-authored-by: Alexander Brandon Coles <a.coles@openproject.com>
* change parameter in update_inputs_aria_live_message string
* change type to politeness
* Update lookbook/docs/patterns/accessibility/18-aria-live.md.erb
Co-authored-by: Alexander Brandon Coles <a.coles@openproject.com>
* set delay for polite updates
* use delay in relations tab update and date pickr update
* remove the usage of aria live region update message in relations tab, since we should handle update message here in another way
* use assistive technology instead of screen reader only
* change the stream action to live region
* change the aria action to live region
* remove alert role
* change the string in away that if there is no value for start date, finish date or duration, it shouldn't be part of the string
* remove aria-live from input text fields
* test for updated message in date pickr
* undo changes for relations updates
* check if message is null then return
* add more delay for updating data in date picker
* fix test for adding more delay for updating data in date picker
---------
Co-authored-by: Henriette Darge <h.darge@openproject.com>
Co-authored-by: Alexander Brandon Coles <a.coles@openproject.com>
Having the route being `datepicker_dialog_content` leads to looking for
a `DatepickerDialogContentController`, but that would be wrong as the
controller is `DatePickerController`. That's not coherent. That's why
routes were moved to `date_picker` so that the routes and the controller
are named the same
Also moved the `new` action to the collection level so that it does not
need a dummy `work_package_id` with value `new` anymore.
* add aria live region for inputs
* add aria live region for finish date
* change the way we use aria-live
* add test to check if there is aria live set for datepickr inputs
* fix line too long issue
* Update spec/components/work_packages/date_picker/dialog_content_component_spec.rb
Co-authored-by: Alexander Brandon Coles <a.coles@openproject.com>
---------
Co-authored-by: Alexander Brandon Coles <a.coles@openproject.com>
It will disable the save button and display the message explaining that
there are no predecessors, but at least it's consistent with the bahvior
with persisted work packages.
https://community.openproject.org/wp/61960