Files
Alexander Brandon Coles e8767481e9 [#70166] Fix accessibility errors found by ERB Lint (#21503)
* Fix GitHub/NoTitleAttribute, LinkHasHref errors

- Replaces `title` attribute with `aria-label` for interactive elements.
- Removes `title` from non-interactive elements.
- Converts `<a>` tags without proper `href` to `<button>` elements,
  using Primer `Button`/`IconButton` where possible.

# Conflicts:
#	app/views/custom_fields/_custom_options.html.erb
#	spec/features/admin/custom_fields/shared_custom_field_expectations.rb
#	spec/features/admin/custom_fields/work_packages/list_spec.rb

* Fix Autocomplete missing errors

* Fix GitHub/NoPositiveTabIndex errors

Removes all positive `tabindex` values.

* Fix Rails/LinkToBlank errors

* Replace toast with Primer Banner on LDAP form

* Add frozen_string_literal

* Ignore erb lint for deprecated files

* Fix linting errors in repository module

* Fix linting errors in budgets and custom actions

* Fix linting errors in member form and 2fa

* Fix linting errors in mcost types and wiki help and storages

* Fix linting errors in multi select filters, ifc viewer, and unsupported browser banner

* Fix failing spec

* Use Primer banner instead of op-toast where ever it is possible

* Use octicon instead of op_icon

* Fix failing tests

* Use no-decoration-on-hover for button links and change the button with only an icon to primer icon button

* Keep webhook response modal activation selector class-based

* use icon button for edit of hourly rate

---------

Co-authored-by: Behrokh Satarnejad <b.satarnejad@openproject.com>
2026-05-07 10:31:10 +02:00

164 lines
6.0 KiB
Plaintext

<%# -- copyright
OpenProject is an open source project management software.
Copyright (C) the OpenProject GmbH
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License version 3.
OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
Copyright (C) 2006-2013 Jean-Philippe Lang
Copyright (C) 2010-2013 the ChiliProject Team
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
See COPYRIGHT and LICENSE files for more details.
++# %>
<% content_controller "admin--custom-fields",
"admin--custom-fields-multi-select-value": @custom_field.multi_value? %>
<% custom_field.custom_options.build if custom_field.custom_options.empty? %>
<div class="generic-table--container">
<div class="generic-table--results-container">
<table class="generic-table" id="custom-options-table" data-controller="table-highlighting">
<colgroup>
<col>
<col>
<col>
<col data-highlight="false">
</colgroup>
<thead>
<tr>
<th>
<div class="generic-table--sort-header-outer">
<div class="generic-table--sort-header">
<span>
<%= t("activerecord.attributes.custom_value.value") %>
</span>
</div>
</div>
</th>
<th>
<div class="generic-table--sort-header-outer">
<div class="generic-table--sort-header">
<span>
<%= t(:label_default) %>
</span>
</div>
</div>
</th>
<th>
<div class="generic-table--sort-header-outer">
<div class="generic-table--sort-header">
<span>
<%= t(:button_sort) %>
</span>
</div>
</div>
</th>
<th style="max-width:200px;">
<div class="generic-table--empty-header">
</div>
</th>
</tr>
</thead>
<tbody
data-test-selector="dragula-container"
data-admin--custom-fields-target="dragContainer">
<% custom_field.custom_options.each_with_index do |custom_option, i| %>
<%= f.fields_for :custom_options, custom_option do |co_f| %>
<tr
class="dragula-element custom-option-row"
data-admin--custom-fields-target="customOptionRow">
<td>
<span class="dragula-handle icon icon-table icon-drag-handle"></span>
<%= co_f.hidden_field :id,
class: "custom-option-id" %>
<span class="custom-option-value">
<%= co_f.text_field :value,
no_label: true %>
</span>
</td>
<td class="custom-option-default-value">
<%= co_f.check_box :default_value,
container_class: "custom-option-default-value",
data: {
"admin--custom-fields-target": "customOptionDefaults",
action: "click->admin--custom-fields#uncheckOtherDefaults"
},
no_label: true %>
</td>
<td>
<span class="reorder-icons">
<%=
render(Primer::Beta::ButtonGroup.new(scheme: :invisible, size: :small)) do |component|
component.with_button(
icon: :"move-to-top",
"aria-label": t(:label_sort_highest),
data: { action: "admin--custom-fields#moveRowToTheTop" }
)
component.with_button(
icon: :"chevron-up",
"aria-label": t(:label_sort_higher),
data: { action: "admin--custom-fields#moveRowUp" }
)
component.with_button(
icon: :"chevron-down",
"aria-label": t(:label_sort_lower),
data: { action: "admin--custom-fields#moveRowDown" }
)
component.with_button(
icon: :"move-to-bottom",
"aria-label": t(:label_sort_lowest),
data: { action: "admin--custom-fields#moveRowToTheBottom" }
)
end
%>
</span>
</td>
<td>
<%= link_to "",
delete_option_of_custom_field_path(id: custom_field.id || 0, option_id: custom_option.id || 0),
data: {
turbo_method: :delete,
action: "admin--custom-fields#removeOption",
turbo_confirm: t(:"custom_fields.confirm_destroy_option")
},
class: "icon icon-delete delete-custom-option",
"aria-label": t(:button_delete) %>
</td>
</tr>
<% end %>
<% end %>
</tbody>
</table>
</div>
</div>
<%=
render Primer::Beta::Button.new(
scheme: :link,
test_selector: "add-custom-option",
data: { action: "admin--custom-fields#addOption" },
mt: 2
) do |button|
button.with_leading_visual_icon(icon: :plus)
t(:button_add)
end
%>