Skip to content

[pull] dev from opf:dev #528

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 37 commits into from
Apr 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
b9c3a7d
[#62217] allow custom fields that are not enabled in project
Kharonus Mar 31, 2025
1f5ce42
Update en.yml
HDinger Apr 2, 2025
a1997ee
Update test
HDinger Apr 2, 2025
f283fca
Create release notes draft for 15.5.0
oliverguenther Apr 3, 2025
13e1545
Bumped version to 15.6.0
oliverguenther Apr 3, 2025
f107360
Bump the fullcalendar group in /frontend with 8 updates
dependabot[bot] Apr 3, 2025
c96734d
Bump the angular group in /frontend with 2 updates
dependabot[bot] Apr 3, 2025
ccae401
Merge pull request #18517 from opf/HDinger-patch-1
HDinger Apr 3, 2025
54cb634
Update en.yml
HDinger Apr 2, 2025
5d7ed95
Update test
HDinger Apr 2, 2025
9536ecf
Merge pull request #18479 from opf/bug/62217-updating-a-work-package-…
Kharonus Apr 3, 2025
0ff47c2
[#57388] create table: export_settings
EinLama Mar 26, 2025
97222c3
[#57388] work with symbolized keys where possible
EinLama Mar 27, 2025
ab2ae3a
[#57388] CSV export reads from ExportSetting
EinLama Mar 27, 2025
2c2ee12
[#57388] use ApplicationComponent pattern for the BaseExportSettingsC…
EinLama Mar 27, 2025
ac92820
[#57388] XLS export reads from ExportSetting
EinLama Mar 27, 2025
f23d7a3
[#57388] PDF table export reads from ExportSetting
EinLama Mar 27, 2025
32a12ef
[#57388] PDF report export reads from ExportSetting
EinLama Mar 27, 2025
2007af0
[#57388] PDF gantt export reads from ExportSetting
EinLama Mar 28, 2025
a036245
[#57388] render (and send) checkbox within dialog
EinLama Mar 28, 2025
8402752
[#57388] save export settings to database if checkbox is checked
EinLama Mar 31, 2025
e56d3c9
[#57388] restore column order from last save
EinLama Mar 31, 2025
d3c753d
[#57388] move save checkbox to the left
EinLama Mar 31, 2025
d12129c
[#57388] provide default value to `true?`
EinLama Mar 31, 2025
015da09
[#57388] fix: allow default text fields
EinLama Mar 31, 2025
8be0057
[#57388] fix: don't break without 'save export settings' checkbox
EinLama Mar 31, 2025
b385470
[#57388] require a saved query for saving export settings
EinLama Mar 31, 2025
216c0c6
[#57388] spec: query export settings
EinLama Apr 1, 2025
a460962
[#57388] feature-spec: query export settings
EinLama Apr 1, 2025
64c6764
[#57388] reduce code complexity
EinLama Apr 1, 2025
86c9169
[#57388] feature-spec: also expect the correct columns
EinLama Apr 2, 2025
549eb2f
[#57388] feature-spec: expect the correct long text fields
EinLama Apr 2, 2025
ddf2702
[#57388] unit tests for export_settings
EinLama Apr 2, 2025
c330e59
[#57388] ensure a saved query is considered for the global wp list
EinLama Apr 3, 2025
92494a4
Bump primer to 0.59.1
HDinger Apr 3, 2025
3db73e3
Merge pull request #18533 from opf/housekeeping/bump-primer-0-59-1
HDinger Apr 3, 2025
b717a5e
Merge remote-tracking branch 'origin/release/15.5' into dev
HDinger Apr 3, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -412,4 +412,4 @@ end

gem "openproject-octicons", "~>19.23.0"
gem "openproject-octicons_helper", "~>19.23.0"
gem "openproject-primer_view_components", "~>0.59.0"
gem "openproject-primer_view_components", "~>0.59.1"
6 changes: 3 additions & 3 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -858,7 +858,7 @@ GEM
actionview
openproject-octicons (= 19.23.0)
railties
openproject-primer_view_components (0.59.0)
openproject-primer_view_components (0.59.1)
actionview (>= 5.0.0)
activesupport (>= 5.0.0)
openproject-octicons (>= 19.23.0)
Expand Down Expand Up @@ -1391,7 +1391,7 @@ DEPENDENCIES
openproject-octicons (~> 19.23.0)
openproject-octicons_helper (~> 19.23.0)
openproject-openid_connect!
openproject-primer_view_components (~> 0.59.0)
openproject-primer_view_components (~> 0.59.1)
openproject-recaptcha!
openproject-reporting!
openproject-storages!
Expand Down Expand Up @@ -1757,7 +1757,7 @@ CHECKSUMS
openproject-octicons (19.23.0) sha256=bf69988c440b4aef249b2cb30e7c4139370e3b5d0c6e77ef2323eb0f48a37c13
openproject-octicons_helper (19.23.0) sha256=d501eb62e323e326ce56eb9e4ea0d499dfca8ec5c382843c78025a529a0a8156
openproject-openid_connect (1.0.0)
openproject-primer_view_components (0.59.0) sha256=72eb181f8151d07f3de42b92e3afb44c5ab3f196557249ab3ef38f44cedde2a0
openproject-primer_view_components (0.59.1) sha256=bd747e187093269e54fc8e26df9a1465765d138dd468e7c6c5e1774f597b08e3
openproject-recaptcha (1.0.0)
openproject-reporting (1.0.0)
openproject-storages (1.0.0)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,16 @@ class BaseExportSettingsComponent < ApplicationComponent
include OpTurbo::Streamable
include WorkPackagesHelper

attr_reader :query
def query
model
end

def initialize(query)
super
def format
raise NotImplementedError, "Must be overridden in subclass"
end

@query = query
def export_settings
@export_settings ||= query.export_settings_for(format)
end
end
end
Expand Down
19 changes: 16 additions & 3 deletions app/components/work_packages/exports/column_selection_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,15 @@ module Exports
class ColumnSelectionComponent < ApplicationComponent
include WorkPackagesHelper

attr_reader :query, :id, :caption, :label
attr_reader :export_settings, :query, :id, :caption, :label

def initialize(query, id, caption,
def initialize(export_settings, id, caption,
label = I18n.t(:"queries.configure_view.columns.input_label"),
required: true)
super()

@query = query
@export_settings = export_settings
@query = @export_settings.query
@id = id
@caption = caption
@label = label
Expand All @@ -59,10 +60,22 @@ def protected_options
end

def selected_columns
return columns_from_saved_export_settings if export_settings.settings.key?(:columns)

query
.columns
.map { |column| { id: column.name.to_s, name: column.caption } }
end

private

def columns_from_saved_export_settings
saved_cols = export_settings.settings[:columns]
# Restore the saved columns, retaining the saved order
saved_cols.filter_map do |col|
available_columns.find { |c| c[:id] == col }
end
end
end
end
end
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<%= flex_layout do |container| %>
<%= container.with_row do |_columns| %>
<%= render WorkPackages::Exports::ColumnSelectionComponent.new(
query,
export_settings,
"columns-select-export-csv",
I18n.t("export.dialog.columns.input_caption_table")
) %>
Expand All @@ -14,9 +14,13 @@
name: "show_descriptions",
value: "true",
unchecked_value: "false",
checked: export_settings.true?(:show_descriptions),
label: I18n.t("export.dialog.xls.include_descriptions.label"),
caption: I18n.t("export.dialog.xls.include_descriptions.caption"),
visually_hide_label: false
visually_hide_label: false,
data: {
test_selector: "show-descriptions-csv"
}
)
) %>
<% end %>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ module WorkPackages
module Exports
module CSV
class ExportSettingsComponent < BaseExportSettingsComponent
def format
"csv"
end
end
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,24 @@
<% end %>
<% end %>
<% end %>
<% dialog.with_footer do %>
<% dialog.with_footer(show_divider: true) do %>
<% if offer_to_save_export_settings? %>
<%= render(Primer::BaseComponent.new(tag: :span, mr: :auto)) do %>
<%= render(
Primer::Alpha::CheckBox.new(
id: "#{EXPORT_FORM_ID}-save_export_settings",
name: "save_export_settings",
value: "true",
unchecked_value: "false",
checked: saved_export_settings?,
label: I18n.t("export.dialog.save_export_settings.label"),
data: {
test_selector: "#{EXPORT_FORM_ID}-save-export-settings"
}
)
) %>
<% end %>
<% end %>
<%= render(Primer::ButtonComponent.new(data: { "close-dialog-id": MODAL_ID })) { I18n.t(:button_cancel) } %>
<%= render(
Primer::ButtonComponent.new(
Expand Down
17 changes: 13 additions & 4 deletions app/components/work_packages/exports/modal_dialog_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,23 @@ def initialize(query:, project:, title:)

def export_format_url(format)
if @project.nil?
index_work_packages_path(format:)
elsif @query.id.present?
project_work_packages_path(project, query_id: @query.id, format:)
# Global work package list. The query_id might be nil for unsaved queries.
index_work_packages_path(format:, query_id: @query.id)
else
project_work_packages_path(project, format:)
# Project work package list. The query_id might be nil for unsaved queries.
project_work_packages_path(project, query_id: @query.id, format:)
end
end

# Users can save their export settings, but only for saved queries.
def offer_to_save_export_settings?
@query.persisted?
end

def saved_export_settings?
@query.export_settings.any?(&:persisted?)
end

def export_formats_settings
[
{ id: "pdf", icon: :"op-pdf",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
size: :medium,
input_width: :small
)) do |component|
selected = entry[:options].find { |e| e[:default] }[:value]
entry[:options].each do |entry|
component.option(label: entry[:label], value: entry[:value], selected: selected == entry[:value])
selected = find_selected_option(entry)
entry[:options].each do |e|
component.option(label: e[:label], value: e[:value], selected: selected[:value] == e[:value])
end
end %>
<% end %>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ module Exports
module PDF
module Gantt
class ExportSettingsComponent < BaseExportSettingsComponent
def format
"pdf_gantt"
end

def gantt_selects
[
{
Expand All @@ -55,6 +59,26 @@ def gantt_selects
]
end

# Reads the saved value from the export settings and returns the selected option.
# When there is no saved value, returns the default option.
# @param [Hash] entry one entry from `gantt_selects`
def find_selected_option(entry)
select_name = entry[:name].to_sym
if export_settings.settings.key?(select_name)
saved_value = export_settings.settings[select_name]

entry[:options].find { |option| option[:value] == saved_value } || find_default_option(entry)
else
find_default_option(entry)
end
end

# Returns the default option for a gantt_select entry.
# @param [Hash] entry one entry from `gantt_selects`
def find_default_option(entry)
entry[:options].find { |option| option[:default] }
end

def gantt_zoom_levels
[
{ label: t("export.dialog.pdf.gantt_zoom_levels.options.days"), value: "day", default: true },
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<%= flex_layout do |container| %>
<% container.with_row do |_columns| %>
<%= render WorkPackages::Exports::ColumnSelectionComponent.new(
query,
export_settings,
"columns-select-export-pdf-report",
I18n.t("export.dialog.columns.input_caption_report"),
I18n.t("export.dialog.columns.input_label_report"),
Expand Down Expand Up @@ -31,7 +31,7 @@
<%= render(
Primer::Alpha::CheckBox.new(
name: "show_images",
checked: true,
checked: export_settings.true?(:show_images, default: true),
value: "true",
unchecked_value: "false",
label: I18n.t("export.dialog.pdf.include_images.label"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,26 @@ module Report
class ExportSettingsComponent < BaseExportSettingsComponent
DESCRIPTION_CF = { id: "description", name: WorkPackage.human_attribute_name("description") }.freeze

def format
"pdf_report"
end

def available_long_text_fields
[DESCRIPTION_CF] + WorkPackageCustomField.where(field_format: "text")
.map { |cf| { id: cf.id, name: cf.name } }
end

def selected_long_text_fields
available_long_text_fields
default_long_text_fields = available_long_text_fields

saved_long_text_fields = if export_settings.settings.key?(:long_text_fields)
saved = export_settings.settings.fetch(:long_text_fields, "").split
default_long_text_fields.select do |cf|
saved.include?(cf[:id].to_s)
end
end

saved_long_text_fields || default_long_text_fields
end

def protected_long_text_fields
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<%= render WorkPackages::Exports::ColumnSelectionComponent.new(
query,
export_settings,
"columns-select-export-pdf-table",
I18n.t("export.dialog.columns.input_caption_table")
) %>
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ module Exports
module PDF
module Table
class ExportSettingsComponent < BaseExportSettingsComponent
def format
"pdf_table"
end
end
end
end
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<%= flex_layout do |container| %>
<%= container.with_row do |_columns| %>
<%= render WorkPackages::Exports::ColumnSelectionComponent.new(
query,
export_settings,
"columns-select-export-xls",
I18n.t("export.dialog.columns.input_caption_table")
) %>
Expand All @@ -14,6 +14,7 @@
name: "show_relations",
value: "true",
unchecked_value: "false",
checked: export_settings.true?(:show_relations),
label: I18n.t("export.dialog.xls.include_relations.label"),
caption: I18n.t("export.dialog.xls.include_relations.caption"),
visually_hide_label: false
Expand All @@ -28,6 +29,7 @@
name: "show_descriptions",
value: "true",
unchecked_value: "false",
checked: export_settings.true?(:show_descriptions),
label: I18n.t("export.dialog.xls.include_descriptions.label"),
caption: I18n.t("export.dialog.xls.include_descriptions.caption"),
visually_hide_label: false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ module WorkPackages
module Exports
module XLS
class ExportSettingsComponent < BaseExportSettingsComponent
def format
"xls"
end
end
end
end
Expand Down
20 changes: 20 additions & 0 deletions app/controllers/work_packages_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,8 @@ def load_and_validate_query_for_export
end

def export_list(mime_type)
save_export_settings if params[:save_export_settings]&.to_bool

job_id = WorkPackages::Exports::ScheduleService
.new(user: current_user)
.call(query: @query, mime_type:, params:)
Expand Down Expand Up @@ -169,6 +171,24 @@ def atom_journals

private

def save_export_settings
# Saving export settings is only allowed for saved queries
return false if @query.new_record?

relevant_keys = %i[format columns show_relations show_descriptions long_text_fields
show_images gantt_mode gantt_width paper_size]

user_settings = params.slice(*relevant_keys)

if user_settings[:format] == "pdf"
user_settings[:format] = "pdf_#{params[:pdf_export_type]}"
end

export_settings = @query.export_settings_for(user_settings[:format])
export_settings.settings = user_settings
export_settings.save
end

def authorize_on_work_package
deny_access(not_found: true) unless work_package
end
Expand Down
Loading
Loading