Skip to content
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

[56339] Split content of Admin/Design page into separate tabs #16255

Merged
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
57ba340
use page header component in design page
bsatarnejad Jul 26, 2024
847bd25
Merge branch 'dev' into 56339-split-content-of-admin-design-page-into…
bsatarnejad Sep 4, 2024
edf70cd
create a new component for design page header
bsatarnejad Sep 4, 2024
5707420
create separate views for each tab
bsatarnejad Sep 4, 2024
ac2bdce
after each action it should be redirected to the current url
bsatarnejad Sep 5, 2024
63c069a
fix rubocop errors
bsatarnejad Sep 5, 2024
c7702d3
fix failing tests in custom styles controller spec
bsatarnejad Sep 9, 2024
91565cd
fix failing specs
bsatarnejad Sep 9, 2024
6edaadd
change header Advanced settings to Interface colours
bsatarnejad Sep 10, 2024
c032d46
add some description for interface colours
bsatarnejad Sep 10, 2024
e3d4e1b
change design header component to use tab helper
bsatarnejad Sep 12, 2024
babcc64
use partials for rendering tabs content
bsatarnejad Sep 12, 2024
343e87f
remove unnecessary pathes
bsatarnejad Sep 12, 2024
35e5940
add tab to the default url options
bsatarnejad Sep 13, 2024
74a56e1
test redirect to interface tab, when there is an ee token
bsatarnejad Sep 13, 2024
72c12f5
write a feature spec and remove unnecessary tests
bsatarnejad Sep 13, 2024
5889dac
change the test to check if it is in interface tab in the first page …
bsatarnejad Sep 17, 2024
0c959a9
change some specs
bsatarnejad Sep 17, 2024
897e27e
fix rubocup errors
bsatarnejad Sep 17, 2024
875d40b
fix rubocup errors
bsatarnejad Sep 18, 2024
809f6d9
add a test to check if the file is deleted
bsatarnejad Sep 18, 2024
e484a82
Merge branch 'dev' into 56339-split-content-of-admin-design-page-into…
bsatarnejad Sep 18, 2024
ef60a0f
Update app/components/admin/design_header_component.html.erb
bsatarnejad Sep 19, 2024
a419ae6
change nil to an empty array
bsatarnejad Sep 19, 2024
e1bfea1
fix rubocup warning and some spacing
bsatarnejad Sep 19, 2024
bd71e43
change test file name and uts description
bsatarnejad Sep 19, 2024
af1d6a9
fix some indentations
bsatarnejad Sep 19, 2024
38faf36
change colours to color in interface tab
bsatarnejad Sep 19, 2024
96481e2
change colour to color for custom styles description
bsatarnejad Sep 19, 2024
bdbb6e6
Merge branch 'dev' into 56339-split-content-of-admin-design-page-into…
bsatarnejad Sep 19, 2024
83a1730
Provide direction of redirect in spec
oliverguenther Sep 20, 2024
bf42337
add a test for a tab param
oliverguenther Sep 20, 2024
c98dcbf
fix failing tests due to string variable changes
bsatarnejad Sep 20, 2024
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
45 changes: 45 additions & 0 deletions app/components/admin/design_header_component.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<%#-- 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.

++#%>

<% helpers.html_title t(:label_administration), t(:label_custom_style), @title %>
<%=
render(Primer::OpenProject::PageHeader.new) do |header|
header.with_title { t(:label_custom_style) }
header.with_breadcrumbs([{ href: admin_index_path, text: t(:label_administration) },
t(:label_custom_style)])
header.with_description { t(:label_custom_style_description) }
header.with_tab_nav(label: nil) do |tab_nav|
@tabs.each do |tab|
tab_nav.with_tab(selected: selected_tab(@tabs) == tab, href: tab[:path]) do |t|
t.with_text { tab[:label] }
end
end
end if @tabs.present?
end
bsatarnejad marked this conversation as resolved.
Show resolved Hide resolved
%>
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# frozen_string_literal: true

#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
Expand Down Expand Up @@ -26,38 +28,15 @@
# See COPYRIGHT and LICENSE files for more details.
#++

require "spec_helper"

RSpec.describe "custom_styles/show" do
let(:user) { build(:admin) }

before do
login_as user
end

context "no custom logo yet" do
before do
assign(:custom_style, CustomStyle.new)
assign(:current_theme, "")
allow(view).to receive(:options_for_select).and_return("")
render
end

it "shows an upload button" do
expect(rendered).to include "Upload"
end
end

context "with existing custom logo" do
before do
assign(:custom_style, build(:custom_style_with_logo))
assign(:current_theme, "")
allow(view).to receive(:options_for_select).and_return("")
render
end
module Admin
class DesignHeaderComponent < ApplicationComponent
include OpPrimer::ComponentHelpers
include ApplicationHelper
include TabsHelper

it "shows a replace button" do
expect(rendered).to include "Replace"
def initialize(tabs: nil)
bsatarnejad marked this conversation as resolved.
Show resolved Hide resolved
super
@tabs = tabs
end
end
end
14 changes: 7 additions & 7 deletions app/controllers/custom_styles_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,16 @@
only: UNGUARDED_ACTIONS
no_authorization_required! *UNGUARDED_ACTIONS

def default_url_options
super.merge(tab: params[:tab])
end
bsatarnejad marked this conversation as resolved.
Show resolved Hide resolved
def show
@custom_style = CustomStyle.current || CustomStyle.new
@current_theme = @custom_style.theme
@theme_options = options_for_theme_select
if params[:tab].blank?
bsatarnejad marked this conversation as resolved.
Show resolved Hide resolved
redirect_to tab: "interface"
end
end

def upsale; end
Expand Down Expand Up @@ -134,27 +140,22 @@
redirect_to action: :show
end

def update_themes
theme = OpenProject::CustomStyles::ColorThemes.themes.find { |t| t[:theme] == params[:theme] }

call = ::Design::UpdateDesignService
.new(theme)
.call

call.on_success do
flash[:notice] = I18n.t(:notice_successful_update)
end

call.on_failure do
flash[:error] = call.message
end

redirect_to action: :show
end

def show_local_breadcrumb
false
redirect_to custom_style_path
bsatarnejad marked this conversation as resolved.
Show resolved Hide resolved
end

Check notice on line 158 in app/controllers/custom_styles_controller.rb

View workflow job for this annotation

GitHub Actions / rubocop

[rubocop] app/controllers/custom_styles_controller.rb#L143-L158 <Metrics/AbcSize>

Assignment Branch Condition size for update_themes is too high. [<5, 17, 2> 17.83/17]
Raw output
app/controllers/custom_styles_controller.rb:143:3: C: Metrics/AbcSize: Assignment Branch Condition size for update_themes is too high. [<5, 17, 2> 17.83/17]

private

Expand Down Expand Up @@ -202,7 +203,6 @@
if @custom_style.nil?
return render_404
end

@custom_style.send(remove_method)
redirect_to custom_style_path
end
Expand Down
23 changes: 23 additions & 0 deletions app/helpers/custom_styles_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,29 @@
#++

module CustomStylesHelper
def design_tabs
[
{
name: "interface",
partial: "custom_styles/interface",
path: custom_style_path(tab: :interface),
label: t(:"admin.custom_styles.tab_interface")
},
{
name: "branding",
partial: "custom_styles/branding",
path: custom_style_path(tab: :branding),
label: t(:"admin.custom_styles.tab_branding")
},
{
name: "pdf_export_styles",
partial: "custom_styles/pdf_export_styles",
path: custom_style_path(tab: :pdf_export_styles),
label: t(:"admin.custom_styles.tab_pdf_export_styles")
}
]
end

def apply_custom_styles?(skip_ee_check: OpenProject::Configuration.bim?)
# Apply custom styles either if EE allows OR we are on a BIM edition with the BIM theme active.
CustomStyle.current.present? &&
Expand Down
119 changes: 119 additions & 0 deletions app/views/custom_styles/_branding.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
<%#-- 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.

++#%>

<%= form_for @custom_style, url: custom_style_path, html: { multipart: true, class: "form -vertical" } do |f| %>
<section class="form--section">
<fieldset class="form--fieldset">
<legend class="form--fieldset-legend"><%= I18n.t(:label_custom_logo) %></legend>
<% if @custom_style.id && @custom_style.logo.present? %>
<div>
<%# Don't use image_tag here due to asset host %>
<%= tag('img', src: custom_style_logo_path(digest: @custom_style.digest, filename: @custom_style.logo_identifier), class: 'custom-logo-preview') %>
<%= link_to t(:button_delete),
custom_style_logo_delete_path,
method: :delete,
class: 'icon icon-delete confirm-form-submit' %>
</div>
<% end %>
<div class="grid-block">
<div class="form--field -required">
<div class="attachment_field form--field-container -vertical -shrink">
<div class="form--file-container">
<%= f.file_field :logo, required: true, class: "attachment_choose_file", size: "15" %>
</div>
</div>
<div class="form--field-instructions">
<%= t('text_custom_logo_instructions') %>
</div>
</div>
</div>
<%= styled_button_tag I18n.t(@custom_style.logo.present? ? :button_replace : :button_upload),
class: "button #{@custom_style.logo.blank? ? '-with-icon icon-add' : ''}" %>
</fieldset>
</section>
<% end %>
<%= form_for @custom_style, url: custom_style_path, html: { multipart: true, class: "form -vertical" } do |f| %>
<section class="form--section">
<fieldset class="form--fieldset">
<legend class="form--fieldset-legend"><%= I18n.t(:label_custom_favicon) %></legend>

<% if @custom_style.id && @custom_style.favicon.present? %>
<div>
<%= tag('img', src: custom_style_favicon_path(digest: @custom_style.digest, filename: @custom_style.favicon_identifier), class: 'custom-favicon-preview') %>
<%= link_to t(:button_delete),
custom_style_favicon_delete_path,
method: :delete,
class: 'icon icon-delete confirm-form-submit' %>
</div>
<% end %>
<div class="grid-block">
<div class="form--field -required">
<div class="attachment_field form--field-container -vertical -shrink">
<div class="form--file-container">
<%= f.file_field :favicon, required: true, class: "attachment_choose_file", size: "15" %>
</div>
</div>
<div class="form--field-instructions">
<%= t('text_custom_favicon_instructions') %>
</div>
</div>
</div>
<%= styled_button_tag t(@custom_style.favicon.present? ? :button_replace : :button_upload), class: "button #{@custom_style.favicon.blank? ? '-with-icon icon-add' : ''}" %>
</fieldset>
</section>
<% end %>
<%= form_for @custom_style, url: custom_style_path, html: { multipart: true, class: "form -vertical" } do |f| %>
<section class="form--section">
<fieldset class="form--fieldset">
<legend class="form--fieldset-legend"><%= I18n.t(:label_custom_touch_icon) %></legend>
<% if @custom_style.id && @custom_style.touch_icon.present? %>
<div>
<%= tag('img', src: custom_style_touch_icon_path(digest: @custom_style.digest, filename: @custom_style.touch_icon_identifier), class: 'custom-touch-icon-preview') %>
<%= link_to t(:button_delete),
custom_style_touch_icon_delete_path,
method: :delete,
class: 'icon icon-delete confirm-form-submit' %>
</div>
<% end %>
<div class="grid-block">
<div class="form--field -required">
<div class="attachment_field form--field-container -vertical -shrink">
<div class="form--file-container">
<%= f.file_field :touch_icon, required: true, class: "attachment_choose_file", size: "15" %>
</div>
</div>
<div class="form--field-instructions">
<%= t('text_custom_touch_icon_instructions') %>
</div>
</div>
</div>
<%= styled_button_tag t(@custom_style.touch_icon.present? ? :button_replace : :button_upload), class: "button #{@custom_style.touch_icon.blank? ? '-with-icon icon-add' : ''}" %>
</fieldset>
</section>
<% end %>
45 changes: 45 additions & 0 deletions app/views/custom_styles/_interface.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<%= form_tag update_design_colors_path, method: :post, class: "form" do %>
<section class="form--section">
<fieldset class="form--fieldset">
<legend class="form--fieldset-legend"><%= I18n.t(:label_interface_colours) %></legend>
<p> <%= t('label_interface_colours_description') %> </p>
bsatarnejad marked this conversation as resolved.
Show resolved Hide resolved
<% DesignColor.setables.each do |design_color| %>
<div class="form--field -required">
<label class="form--label"><%= I18n.t("admin.custom_styles.colors.#{design_color.variable}") %>:</label>
<span class="form--field-container">
<div class="form--field-affix">
<%= icon_for_color(OpenStruct.new(variable: design_color.variable,
hexcode: design_color.hexcode),
data: { target: "#design_colors_" + design_color.variable }) %>
</div>
<span class="form--text-field-container">
<%= styled_text_field_tag "design_colors[]" + design_color.variable,
design_color.hexcode,
class: 'design-color--variable-input',
data: { 'variable-name': design_color.variable }
%>
</span>
</span>
<div class="form--field-instructions">
<% instruction_key = "admin.custom_styles.instructions.#{design_color.variable}" %>
<% if I18n.exists?(instruction_key, :en) %>
<%= I18n.t(instruction_key) %>
<% end %>
</div>
</div>
<% end %>
<button type="submit" class="button -hide-when-collapsed" data-test-selector="interface-colors-button"><%= I18n.t(:button_save) %></button>
</fieldset>
</section>
<%# Fill in the computed css variables in the inputs as their defaults %>
<%= nonced_javascript_tag do %>
var computedStyle = getComputedStyle(document.documentElement);
document
.querySelectorAll('.design-color--variable-input')
.forEach(function(el) {
if (!el.value || el.value === '') {
el.placeholder = computedStyle.getPropertyValue('--' + el.dataset.variableName).trim();
}
});
bsatarnejad marked this conversation as resolved.
Show resolved Hide resolved
<% end %>
<% end %>
Loading