Files
2026-03-19 13:39:05 +01:00

224 lines
8.5 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.
++#%><!DOCTYPE html>
<% show_decoration = params["layout"].nil? %>
<html xmlns="http://www.w3.org/1999/xhtml"
lang="<%= I18n.locale.to_s %>"
xml:lang="<%= I18n.locale.to_s %>"
class="<%= "in_modal" unless show_decoration %>">
<head>
<%= render partial: "layouts/common_head" %>
<!-- project specific tags -->
<%= call_hook :view_layouts_base_html_head %>
<!-- page specific tags -->
<%= content_for(:header_tags) if content_for?(:header_tags) %>
<meta name="current_menu_item" content="<%= current_menu_item %>"/>
</head>
<%= content_tag :body,
class: "#{body_css_classes} __overflowing_element_container __overflowing_body",
data: body_data_attributes(local_assigns) do %>
<%= render partial: "warning_bar/warning_bar" %>
<noscript>
<div class="top-shelf">
<p>
<span>
<%= op_icon "icon3 icon-warning" %>
<strong><%= t(:noscript_heading) %></strong>
</span>
<%= t(:noscript_description) %>
<a href="http://www.enable-javascript.com/" target="_blank"><%= t(:noscript_learn_more) %></a>
</p>
</div>
</noscript>
<opce-toasts-container></opce-toasts-container>
<%= render partial: "layouts/flashes" %>
<opce-modal-overlay></opce-modal-overlay>
<live-region></live-region>
<span id="open-blank-target-link-description" class="sr-only"><%= I18n.t("open_link_in_a_new_tab") %></span>
<opce-spot-drop-modal-portal></opce-spot-drop-modal-portal>
<% main_menu = render_main_menu(local_assigns.fetch(:menu_name, nil), @project) %>
<% side_displayed = content_for?(:sidebar) || content_for?(:main_menu) || !main_menu.blank? %>
<% initial_classes = initial_menu_classes(side_displayed, show_decoration) %>
<div id="wrapper" style="<%= initial_menu_styles %>" class="<%= initial_classes %>">
<% if show_decoration %>
<header class="op-app-header<%= " op-app-header_development" if OpenProject::Configuration.development_highlight_enabled? %>">
<div class="op-app-header--start">
<a href="" class="sr-only skip-navigation-link"
id="skip-navigation--content"
aria-label="<%= I18n.t("js.work_packages.jump_marks.label_content") %>">
<%= I18n.t("js.work_packages.jump_marks.content") %>
</a>
<%= render_top_menu_left %>
</div>
<div class="op-app-header--center op-app-header--center_mobile-end">
<%= render_top_menu_center %>
</div>
<div class="op-app-header--end">
<%= call_hook :view_layouts_base_top_menu %>
<%= render_top_menu_right %>
</div>
</header>
<% end %>
<div id="main"
class="<%= initial_classes %>"
data-controller="menus--main-toggle">
<% if (side_displayed && show_decoration) %>
<nav
id="main-menu"
class="main-menu"
data-controller="menus--main"
aria-label="<%= t(:label_main_menu) %>">
<opce-main-menu-resizer></opce-main-menu-resizer>
<div id="menu-sidebar">
<div class="main-menu--top-container">
<%= render(Primer::OpenProject::FlexLayout.new(align_items: :center, pt: 3)) do |flex|
flex.with_column(overflow: :hidden) do
render_projects_top_menu_node
end
flex.with_column(text_align: :right, flex: :auto) do
render(OpenProject::Common::MainMenuToggleComponent.new(expanded: true))
end
end %>
<%= render(
Primer::BaseComponent.new(
tag: :hr,
classes: "main-menu--projects-divider",
role: :presentation,
aria: {
hidden: true
}
)
) %>
</div>
<%= main_menu %>
<%= content_for :main_menu %>
<%= call_hook :view_layouts_base_main_menu %>
<%=
render(EnterpriseEdition::TrialTeaserComponent.new)
%>
<!-- Sidebar -->
<div id="sidebar" data-menus--main-target="sidebar">
<%= content_for :sidebar %>
<%= call_hook :view_layouts_base_sidebar %>
</div>
</div>
</nav>
<% end %>
<div class="content-overlay"
data-action="click->menus--main-toggle#toggleNavigation"></div>
<%= content_tag :main, id: "content-wrapper", class: initial_classes, data: stimulus_content_data do %>
<% if show_onboarding_modal? %>
<section data-augmented-model-wrapper
data-modal-initialize-now="true"
data-modal-class-name="onboarding-modal">
<%= render partial: "/onboarding/configuration_modal" %>
</section>
<% end %>
<%= content_tag :div,
id: "content",
class: "#{initial_classes} #{'content--split' if content_for?(:content_body_right)}" do %>
<h1 class="sr-only accessibility-helper"><%= t(:label_content) %></h1>
<% if content_for?(:content_header) %>
<div id="content-header">
<%=
render(
OpenProject::Common::MainMenuToggleComponent.new(
expanded: false,
aria: { controls: "main-menu" }
)
)
%>
<%= content_for :content_header %>
</div>
<% end %>
<div id="content-body">
<% unless content_for?(:content_header) %>
<%=
render(
OpenProject::Common::MainMenuToggleComponent.new(
expanded: false,
aria: { controls: "main-menu" }
)
)
%>
<% end %>
<%= content_for :content_body %>
<% unless local_assigns[:no_layout_yield] %>
<%= yield %>
<% end %>
</div>
<%= turbo_frame_tag "content-bodyRight" do %>
<%= content_for :content_body_right %>
<% end %>
<% end %>
<% end %>
</div>
<%= render Primer::Beta::Spinner.new(
size: :large,
hidden: true,
wrapper_arguments: { id: "global-loading-indicator", position: :absolute }
) %>
</div>
<%# Properly decides main menu expanded state and width before its drawn. Fixes flickering side menu
where menu is first expanded, then being collapsed in angular. %>
<%= nonced_javascript_tag type: "module" do %>
// execute these lines to prevent flickering when page loads:
const wrapper = document.getElementById('wrapper');
const mainMenuCollapsed = window.OpenProject.guardedLocalStorage('openProject-mainMenuCollapsed');
let savedMainMenuWidth;
if (mainMenuCollapsed === 'true') {
savedMainMenuWidth = 0;
} else {
savedMainMenuWidth = parseInt(window.OpenProject.guardedLocalStorage('openProject-mainMenuWidth'), 10);
}
if (window.innerWidth < 1012) {
// force hide on load for small desktops
document.querySelector('.can-hide-navigation')?.classList.add('hidden-navigation');
}
if (savedMainMenuWidth >= 0) {
document.documentElement.style.setProperty('--main-menu-width', savedMainMenuWidth + 'px');
}
wrapper.style.display = '';
// Wrapper for page-specific JS from deprecated inline functions
// no longer available with CSP.
<%= content_for :additional_js_dom_ready %>
<% end %>
<div class="op-wide-autocomplete-wrapper"></div>
<%= call_hook :view_layouts_base_body_bottom %>
<% end %>
</html>