Skip to content

Commit

Permalink
Merge branch 'dev' into task/56496-document-primer-flash-modals-pattern
Browse files Browse the repository at this point in the history
  • Loading branch information
akabiru committed Oct 1, 2024
2 parents cab737f + 3ff5fe1 commit 095f641
Show file tree
Hide file tree
Showing 400 changed files with 10,505 additions and 1,233 deletions.
10 changes: 7 additions & 3 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,16 @@ LOCAL_DEV_CHECK=1
# want to develop ckeditor locally.
CKEDITOR_BUILD_DIR=./frontend/src/vendor/ckeditor/

HOST=0.0.0.0
PORT=4200
# Local backend development host and port
HOST=localhost
PORT=3000
# Local frontend development host and port
FE_HOST=localhost
FE_PORT=4200

# Use this variables to configure hostnames for frontend and backend, e.g. to enable HTTPS in docker development setup
OPENPROJECT_DEV_HOST=localhost
OPENPROJECT_DEV_URL=http://${OPENPROJECT_DEV_HOST}:${PORT}
OPENPROJECT_DEV_URL=http://${OPENPROJECT_DEV_HOST}:${FE_PORT}

# Select edition from: ['standard','bim']
OPENPROJECT_EDITION=standard
Expand Down
2 changes: 1 addition & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -399,4 +399,4 @@ end

gem "openproject-octicons", "~>19.18.0"
gem "openproject-octicons_helper", "~>19.18.0"
gem "openproject-primer_view_components", "~>0.47.0"
gem "openproject-primer_view_components", "~>0.47.1"
14 changes: 7 additions & 7 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -283,9 +283,9 @@ GEM
globalid (>= 0.3.6)
activemodel (7.1.4)
activesupport (= 7.1.4)
activemodel-serializers-xml (1.0.2)
activemodel (> 5.x)
activesupport (> 5.x)
activemodel-serializers-xml (1.0.3)
activemodel (>= 5.0.0.a)
activesupport (>= 5.0.0.a)
builder (~> 3.1)
activerecord (7.1.4)
activemodel (= 7.1.4)
Expand Down Expand Up @@ -342,8 +342,8 @@ GEM
activerecord (>= 4.0.0, < 8.0)
awrence (1.2.1)
aws-eventstream (1.3.0)
aws-partitions (1.977.0)
aws-sdk-core (3.208.0)
aws-partitions (1.981.0)
aws-sdk-core (3.209.1)
aws-eventstream (~> 1, >= 1.3.0)
aws-partitions (~> 1, >= 1.651.0)
aws-sigv4 (~> 1.9)
Expand Down Expand Up @@ -804,7 +804,7 @@ GEM
actionview
openproject-octicons (= 19.18.0)
railties
openproject-primer_view_components (0.47.0)
openproject-primer_view_components (0.47.1)
actionview (>= 5.0.0)
activesupport (>= 5.0.0)
openproject-octicons (>= 19.17.0)
Expand Down Expand Up @@ -1303,7 +1303,7 @@ DEPENDENCIES
openproject-octicons (~> 19.18.0)
openproject-octicons_helper (~> 19.18.0)
openproject-openid_connect!
openproject-primer_view_components (~> 0.47.0)
openproject-primer_view_components (~> 0.47.1)
openproject-recaptcha!
openproject-reporting!
openproject-storages!
Expand Down
2 changes: 1 addition & 1 deletion Procfile.dev
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
web: bundle exec rails server -p 3000 -b ${HOST:="127.0.0.1"} --environment ${RAILS_ENV:="development"}
web: bundle exec rails server
angular: npm run serve
worker: bundle exec good_job start
6 changes: 5 additions & 1 deletion app/components/op_primer/flash_component.erb
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,11 @@ See COPYRIGHT and LICENSE files for more details.
render(Primer::BaseComponent.new(
tag: :div,
classes: "op-primer-flash--item",
data: { unique_key: @unique_key }.compact
data: {
"flash-target": "item",
"autohide": @autohide,
unique_key: @unique_key
}.compact
)) do
render_parent
end
Expand Down
4 changes: 3 additions & 1 deletion app/components/op_primer/flash_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,12 @@ class FlashComponent < Primer::Alpha::Banner
def initialize(**system_arguments)
@unique_key = system_arguments.delete(:unique_key)

system_arguments[:test_selector] ||= "primer-banner-message-component"
system_arguments[:test_selector] ||= "op-primer-flash-message"
system_arguments[:dismiss_scheme] ||= :remove
system_arguments[:dismiss_label] ||= I18n.t(:button_close)

@autohide = system_arguments[:scheme] == :success && system_arguments[:dismiss_scheme] != :none

super
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,8 @@ def create
create_service.on_success { render_project_list(url_for_action: :index) }

create_service.on_failure do
update_flash_message_via_turbo_stream(
message: join_flash_messages(create_service.errors),
full: true, dismiss_scheme: :hide, scheme: :danger
render_error_flash_message_via_turbo_stream(
message: join_flash_messages(create_service.errors)
)
end

Expand All @@ -82,9 +81,8 @@ def destroy
delete_service.on_success { render_project_list(url_for_action: :index) }

delete_service.on_failure do
update_flash_message_via_turbo_stream(
message: join_flash_messages(delete_service.errors.full_messages),
full: true, dismiss_scheme: :hide, scheme: :danger
render_error_flash_message_via_turbo_stream(
message: join_flash_messages(delete_service.errors.full_messages)
)
end

Expand Down Expand Up @@ -139,15 +137,6 @@ def find_custom_field_project_to_destroy
respond_with_project_not_found_turbo_streams
end

def update_project_list_via_turbo_stream(url_for_action: action_name)
update_via_turbo_stream(
component: Admin::CustomFields::CustomFieldProjects::TableComponent.new(
query: available_custom_fields_projects_query,
params: { custom_field: @custom_field, url_for_action: }
)
)
end

def available_custom_fields_projects_query
@available_custom_fields_projects_query = ProjectQuery.new(
name: "custom-fields-projects-#{@custom_field.id}"
Expand All @@ -166,9 +155,8 @@ def initialize_custom_field_project
end

def respond_with_project_not_found_turbo_streams
update_flash_message_via_turbo_stream message: t(:notice_project_not_found), full: true, dismiss_scheme: :hide,
scheme: :danger
update_project_list_via_turbo_stream
render_error_flash_message_via_turbo_stream message: t(:notice_project_not_found)
render_project_list(url_for_action: :index)

respond_with_turbo_streams
end
Expand Down
27 changes: 8 additions & 19 deletions app/controllers/admin/settings/project_custom_fields_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,8 @@ def link
create_service.on_success { render_project_list(url_for_action: :project_mappings) }

create_service.on_failure do
update_flash_message_via_turbo_stream(
message: join_flash_messages(create_service.errors),
full: true, dismiss_scheme: :hide, scheme: :danger
render_error_flash_message_via_turbo_stream(
message: join_flash_messages(create_service.errors)
)
end

Expand All @@ -106,9 +105,8 @@ def unlink
delete_service.on_success { render_project_list(url_for_action: :project_mappings) }

delete_service.on_failure do
update_flash_message_via_turbo_stream(
message: join_flash_messages(delete_service.errors.full_messages),
full: true, dismiss_scheme: :hide, scheme: :danger
render_error_flash_message_via_turbo_stream(
message: join_flash_messages(delete_service.errors.full_messages)
)
end

Expand Down Expand Up @@ -184,15 +182,8 @@ def find_unlink_project_custom_field_mapping
project_id: permitted_params.project_custom_field_project_mapping[:project_id]
)
rescue ActiveRecord::RecordNotFound
update_flash_message_via_turbo_stream(
message: t(:notice_file_not_found), full: true, dismiss_scheme: :hide, scheme: :danger
)
replace_via_turbo_stream(
component: Settings::ProjectCustomFields::ProjectCustomFieldMapping::TableComponent.new(
query: project_custom_field_mappings_query,
params: { custom_field: @custom_field }
)
)
render_error_flash_message_via_turbo_stream(message: t(:notice_file_not_found))
render_project_list(url_for_action: :project_mappings)

respond_with_turbo_streams
end
Expand All @@ -213,10 +204,8 @@ def find_custom_field_projects_to_link
false
end
rescue ActiveRecord::RecordNotFound
update_flash_message_via_turbo_stream(
message: t(:notice_project_not_found), full: true, dismiss_scheme: :hide, scheme: :danger
)
render_project_list
render_error_flash_message_via_turbo_stream(message: t(:notice_project_not_found))
render_project_list(url_for_action: :project_mappings)

respond_with_turbo_streams
end
Expand Down
4 changes: 2 additions & 2 deletions app/controllers/my_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -174,13 +174,13 @@ def revoke_api_key

# rubocop:disable Rails/ActionControllerFlashBeforeRender
result.on_success do
flash[:op_primer_flash] = { message: t("my.access_token.notice_api_token_revoked") }
flash[:notice] = t("my.access_token.notice_api_token_revoked")
end

result.on_failure do |r|
error = r.errors.map(&:message).join("; ")
Rails.logger.error("Failed to revoke api token ##{current_user.id}: #{error}")
flash[:op_primer_flash] = { message: t("my.access_token.failed_to_revoke_token", error:), scheme: :danger }
flash[:error] = t("my.access_token.failed_to_revoke_token", error:)
end
# rubocop:enable Rails/ActionControllerFlashBeforeRender

Expand Down
39 changes: 29 additions & 10 deletions app/helpers/error_message_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,32 +34,51 @@ def error_messages_for(object)
object = convert_to_model(object)
return unless object

render_error_messages_partial(object.errors, object)
assign_flash_error(object.errors, object)

# Don't output anything for compability
nil
end

def render_error_messages_partial(errors, object)
return "" if errors.empty?
def assign_flash_error(errors, object)
return if errors.empty?

base_error_messages = errors.full_messages_for(:base)
fields_error_messages = errors.full_messages - base_error_messages

render partial: "common/validation_error",
locals: { base_error_messages:,
fields_error_messages:,
object_name: object.class.model_name.human }
flash[:error] = {
message: error_message_header(object.class.model_name.human, base_error_messages.count + fields_error_messages.count),
description: error_flash_description(object, base_error_messages, fields_error_messages)
}
end

def error_flash_description(_object, base_error_messages, fields_error_messages)
capture do
concat list_of_messages(base_error_messages)
concat text_header_invalid_fields(base_error_messages, fields_error_messages)
concat list_of_messages(fields_error_messages)
end
end

def error_message_header(object_name, count)
t("activerecord.errors.template.header", model: object_name, count:)
end

def text_header_invalid_fields(base_error_messages, fields_error_messages)
return if fields_error_messages.blank?

i18n_key = base_error_messages.present? ? "errors.header_additional_invalid_fields" : "errors.header_invalid_fields"
t(i18n_key, count: fields_error_messages.count)
out = "".html_safe

out << t(i18n_key, count: fields_error_messages.count)
out << "<br/>".html_safe

out
end

def list_of_messages(messages)
return if messages.blank?

messages = messages.map { |message| tag.li message }
tag.ul { safe_join(messages, "\n") }
safe_join(messages, "<br/>".html_safe)
end
end
51 changes: 24 additions & 27 deletions app/helpers/errors_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,34 +27,34 @@
#++

module ErrorsHelper
def render_400(options = {})
@project = nil
def render_400(options = {}) # rubocop:disable Naming/VariableNumber
unset_template_magic
render_error({ message: :notice_bad_request, status: 400 }.merge(options))
false
end

def render_403(options = {})
@project = nil
def render_403(options = {}) # rubocop:disable Naming/VariableNumber
unset_template_magic
render_error({ message: :notice_not_authorized, status: 403 }.merge(options))
false
end

def render_404(options = {})
def render_404(options = {}) # rubocop:disable Naming/VariableNumber
render_error({ message: :notice_file_not_found, status: 404 }.merge(options))
false
end

def render_500(options = {})
message = t(:notice_internal_server_error, app_title: Setting.app_title)

def render_500(options = {}) # rubocop:disable Naming/VariableNumber
unset_template_magic

message = t(:notice_internal_server_error, app_title: Setting.app_title)

# Append error information
if current_user.admin?
options[:message_details] = get_additional_message
end

render_error({ message: }.merge(options))
render_error({ message:, status: 500 }.merge(options))
false
end

Expand All @@ -80,37 +80,34 @@ def render_optional_error_file(status_code)
end

# Renders an error response
def render_error(arg)
def render_error(arg) # rubocop:disable Metrics/AbcSize
arg = { message: arg } unless arg.is_a?(Hash)

@status = arg[:status] || 500
@message = arg[:message]
status = arg[:status] || 500
message = arg[:message]

if @status >= 500
op_handle_error(arg[:exception] || "[Error #@status] #@message", payload: arg[:payload])
if status >= 500
op_handle_error(arg[:exception] || "[Error #status] #message", payload: arg[:payload])
end

@message = I18n.t(@message) if @message.is_a?(Symbol)
@message_details = arg[:message_details]
message = I18n.t(message) if message.is_a?(Symbol)
message_details = arg[:message_details]
respond_to do |format|
format.html do
render template: "common/error", layout: use_layout, status: @status
error_message = "[#{I18n.t(:error_code, code: status)}] #{message}\n#{message_details}"
flash.now[:error] = { message: error_message, dismiss_scheme: :none }
render template: "common/error",
layout: use_layout,
status:,
locals: { status:, params: }
end
format.any do
head @status
head status
end
end
end

def unset_template_magic
if $ERROR_INFO.is_a?(ActionView::ActionViewError)
@template.instance_variable_set(:@project, nil)
@template.instance_variable_set(:@status, 500)
@template.instance_variable_set(:@message, message)
else
@project = nil
end
rescue StandardError
# bad luck
@project = nil # rubocop:disable Rails/HelperInstanceVariable
end
end
Loading

0 comments on commit 095f641

Please sign in to comment.