Skip to content

Commit

Permalink
Merge branch 'release/14.6' into dev
Browse files Browse the repository at this point in the history
  • Loading branch information
openprojectci committed Sep 28, 2024
2 parents 8772589 + b588816 commit 011f74e
Show file tree
Hide file tree
Showing 27 changed files with 210 additions and 105 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,10 @@ def more_menu_detach_project
def detach_from_project_url
url_helpers.custom_field_project_path(
custom_field_id: @table.params[:custom_field].id,
custom_fields_project: { project_id: project.id }
custom_fields_project: { project_id: project.id },
page: current_page
)
end

def project = model.first
end
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ module Admin
module CustomFields
module CustomFieldProjects
class TableComponent < Projects::TableComponent
include OpTurbo::Streamable
include ::Projects::Concerns::TableComponent::StreamablePaginationLinksConstraints

def columns
@columns ||= query.selects.reject { |select| select.is_a?(Queries::Selects::NotExistingSelect) }
Expand All @@ -39,23 +39,6 @@ def columns
def sortable?
false
end

# @override optional_pagination_options are passed to the pagination_options
# which are passed to #pagination_links_full in pagination_helper.rb
#
# In Turbo streamable components, we need to be able to specify the url_for(action:) so that links are
# generated in the context of the component index action, instead of any turbo stream actions performing
# partial updates on the page.
#
# params[:url_for_action] is passed to the pagination_options making it's way down to any pagination links
# that are generated via link_to which calls url_for which uses the params[:url_for_action] to specify
# the controller action that link_to should use.
#
def optional_pagination_options
return super unless params[:url_for_action]

super.merge(params: { action: params[:url_for_action] })
end
end
end
end
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#-- 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.
#++

module Projects
module Concerns
module TableComponent
module StreamablePaginationLinksConstraints
# @override optional_pagination_options are passed to the pagination_options
# which are passed to #pagination_links_full in pagination_helper.rb
#
# In Turbo streamable components, we need to be able to specify the url_for(action:) so that links are
# generated in the context of the component index action, instead of any turbo stream actions performing
# partial updates on the page.
#
# params[:url_for_action] is passed to the pagination_options making it's way down to any pagination links
# that are generated via link_to which calls url_for which uses the params[:url_for_action] to specify
# the controller action that link_to should use.
#
# data-turbo-action="advance" is added to the pagination links ensure links pushState to the browser
#
def optional_pagination_options
super.tap do |options|
options[:params] = { action: params[:url_for_action] } if params[:url_for_action]
options[:turbo_action] = "advance"
end
end
end
end
end
end
4 changes: 4 additions & 0 deletions app/components/projects/row_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -373,5 +373,9 @@ def user_can_view_project?
def custom_field_column?(column)
column.is_a?(::Queries::Projects::Selects::CustomField)
end

def current_page
table.model.current_page.to_s
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ class RowComponent < Admin::CustomFields::CustomFieldProjects::RowComponent
def detach_from_project_url
url_helpers.unlink_admin_settings_project_custom_field_path(
id: @table.params[:custom_field].id,
project_custom_field_project_mapping: { project_id: project.id }
project_custom_field_project_mapping: { project_id: project.id },
page: current_page
)
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ def render_project_list(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: }
params: params.merge({ custom_field: @custom_field, url_for_action: })
)
)
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ def render_project_list(url_for_action: action_name)
update_via_turbo_stream(
component: Settings::ProjectCustomFields::ProjectCustomFieldMapping::TableComponent.new(
query: project_custom_field_mappings_query,
params: { custom_field: @custom_field, url_for_action: }
params: params.merge({ custom_field: @custom_field, url_for_action: })
)
)
end
Expand Down
15 changes: 15 additions & 0 deletions app/helpers/pagination_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ def previous_or_next_page(page, text, class_suffix)
def link(text, target, attributes)
new_attributes = attributes.dup
new_attributes["data-turbo-stream"] = true if turbo?
new_attributes["data-turbo-action"] = turbo_action if turbo_action.present?

super(text, target, new_attributes)
end
Expand All @@ -210,6 +211,20 @@ def allowed_params
@options[:allowed_params] # rubocop:disable Rails/HelperInstanceVariable
end

# Customize the Turbo visit action for pagination links. Can be set to "advance" or "replace".
# "advance" - push a new entry onto the history stack.
# "replace" - replace the current history entry.
# See: https://turbo.hotwired.dev/reference/attributes
#
# Example: Promoting a Frame Navigation to a Page Visit
# By default navigation within a turbo frame does not change the rest of the browser's state,
# but you can promote a frame navigation a "Visit" by setting the turbo-action attribute to "advance".
# See: https://turbo.hotwired.dev/handbook/frames#promoting-a-frame-navigation-to-a-page-visit
#
def turbo_action
@options[:turbo_action] # rubocop:disable Rails/HelperInstanceVariable
end

def turbo?
@options[:turbo] # rubocop:disable Rails/HelperInstanceVariable
end
Expand Down
2 changes: 1 addition & 1 deletion app/seeders/oauth_applications_seeder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def create_app
OAuth::Applications::CreateService
.new(user: User.system)
.call(
enabled: true,
enabled: false,
name: "OpenProject Mobile App",
redirect_uri: "openprojectapp://oauth-callback",
builtin: true,
Expand Down
1 change: 0 additions & 1 deletion app/views/notifications/index.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@

<% content_for :content_body do %>
<%= angular_component_tag "opce-notification-center" %>
dd
<% end %>

<% content_for :content_body_right do %>
Expand Down
6 changes: 4 additions & 2 deletions app/views/users/_consent.html.erb
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
<section class="form--section">
<h3 class="form--section-title"><%=t('consent.title')%></h3>
<% consent_link = admin_settings_users_path(anchor: 'consent_settings') %>

<%= render ::Components::OnOffStatusComponent.new({
is_on: @user.consented_at.present?,
on_text: format_time(@user.consented_at),
on_description: t('consent.user_has_consented'),
on_description: link_translate('consent.user_has_consented', links: { consent_settings: consent_link }),
off_text: t(:label_never),
off_description: t('consent.not_yet_consented')
off_description: link_translate('consent.not_yet_consented', links: { consent_settings: consent_link })
}) %>
</section>
6 changes: 3 additions & 3 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1504,8 +1504,8 @@ en:
failure_message: Consent failed, cannot proceed.
title: User Consent
decline_warning_message: You have declined to consent and have been logged out.
user_has_consented: User has consented to your configured statement at the given time.
not_yet_consented: User has not consented yet, will be requested upon next login.
user_has_consented: The user gave their consent to your [configured consent information text](consent_settings).
not_yet_consented: The user has not yet given their consent to your [configured consent information text](consent_settings). They will be reminded the next time they log in.
contact_mail_instructions: Define the mail address that users can reach a data controller to perform data change or removal requests.
contact_your_administrator: Please contact your administrator if you want to have your account deleted.
contact_this_mail_address: Please contact %{mail_address} if you want to have your account deleted.
Expand Down Expand Up @@ -3380,7 +3380,7 @@ en:
setting_total_percent_complete_mode_work_weighted_average: "Weighted by work"
setting_total_percent_complete_mode_work_weighted_average_caption_html: >-
The <i>total % Complete</i> will be weighted against the <i>Work</i> of each work package in the hierarchy.
Work packages without <i>Work</i> will be ignored (current behaviour).
Work packages without <i>Work</i> will be ignored.
setting_total_percent_complete_mode_simple_average: "Simple average"
setting_total_percent_complete_mode_simple_average_caption_html: >-
<i>Work</i> is ignored and the <i>total % Complete</i> will be a simple average of <i>% Complete</i> values of work packages in the hierarchy.
Expand Down
14 changes: 12 additions & 2 deletions frontend/src/stimulus/controllers/poll-for-changes.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,11 @@ export default class PollForChangesController extends ApplicationController {
autoscrollEnabled: Boolean,
};

static targets = ['reloadButton'];
static targets = ['reloadButton', 'reference'];

declare reloadButtonTarget:HTMLLinkElement;
declare referenceTarget:HTMLElement;
declare readonly hasReferenceTarget:boolean;

declare referenceValue:string;
declare urlValue:string;
Expand Down Expand Up @@ -69,12 +71,20 @@ export default class PollForChangesController extends ApplicationController {
clearInterval(this.interval);
}

buildReference():string {
if (this.hasReferenceTarget) {
return this.referenceTarget.dataset.referenceValue as string;
}

return this.referenceValue;
}

reloadButtonTargetConnected() {
this.reloadButtonTarget.addEventListener('click', this.rememberCurrentScrollPosition.bind(this));
}

triggerTurboStream() {
void fetch(`${this.urlValue}?reference=${this.referenceValue}`, {
void fetch(`${this.urlValue}?reference=${this.buildReference()}`, {
headers: {
Accept: 'text/vnd.turbo-stream.html',
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
<%=
helpers.content_controller "poll-for-changes",
poll_for_changes_reference_value: @meeting.changed_hash,
poll_for_changes_url_value: check_for_updates_meeting_path(@meeting),
poll_for_changes_interval_value: check_for_updates_interval,
poll_for_changes_autoscroll_enabled_value: true

component_wrapper do
render(Primer::OpenProject::PageHeader.new(
test_selector: "meeting-page-header",
state: @state
state: @state,
data: {
poll_for_changes_target: "reference",
reference_value: @meeting.changed_hash
}
)) do |header|
header.with_title do |title|
title.with_editable_form(model: @meeting,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ See COPYRIGHT and LICENSE files for more details.
component_wrapper do
primer_form_with(
model: @project_storage,
url: admin_settings_storage_project_storage_path(id: @project_storage),
url: admin_settings_storage_project_storage_path(id: @project_storage, page: current_page),
data: {
turbo: true,
controller: 'disable-when-checked',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,12 @@ class DestroyConfirmationDialogComponent < ApplicationComponent
include OpTurbo::Streamable
include OpPrimer::ComponentHelpers

def initialize(storage:, project_storage:)
def initialize(storage:, project_storage:, params: {})
super

@storage = storage
@project_storage = project_storage
@params = params
end

def id
Expand All @@ -56,6 +57,10 @@ def text
text
end

def current_page
@params[:page]
end

def confirmation_text
I18n.t("project_storages.remove_project.dialog.confirmation_text")
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ def more_menu_detach_project
icon: :trash,
label: I18n.t("project_storages.remove_project.label"),
href: destroy_confirmation_dialog_admin_settings_storage_project_storage_path(
id: project_storage.id
id: project_storage.id,
page: current_page
),
data: {
controller: "async-dialog"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
# for every "column" defined below.
module Storages::ProjectStorages::Projects
class TableComponent < Projects::TableComponent
include OpTurbo::Streamable
include ::Projects::Concerns::TableComponent::StreamablePaginationLinksConstraints

options :storage

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,8 @@ def update
def destroy_confirmation_dialog
respond_with_dialog Storages::ProjectStorages::DestroyConfirmationDialogComponent.new(
storage: @storage,
project_storage: @project_storage
project_storage: @project_storage,
params:
)
end

Expand Down Expand Up @@ -186,7 +187,7 @@ def update_project_list_via_turbo_stream(url_for_action: action_name)
component: Storages::ProjectStorages::Projects::TableComponent.new(
query: storage_projects_query,
storage: @storage,
params: { url_for_action: }
params: params.merge({ url_for_action: })
)
)
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,10 @@

expect(page).to have_text(project.name)
expect(page).to have_text(subproject.name)

aggregate_failures "pagination links maintain the correct url" do
project_storages_index_page.expect_page_sizes(model: storage)
end
end

context "when the user does not select a folder" do
Expand Down Expand Up @@ -297,6 +301,10 @@
project_storages_index_page.within_the_table_row_containing(project.name) do
expect(page).to have_text("No specific folder")
end

aggregate_failures "pagination links maintain the correct url" do
project_storages_index_page.expect_page_sizes(model: storage)
end
end

context "when oauth access has not been granted and manual selection" do
Expand Down Expand Up @@ -363,8 +371,15 @@ def call
expect(page).to have_text(project.name)
end

it "is possible to remove the project after checking the confirmation checkbox in the dialog" do
expect(page).to have_text(project.name)
it "is possible to remove the project after checking the confirmation checkbox in the dialog",
with_settings: { per_page_options: "2,5" } do
projects = create_list(:project, 4)
projects.each { |project| create(:project_storage, storage:, project:) }

current_page = 3
visit admin_settings_storage_project_storages_path(storage, page: current_page)

project = project_storages_index_page.project_in_first_row(column_text_separator: "\t")
project_storages_index_page.click_menu_item_of("Remove project", project)

# The original DeleteService would try to remove actual files from actual storages,
Expand All @@ -388,6 +403,10 @@ def call
expect(page).to have_no_selector("dialog")
expect(page).to have_text("Successful deletion.")
expect(page).to have_no_text(project.name)

aggregate_failures "pagination links maintain the correct url" do
project_storages_index_page.expect_page_links(model: storage, current_page:)
end
end
end
end
Expand Down
Loading

0 comments on commit 011f74e

Please sign in to comment.