Skip to content

Commit

Permalink
Merge pull request #15892 from opf/implementation/55177-replace-sidem…
Browse files Browse the repository at this point in the history
…enu-of-calendar-with-rails-component

[55177] Replace sidemenu of calendar with Rails component
  • Loading branch information
oliverguenther authored Jun 20, 2024
2 parents ee178b3 + 2c0e56d commit b4195a4
Show file tree
Hide file tree
Showing 26 changed files with 368 additions and 220 deletions.
13 changes: 13 additions & 0 deletions app/components/open_project/common/submenu_component.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<div class="op-sidebar--search">
<%= render Primer::Alpha::TextField.new(name: "search",
label: I18n.t("label_search"),
placeholder: I18n.t("label_search"),
leading_visual: { icon: :search },
visually_hide_label: true,
classes: "op-sidebar--search-input",
Expand Down Expand Up @@ -68,4 +69,16 @@
</div>
<% end %>
</div>

<% if @create_btn_options.present? %>
<div class="op-sidebar--footer">
<%= render Primer::Beta::Button.new(scheme: :primary,
tag: :a,
href: @create_btn_options[:href],
classes: "op-sidebar--footer-action") do |button|
button.with_leading_visual_icon(icon: "plus")
@create_btn_options[:text]
end %>
</div>
<% end %>
</div>
3 changes: 2 additions & 1 deletion app/components/open_project/common/submenu_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,11 @@
module OpenProject
module Common
class SubmenuComponent < ApplicationComponent
def initialize(sidebar_menu_items: nil, searchable: false)
def initialize(sidebar_menu_items: nil, searchable: false, create_btn_options: nil)
super()
@sidebar_menu_items = sidebar_menu_items
@searchable = searchable
@create_btn_options = create_btn_options
end

def render?
Expand Down
111 changes: 111 additions & 0 deletions app/menus/submenu.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# -- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2010-2023 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.
# ++
class Submenu
include Rails.application.routes.url_helpers
attr_reader :view_type, :project, :params

def initialize(view_type:, project: nil, params: nil)
@view_type = view_type
@project = project
@params = params
end

def menu_items
[
OpenProject::Menu::MenuGroup.new(header: I18n.t("js.label_starred_queries"), children: starred_queries),
OpenProject::Menu::MenuGroup.new(header: I18n.t("js.label_default_queries"), children: default_queries),
OpenProject::Menu::MenuGroup.new(header: I18n.t("js.label_global_queries"), children: global_queries),
OpenProject::Menu::MenuGroup.new(header: I18n.t("js.label_custom_queries"), children: custom_queries)
]
end

def starred_queries
base_query
.where("starred" => "t")
.pluck(:id, :name)
.map { |id, name| menu_item(query_params(id), name) }
end

def default_queries
raise NotImplementedError
end

def global_queries
base_query
.where("starred" => "f")
.where("public" => "t")
.pluck(:id, :name)
.map { |id, name| menu_item(query_params(id), name) }
end

def custom_queries
base_query
.where("starred" => "f")
.where("public" => "f")
.pluck(:id, :name)
.map { |id, name| menu_item(query_params(id), name) }
end

def base_query
base_query ||= Query
.visible(User.current)
.includes(:project)
.joins(:views)
.where("views.type" => view_type)

if project.present?
base_query.where("queries.project_id" => project.id)
else
base_query.where("queries.project_id" => nil)
end
end

def query_params(id)
{ query_id: id }
end

def menu_item(query_params, name)
OpenProject::Menu::MenuItem.new(title: name,
href: query_path(query_params),
selected: selected?(query_params))
end

def selected?(query_params)
query_params.each_key do |filter_key|
if params[filter_key] != query_params[filter_key].to_s
return false
end
end

true
end

def query_path(query_params)
raise NotImplementedError
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -147,10 +147,6 @@ import {
opTeamPlannerSidemenuSelector,
TeamPlannerSidemenuComponent,
} from 'core-app/features/team-planner/team-planner/sidemenu/team-planner-sidemenu.component';
import {
CalendarSidemenuComponent,
opCalendarSidemenuSelector,
} from 'core-app/features/calendar/sidemenu/calendar-sidemenu.component';
import {
OpModalOverlayComponent,
opModalOverlaySelector,
Expand Down Expand Up @@ -218,7 +214,6 @@ export const globalDynamicComponents:OptionalBootstrapDefinition[] = [
{ selector: wpOverviewGraphSelector, cls: WorkPackageOverviewGraphComponent },
{ selector: opViewSelectSelector, cls: ViewSelectComponent },
{ selector: opTeamPlannerSidemenuSelector, cls: TeamPlannerSidemenuComponent },
{ selector: opCalendarSidemenuSelector, cls: CalendarSidemenuComponent },
{ selector: triggerActionsEntryComponentSelector, cls: TriggerActionsEntryComponent, embeddable: true },
{ selector: editableQueryPropsSelector, cls: EditableQueryPropsComponent },
{ selector: backupSelector, cls: BackupComponent },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ $pill-padding-left: 8px
// Workaround to hide the actual text of the link and show our icons instead
color: var(--main-menu-bg-color)

.main-menu &
.main-menu &:not(.Button)
// reset main menu indents
padding: initial

Expand Down
9 changes: 9 additions & 0 deletions frontend/src/app/features/calendar/calendar.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@ import { WorkPackagesBaseComponent } from 'core-app/features/work-packages/routi
import { WorkPackagesCalendarComponent } from 'core-app/features/calendar/wp-calendar/wp-calendar.component';
import { WorkPackagesCalendarPageComponent } from 'core-app/features/calendar/wp-calendar-page/wp-calendar-page.component';

export const sidemenuId = 'calendar_sidemenu';
export const sideMenuOptions = {
sidemenuId,
hardReloadOnBaseRoute: true,
defaultQuery: 'new',
};

export const CALENDAR_ROUTES:Ng2StateDeclaration[] = [
{
name: 'calendar',
Expand All @@ -56,12 +63,14 @@ export const CALENDAR_ROUTES:Ng2StateDeclaration[] = [
redirectTo: 'calendar.page.show',
data: {
bodyClasses: 'router--calendar',
sideMenuOptions,
},
},
{
name: 'calendar.page.show',
data: {
baseRoute: 'calendar.page.show',
sideMenuOptions,
},
views: {
'content-left': { component: WorkPackagesCalendarComponent },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ import { OpenprojectFieldsModule } from 'core-app/shared/components/fields/openp
import { OpenprojectTimeEntriesModule } from 'core-app/shared/components/time_entries/openproject-time-entries.module';
import { WorkPackagesCalendarPageComponent } from 'core-app/features/calendar/wp-calendar-page/wp-calendar-page.component';
import { CALENDAR_ROUTES } from 'core-app/features/calendar/calendar.routes';
import { CalendarSidemenuComponent } from './sidemenu/calendar-sidemenu.component';
import { QueryGetIcalUrlModalComponent } from 'core-app/shared/components/modals/get-ical-url-modal/query-get-ical-url.modal';

@NgModule({
Expand Down Expand Up @@ -69,7 +68,6 @@ import { QueryGetIcalUrlModalComponent } from 'core-app/shared/components/modals
WorkPackagesCalendarPageComponent,
WorkPackagesCalendarComponent,
TimeEntryCalendarComponent,
CalendarSidemenuComponent,
QueryGetIcalUrlModalComponent,
],
exports: [
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -431,10 +431,21 @@ export class WorkPackagesListService {
}

private navigateToDefaultQuery(query:QueryResource):void {
const { hardReloadOnBaseRoute } = this.$state.$current.data as { hardReloadOnBaseRoute?:boolean };
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
const sideMenuOptions = this.$state.$current.data?.sideMenuOptions as { hardReloadOnBaseRoute?:boolean, defaultQuery?:string };
const hardReloadOnBaseRoute = sideMenuOptions?.hardReloadOnBaseRoute;

if (hardReloadOnBaseRoute) {
const url = new URL(window.location.href);
const defaultQuery = sideMenuOptions.defaultQuery;

// If there is a default query passed, we replace the hard coded ids with the default query
// e.g. calendars/:id, team_planner/:id, ...
// Otherwise, we will just delete the search params
if (defaultQuery) {
url.pathname = url.pathname.replace(/\d+$/, defaultQuery);
}

url.search = '';
window.location.href = url.href;
} else {
Expand All @@ -451,7 +462,8 @@ export class WorkPackagesListService {
}

private reloadSidemenu(selectedQueryId:string|null):void {
const menuIdentifier:string|undefined = this.$state.current.data.sidemenuId;
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-unsafe-assignment
const menuIdentifier:string|undefined = this.$state.current.data.sideMenuOptions?.sidemenuId;

if (menuIdentifier) {
const menu = (document.getElementById(menuIdentifier) as HTMLElement&TurboElement);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ import { makeSplitViewRoutes } from 'core-app/features/work-packages/routing/spl
export const menuItemClass = 'gantt-menu-item';

export const sidemenuId = 'gantt_menu';
export const sideMenuOptions = {
sidemenuId,
hardReloadOnBaseRoute: true,
};

export const WORK_PACKAGES_GANTT_ROUTES:Ng2StateDeclaration[] = [
{
Expand All @@ -49,8 +53,7 @@ export const WORK_PACKAGES_GANTT_ROUTES:Ng2StateDeclaration[] = [
data: {
bodyClasses: 'router--work-packages-base',
menuItem: menuItemClass,
sidemenuId,
hardReloadOnBaseRoute: true,
sideMenuOptions,
},
params: {
query_id: { type: 'query', dynamic: true },
Expand All @@ -68,8 +71,7 @@ export const WORK_PACKAGES_GANTT_ROUTES:Ng2StateDeclaration[] = [
data: {
// This has to be empty to avoid inheriting the parent bodyClasses
bodyClasses: '',
sidemenuId,
hardReloadOnBaseRoute: true,
sideMenuOptions,
},
},
{
Expand All @@ -83,8 +85,7 @@ export const WORK_PACKAGES_GANTT_ROUTES:Ng2StateDeclaration[] = [
bodyClasses: 'router--work-packages-partitioned-split-view',
menuItem: menuItemClass,
partition: '-left-only',
sidemenuId,
hardReloadOnBaseRoute: true,
sideMenuOptions,
},
},
...makeSplitViewRoutes(
Expand Down
Loading

0 comments on commit b4195a4

Please sign in to comment.