Compare commits

...

10 Commits

  1. 6
      Gemfile
  2. 11
      Gemfile.lock
  3. 62
      app/cells/hot_boards/row_cell.rb
  4. 22
      app/cells/hot_boards/table_cell.rb
  5. 35
      app/components/hot_message_component.html.erb
  6. 42
      app/components/hot_message_component.rb
  7. 76
      app/components/work_package_card_component.html.erb
  8. 30
      app/components/work_package_card_component.rb
  9. 8
      app/controllers/application_controller.rb
  10. 61
      app/controllers/hot_boards_controller.rb
  11. 56
      app/controllers/hot_messages_controller.rb
  12. 77
      app/controllers/notifications_controller.rb
  13. 2
      app/helpers/hot_boards_helper.rb
  14. 2
      app/helpers/mail_notification_helper.rb
  15. 58
      app/models/broadcast/hot_message.rb
  16. 24
      app/models/dumb_notification.rb
  17. 4
      app/models/hot_board.rb
  18. 7
      app/models/hot_item.rb
  19. 8
      app/models/hot_list.rb
  20. 33
      app/models/hot_message.rb
  21. 34
      app/models/queries/work_packages/filter/precedes_filter.rb
  22. 36
      app/views/hot_boards/_form.html.erb
  23. 1
      app/views/hot_boards/_item.html.erb
  24. 12
      app/views/hot_boards/_list.html.erb
  25. 42
      app/views/hot_boards/edit.html.erb
  26. 48
      app/views/hot_boards/index.html.erb
  27. 42
      app/views/hot_boards/new.html.erb
  28. 69
      app/views/hot_boards/show.html.erb
  29. 33
      app/views/hot_messages/_form.html.erb
  30. 33
      app/views/hot_messages/create.turbo_stream.erb
  31. 38
      app/views/hot_messages/index.html.erb
  32. 1
      app/views/layouts/_common_head.html.erb
  33. 2
      app/views/layouts/angular/angular.html.erb
  34. 49
      app/views/notifications/_form.html.erb
  35. 45
      app/views/notifications/_notification.html.erb
  36. 36
      app/views/notifications/_notification_bell.erb
  37. 32
      app/views/notifications/_notification_create.html.erb
  38. 3
      app/views/notifications/_notifications_empty.html.erb
  39. 4
      app/views/notifications/_unread_count.html.erb
  40. 4
      app/views/notifications/create.turbo_stream.erb
  41. 32
      app/views/notifications/destroy.turbo_stream.erb
  42. 44
      app/views/notifications/index.html.erb
  43. 42
      app/views/notifications/new.html.erb
  44. 3
      config/cable.yml
  45. 4
      config/initializers/secure_headers.rb
  46. 11
      config/routes.rb
  47. 10
      db/migrate/20220523112733_dumb_notification.rb
  48. 24
      db/migrate/20220530072855_create_hot_boards.rb
  49. 38
      db/migrate/20220607140620_create_hot_messages.rb
  50. 474
      frontend/package-lock.json
  51. 4
      frontend/package.json
  52. 2
      frontend/src/app/core/setup/global-dynamic-components.const.ts
  53. 4
      frontend/src/app/core/setup/globals/global-listeners.ts
  54. 15
      frontend/src/app/core/setup/globals/global-listeners/bootstrap-turbo-frames.ts
  55. 9
      frontend/src/app/features/calendar/wp-calendar/wp-calendar.component.ts
  56. 1
      frontend/src/app/features/in-app-notifications/bell/in-app-notification-bell.component.ts
  57. 237
      frontend/src/global_styles/content/_cards.sass
  58. 1
      frontend/src/global_styles/content/_index.sass
  59. 7
      frontend/src/global_styles/content/modules/_calendar.sass
  60. 1
      frontend/src/global_styles/layout/_index.sass
  61. 9
      frontend/src/global_styles/layout/_notifications.sass
  62. 3
      frontend/src/main.ts
  63. 8
      frontend/src/stimulus/bootstrap.ts
  64. 67
      frontend/src/stimulus/controllers/boards_controller.ts
  65. 27
      frontend/src/stimulus/controllers/hot_message_controller.ts
  66. 11
      frontend/src/stimulus/controllers/list_controller.ts
  67. 9
      frontend/src/stimulus/controllers/split_view_controller.ts
  68. 3
      frontend/src/tsconfig.app.json
  69. 2
      lib/redmine/menu_manager/top_menu_helper.rb
  70. 20
      modules/calendar/app/controllers/calendar/calendars_controller.rb
  71. 34
      modules/calendar/app/views/calendar/calendars/_overview.html.erb
  72. 34
      modules/calendar/app/views/calendar/calendars/_relations.html.erb
  73. 46
      modules/calendar/app/views/calendar/calendars/details.html.erb
  74. 3
      modules/calendar/app/views/calendar/calendars/show.html.erb
  75. 6
      modules/calendar/config/routes.rb
  76. 4
      modules/calendar/lib/open_project/calendar/engine.rb

@ -338,3 +338,9 @@ gemfiles.each do |file|
# don't use eval_gemfile(file) here as it will break dependabot!
send(:eval_gemfile, file) if File.readable?(file)
end
gem "turbo-rails", "~> 1.1"
gem "redis", "~> 4.6"
gem "view_component", "~> 2.55"

@ -811,6 +811,7 @@ GEM
recaptcha (5.10.0)
json
redcarpet (3.5.1)
redis (4.6.0)
regexp_parser (2.5.0)
representable (3.2.0)
declarative (< 0.1.0)
@ -959,6 +960,10 @@ GEM
timeout (0.3.0)
trailblazer-option (0.1.2)
ttfunk (1.7.0)
turbo-rails (1.1.1)
actionpack (>= 6.0.0)
activejob (>= 6.0.0)
railties (>= 6.0.0)
typed_dag (2.0.2)
rails (>= 5.0.4)
tzinfo (2.0.4)
@ -977,6 +982,9 @@ GEM
validate_url (1.0.15)
activemodel (>= 3.0.0)
public_suffix
view_component (2.55.0)
activesupport (>= 5.0.0, < 8.0)
method_source (~> 1.0)
warden (1.2.9)
rack (>= 2.0.9)
warden-basic_auth (0.2.1)
@ -1135,6 +1143,7 @@ DEPENDENCIES
rails-controller-testing (~> 1.0.2)
rails-i18n (~> 7.0.0)
rdoc (>= 2.4.2)
redis (~> 4.6)
request_store (~> 1.5.0)
responders (~> 3.0)
rest-client (~> 2.0)
@ -1174,9 +1183,11 @@ DEPENDENCIES
table_print (~> 1.5.6)
test-prof (~> 1.0.0)
timecop (~> 0.9.0)
turbo-rails (~> 1.1)
typed_dag (~> 2.0.2)
tzinfo-data (~> 1.2022.1)
validate_url
view_component (~> 2.55)
warden (~> 1.2)
warden-basic_auth (~> 0.2.1)
webdrivers (~> 5.0.0)

@ -0,0 +1,62 @@
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2022 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 HotBoards
class RowCell < ::RowCell
def board
model
end
def button_links
[edit_link, delete_link].compact
end
def title
link_to board.title,
hot_board_path(board)
end
private
def edit_link
link_to '',
{ controller: '/hot_boards', action: 'edit', id: board },
class: 'icon icon-edit',
title: t(:button_edit)
end
def delete_link
link_to '',
{ controller: '/hot_boards', action: 'destroy', id: board },
data: { confirm: t(:text_are_you_sure) },
method: :delete,
class: 'icon icon-delete',
title: t(:button_delete)
end
end
end

@ -0,0 +1,22 @@
module HotBoards
class TableCell < ::TableCell
columns :title
def sortable?
false
end
def headers
[
[:title, { caption: 'Title' }]
]
end
def inline_create_link
link_to new_hot_board_path,
class: 'wp-inline-create--add-link' do
op_icon('icon icon-add')
end
end
end
end

@ -0,0 +1,35 @@
<%#-- copyright
OpenProject is an open source project management software.
Copyright (C) 2012-2022 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.
++#%>
<div id="<%= dom_id(@hot_message) %>"
data-controller="hot-message"
data-hot-message-author-id-value="<%= @hot_message.author.id %>"
>
<%= tag.time(timestamp) %> -
<span data-hot-message-target="authorName"><%= @hot_message.author.name %></span>: <%= @hot_message.text %>
</div>

@ -0,0 +1,42 @@
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2022 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 HotMessageComponent < ViewComponent::Base
def initialize(hot_message:)
super()
@hot_message = hot_message
end
private
attr_reader :hot_message
def timestamp
hot_message.created_at.strftime("%Y-%m-%d at %H:%M:%S")
end
end

@ -0,0 +1,76 @@
<div
class="op-wp-single-card"
op-list-target="item"
data-qa-selector="op-wp-single-card"
data-id="<%= @work_package.id %>"
data-position="<%= @item.position %>"
>
<div class="op-wp-single-card--highlighting">
</div>
<div class="op-wp-single-card--card-actions">
<div class="op-wp-single-card--inline-buttons hidden-for-mobile"
data-qa-selector="op-wp-single-card--inline-buttons">
<button
type="button"
class="spot-link op-wp-single-card--details-button op-wp-single-card--card-action"
data-qa-selector="op-wp-single-card--details-button"
>
<i class="icon3 icon-info2"></i>
</button>
</div>
</div>
<div class="op-wp-single-card--content">
<span
class="op-wp-single-card--content-project-name"
>
<%= @work_package.project.name %>
</span>
<%= link_to "##{@work_package.id}",
work_package_path(@work_package.id),
class: 'op-wp-single-card--content-id'
%>
<span class="op-wp-single-card--content-subject-line">
<span
class="op-wp-single-card--content-type __hl_inline_type_<%= @work_package.type.id %>"
data-qa-selector="op-wp-single-card--content-type"
>
<%= @work_package.type.name %>
</span>
<span
class="op-wp-single-card--content-subject"
data-qa-selector="op-wp-single-card--content-subject"
>
<%= @work_package.subject %>
</span>
</span>
<div
class="op-wp-status-button op-wp-status-button_small"
data-qa-selector="op-wp-status-button"
>
<button
class="op-wp-status-button--button button __hl_background_status_<%= @work_package.status.id %>"
>
<span
class="op-wp-status-button--text button--text"
aria-hidden="true"
>
<%= @work_package.status.name %>
</span>
</button>
</div>
<%= avatar(@work_package.assigned_to) if @work_package.assigned_to_id %>
<span
class="op-wp-single-card--content-dates"
>
<%= formatted_dates %>
</span>
</div>
</div>

@ -0,0 +1,30 @@
# frozen_string_literal: true
class WorkPackageCardComponent < ViewComponent::Base
include ::Redmine::I18n
include ::AvatarHelper
def initialize(work_package:, item:)
@work_package = work_package
@item = item
end
def formatted_dates
start = @work_package.start_date
due = @work_package.due_date
if start && due
return "#{format_date(start)}#{format_date(due)}"
end
if !start && due
return "#{format_date(due)}"
end
if start && !due
return "#{format_date(start)}"
end
''
end
end

@ -131,6 +131,7 @@ class ApplicationController < ActionController::Base
end
before_action :user_setup,
:turbolinks_nonce,
:set_localization,
:tag_request,
:check_if_login_required,
@ -168,6 +169,13 @@ class ApplicationController < ActionController::Base
end
end
def turbolinks_nonce
# use the same csp nonce for turbolinks requests
if request.env['HTTP_X_TURBOLINKS_REFERRER'].present?
request.env[::SecureHeaders::NONCE_KEY] = request.env['HTTP_X_TURBOLINKS_NONCE']
end
end
def tag_request
::OpenProject::Appsignal.tag_request(controller: self, request:)
end

@ -0,0 +1,61 @@
class HotBoardsController < ApplicationController
add_flash_types :notice
before_action :find_board, only: %i[show edit update destroy delta]
def index
@boards = HotBoard.all
end
def new
@board = HotBoard.new
end
def show; end
def edit; end
def create
@board = HotBoard.new board_params
@board.save
respond_to do |format|
format.html { redirect_to hot_boards_path, notice: "Board was successfully created." }
end
end
def update
@board.update board_params
respond_to do |format|
format.html { redirect_to hot_boards_path, notice: "Board was successfully updated." }
end
end
def destroy
@board.destroy
respond_to do |format|
format.html { redirect_to hot_boards_path, notice: "Board was successfully destroyed." }
end
end
def delta
lists = @board.lists.pluck(:id)
params[:delta].each do |wp, pos|
HotItem.where(hot_list_id: lists, work_package_id: wp).update_all(position: pos)
end
end
private
def find_board
@board = HotBoard.find(params[:id])
end
def board_params
params
.require(:hot_board)
.permit(:title)
end
end

@ -0,0 +1,56 @@
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2022 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 HotMessagesController < ApplicationController
def index
@hot_messages = HotMessage.all
end
def create
@hot_message = HotMessage.new(hot_messages_params)
if @hot_message.save
Broadcast::HotMessage.append(hot_message: @hot_message)
end
respond_to do |format|
format.html { redirect_to action: :index, notice: 'HotMessage was successfully created.' }
format.turbo_stream
end
end
private
def hot_messages_params
params
.permit(:text)
.merge(
author: User.current
)
end
end

@ -0,0 +1,77 @@
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2022 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 NotificationsController < ApplicationController
layout 'no_menu'
before_action :find_notification, only: %i[destroy]
def index
@notifications = DumbNotification
.where(recipient: current_user)
end
def new
@notification = DumbNotification.new
end
def create
@notification = DumbNotification.new notification_params
@notification.save
respond_to do |format|
format.html { redirect_to action: :index, notice: "Notification was successfully create." }
format.turbo_stream
end
end
def destroy
@notification.destroy
respond_to do |format|
format.html { redirect_to action: :index, notice: "Notification was successfully destroyed." }
format.turbo_stream
end
end
private
def find_notification
@notification = DumbNotification.find(params[:id])
raise "Du Schlawiner!" if @notification.recipient != current_user
end
def notification_params
params
.require(:notification)
.permit(:message)
.merge(
author: User.active.order(Arel.sql('RANDOM()')).first,
recipient: current_user
)
end
end

@ -0,0 +1,2 @@
module HotBoardsHelper
end

@ -35,7 +35,7 @@ module MailNotificationHelper
.uniq
end
def notifications_path(id)
def notifications_details_path(id)
notifications_center_url(['details', id, 'activity'])
end

@ -0,0 +1,58 @@
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2022 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 Broadcast
class HotMessage
def self.append(hot_message:)
new(hot_message).append
end
def initialize(hot_message)
@hot_message = hot_message
end
def append
Turbo::StreamsChannel.broadcast_append_to(
:hot_messages_stream,
target: 'hot_messages',
html: rendered_component
)
end
private
attr_reader :hot_message
def rendered_component
ApplicationController.render(
HotMessageComponent.new(hot_message:),
layout: false
)
end
end
end

@ -0,0 +1,24 @@
class DumbNotification < ApplicationRecord
belongs_to :author, class_name: 'User'
belongs_to :recipient, class_name: 'User'
after_create_commit do
broadcast_append_to('notification_center', target: 'notifications_feed', partial: "notifications/notification", locals: { notification: self })
end
after_update_commit do
broadcast_replace_to('notification_center', target: self, partial: "notifications/notification", locals: { notification: self })
end
after_destroy_commit do
broadcast_remove_to('notification_center', target: self)
end
def self.recipient(user)
where(recipient: user)
end
def reason
Notification::REASONS.invert[(id || 0) % 9]
end
end

@ -0,0 +1,4 @@
class HotBoard < ApplicationRecord
has_many :lists, class_name: 'HotList'
validates_presence_of :title
end

@ -0,0 +1,7 @@
class HotItem < ApplicationRecord
belongs_to :hot_list
belongs_to :work_package
has_one :hot_board, through: :hot_list
validates_presence_of :hot_list, :work_package
end

@ -0,0 +1,8 @@
class HotList < ApplicationRecord
validates_presence_of :title
has_many :items, class_name: 'HotItem'
def work_packages
WorkPackage.where(id: items.order(:position).select(:work_package_id))
end
end

@ -0,0 +1,33 @@
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2022 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 HotMessage < ApplicationRecord
belongs_to :author, class_name: 'User'
validates :text, presence: true
end

@ -46,3 +46,37 @@ class Queries::WorkPackages::Filter::PrecedesFilter <
:to_id
end
end
{
"providers" => {
"saml" => {
"name" => "saml",
"display_name" => "GEI SSO",
"email" => "email",
"login" => "username",
"first_name" => "firstname",
"last_name" => "lastname",
"assertion_consumer_service_url" => "https://pm-test.intern.gei.de/auth/saml/callback",
"idp_cert_fingerprint" => "A6:05:F5:02:88:36:20:BA:76:C7:B0:F0:EE:DD:38:F7:EC:13:DE:38",
"idp_sso_target_url" => "https://idp-test.gei.de/idp/profile/SAML2/Redirect/SSO",
"idp_slo_target_url" => "https://idp-test.gei.de/idp/profile/SAML2/Redirect/SLO",
"certificate" => '-----BEGIN\nCERTIFICATE-----\nMIIEETCCAnmgAwIBAgIUa69lX7LqrAGmli9dnraSuBk4YxAwDQYJKoZIhvcNAQEL\nBQAwIDEeMBwGA1UEAxMVcG0tdGVzdC5pbnRlcm4uZ2VpLmRlMB4XD
TIyMDUxODE0\nMDMwNloXDTMyMDUxNTE0MDMwNlowIDEeMBwGA1UEAxMVcG0tdGVzdC5pbnRlcm4u\nZ2VpLmRlMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEA0EpMgCk5FSqg\n2sOS5iU2v6OGU1hbupclj293HkN4UzISbXvBaYY/MFGDU
BIDLHwXlRGXjWytPgwh\ngDma8W9foFc0Wa/JpH+DPfkj4c3ltK2WqEoMuSy7Zf/LTQW+xNqb6wLbDW102Buv\nr6dQBfMgYfr4HSm4ZxP3VIytf2IEqPzCJF4Tzwn8FC9SkT0UU6zGak89qSKDFdiU\nDPehTDbaOExElJicXGR4lxCYiZ/TLpChdUArG
RYf+5Y73NgvrzO0I5iGmIvmBhAY\nqchfoE+K0I4z+xFhjULIEHnwZfAA1ovCkfGZLJUZVf5achDqLswMN3HBwiGk/T+U\nKyPtiasgCzkjSI/+smwdgQ0cVbqB3cHRpCDwE7XNx8swO7oFWWLVGEZNDwPtaNY5\nGY6p+8foD5CrF6t4mCZdzhZ6exoi1
uoP5+IUuctwLnyLAaOeCGX/fLrUCd6D/IGB\nnOdVMerHXUpxJFESREVQj0RbWtNDxMTjsGLLPn6PCh0zbnQ/W6BjAgMBAAGjQzBB\nMCAGA1UdEQQZMBeCFXBtLXRlc3QuaW50ZXJuLmdlaS5kZTAdBgNVHQ4EFgQUWTeT\n1KNagMAf5vstHkNac2XlF
XAwDQYJKoZIhvcNAQELBQADggGBAAZ/wL3Q0LK5v/El\njGySQPf7UYFv0a3jSPFELGrrM+DrhdVCmpvEq/G+5+mmPa392/maBj906AHLWC/n\nEqSi9CG4Y2EDkFHXKbqg9esZSgXK5A9knvsj0t3BHRZEev00Ij9h2z7cIWmNDK3J\nyQwuzUry5JA69
8zXt9Oib+90bpp3QyAYg7bnN830RwdCA7Hcp6wA5KxOCi1LNzzs\nAuME+FN7Co+sIqXp5a39oHJchAz7ryLFuSIH19ZStdJzc5ujiXpmbPd+oW5Ccwp5\n9jUqpbMmh1E05odcXIJL1OfRsyd11YT3MG/ERA9QtVesRA5kiQjWPPHi8OeUp/Cn\n0/XCv
0qt5IZkQOt+7c0mOlN1GeLGUB5mOt28A5UUKOee+kusiB6h3ir4DF3s4DL8\nZJpm8UChwDkMzwcA8TKBCsoFuu1tloCJ7nh1ulLxmn5AH4nZDxIc+WDG1Gqb4OW7\nGfinIWEkqXPzuv2h1Lq1j0Ll9Z7qJZqFeoDWYb3SVDrTUUrvag==\n-----END\
nCERTIFICATE-----',
"private_key" => 'test',
"security" => {
"authn_requests_signed" => "true",
"want_assertions_signed" => "true",
"embed_sign" => "true",
"signature_method" => ' http : // www.w3.org / 2001 / 04 / xmldsig - more #rsa-sha256',
"digest_method" => 'http://www.w3.org/2001/04/xmlenc#sha256',
}
}
}
}

@ -0,0 +1,36 @@
<%#-- copyright
OpenProject is an open source project management software.
Copyright (C) 2012-2022 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.
++#%>
<%= labelled_tabular_form_for @board,
url: hot_boards_path do |f| %>
<div class='form--field -required'>
<%= f.text_field :title, autofocus: true, required: true, container_class: '-middle' %>
</div>
<%= styled_button_tag t(:button_save), class: '-highlight -with-icon icon-checkmark' %>
<% end %>

@ -0,0 +1 @@
<%= render WorkPackageCardComponent.new(work_package: item.work_package, item: item) %>

@ -0,0 +1,12 @@
<section class="op-hot-list">
<h2><%= list.title %></h2>
<div class="op-board-list--button-container">
<button class="op-board-list--add-button op-board-list--card-dropdown-button button"
title="Add card">
<i class="icon-small icon-add"></i>
</button>
</div>
<div class="op-hot-list--container" data-controller="list">
<%= render partial: 'item', collection: list.items.includes(:work_package), as: :item %>
</div>
</section>

@ -0,0 +1,42 @@
<%#-- copyright
OpenProject is an open source project management software.
Copyright (C) 2012-2022 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.
++#%>
<main class="container">
<%= link_to sanitize("&larr; Back to list"), hot_boards_path %>
<div class="header">
<h1>New board</h1>
</div>
<%= labelled_tabular_form_for @board do |f| %>
<%= render partial: 'form', locals: { f: f }%>
<% end %>
</main>

@ -0,0 +1,48 @@
<%#-- copyright
OpenProject is an open source project management software.
Copyright (C) 2012-2022 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.
++#%>
<%= turbo_stream_from 'hot_boards' %>
<%= toolbar title: 'Boards' do %>
<li class="toolbar-item">
<%=
link_to(
{ action: :new },
class: 'button -alt-highlight',
) do
%>
<%= op_icon("button--icon icon-add") %>
<span class="button--text">Board</span>
<% end %>
</li>
<% end %>
<%= rails_cell HotBoards::TableCell, @boards %>

@ -0,0 +1,42 @@
<%#-- copyright
OpenProject is an open source project management software.
Copyright (C) 2012-2022 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.
++#%>
<main class="container">
<%= link_to sanitize("&larr; Back to list"), hot_boards_path %>
<div class="header">
<h1>New board</h1>
</div>
<%= labelled_tabular_form_for @board do |f| %>
<%= render partial: 'form', locals: { f: f }%>
<% end %>
</main>

@ -0,0 +1,69 @@
<%#-- copyright
OpenProject is an open source project management software.
Copyright (C) 2012-2022 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.
++#%>
<main class="container">
<%= link_to sanitize("&larr; Back to list"), hot_boards_path %>
<%= toolbar title: @board.title do %>
<li class="toolbar-item">
<%=
link_to(
{ action: :edit },
class: 'button',
) do
%>
<%= op_icon("button--icon icon-edit") %>
<span class="button--text">Edit</span>
<% end %>
</li>
<li class="toolbar-item">
<%=
link_to(
{ action: :destroy },
method: :delete,
data: { confirm: I18n.t(:text_are_you_sure) },
class: 'button -danger',
) do
%>
<%= op_icon("button--icon icon-delete") %>
<span class="button--text">Delete</span>
<% end %>
</li>
<% end %>
<%= turbo_stream_from "board_content_#{@board.id}" %>
<% if @board.lists.empty? %>
<%= no_results_box %>
<% end %>
<div class="op-hot-board" data-controller="boards" data-board-id="<%= @board.id %>">
<%= render partial: 'list', collection: @board.lists, as: :list %>
</div>
</main>

@ -0,0 +1,33 @@
<%#-- copyright
OpenProject is an open source project management software.
Copyright (C) 2012-2022 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_with url: hot_messages_path, id: 'new_hot_message_form' do |f| %>
<%= f.label :text, 'Message:' %>
<%= f.text_field :text, placeholder: 'Speak here...' %>
<%= f.submit 'Post message' %>
<% end %>

@ -0,0 +1,33 @@
<%#-- copyright
OpenProject is an open source project management software.
Copyright (C) 2012-2022 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.
++#%>
<%= turbo_stream.replace "new_hot_message_form", partial: "form" %>
<%= turbo_stream.append "hot_messages" do %>
<%= render HotMessageComponent.new(hot_message: @hot_message) %>
<% end %>

@ -0,0 +1,38 @@
<%#-- copyright
OpenProject is an open source project management software.
Copyright (C) 2012-2022 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.
++#%>
<div>
<h3>Messages - rendered at <%= Time.zone.now %></h3>
<%= turbo_stream_from :hot_messages_stream %>
<div id="hot_messages">
<%= render HotMessageComponent.with_collection(@hot_messages) %>
</div>
<%= render 'form' %>
</div>

@ -23,6 +23,7 @@
<% if Setting.boards_demo_data_available %><meta name="boards_demo_data_available" content="true"/><% end %>
<% if Setting.demo_view_of_type_team_planner_seeded %><meta name="demo_view_of_type_team_planner_seeded" content="true"/><% end %>
<%= csrf_meta_tags %>
<meta name="csp-nonce" content="<%= content_security_policy_script_nonce %>" />
<%= initializer_meta_tag %>
<!-- global meta hooks before any scripts are loaded-->

@ -37,7 +37,7 @@ See COPYRIGHT and LICENSE files for more details.
<openproject-base></openproject-base>
<%# Allow projection pages to show rails rendered content after initialization %>
<div id="projected-content" hidden>
<div id="projected-content">
<%= yield %>
</div>
<% end -%>

@ -0,0 +1,49 @@
<%#-- copyright
OpenProject is an open source project management software.
Copyright (C) 2012-2022 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.
++#%>
<%= labelled_tabular_form_for @notification,
as: :notification,
url: notifications_path do |f| %>
<div class='form--field -required'>
<%= f.text_field :message, autofocus: true, required: true, container_class: '-middle' %>
</div>
<div class="form--field-container">
<div class="form--select-container -middle">
<% users = User.active.order(Arel.sql('RANDOM()')).take(50) %>
<% select_options = users.map { |v| { label: v.name, value: v.id } } %>
<%= render partial: 'augmented/autocomplete_select_decoration',
locals: { input_name: 'foobar',
input_id: "foobar",
select_options: select_options,
multiple: true } %>
</div>
</div>
<%= styled_button_tag t(:button_save), class: '-highlight -with-icon icon-checkmark' %>
<% end %>

@ -0,0 +1,45 @@
<%#-- copyright
OpenProject is an open source project management software.
Copyright (C) 2012-2022 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.
++#%>
<%= turbo_frame_tag notification do %>
<div class="op-dumb-notification">
<span class="op-dumb-notification--author">
<%= avatar notification.author %>
</span>
<span class="op-dumb-notification--message">
<%= notification.message %>
</span>
<div class="op-dumb-notification--actions">
<%= button_to "Delete",
notification_path(notification),
method: :delete,
class: "button" %>
</div>
</div>
<% end %>

@ -0,0 +1,36 @@
<%#-- copyright
OpenProject is an open source project management software.
Copyright (C) 2012-2022 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.
++#%>
<a class="op-ian-bell op-app-menu--item-action"
href="/notifications">
<%= op_icon 'icon-bell' %>
<%= turbo_frame_tag 'notifications_bell_count' do %>
<%= render partial: 'notifications/unread_count' %>
<% end %>
</a>

@ -0,0 +1,32 @@
<%#-- copyright
OpenProject is an open source project management software.
Copyright (C) 2012-2022 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.
++#%>
<%= link_to 'Add notification',
new_notification_path,
class: 'button -highlight' %>

@ -0,0 +1,3 @@
<% if DumbNotification.recipient(current_user).empty? %>
<%= no_results_box %>
<% end %>

@ -0,0 +1,4 @@
<% count = DumbNotification.recipient(current_user).count %>
<% if count > 0 %>
<span class="op-ian-bell--indicator"><%= count %></span>
<% end %>

@ -0,0 +1,4 @@
<%= turbo_stream.prepend(:notifications_feed, partial: 'notification', locals: { notification: @notification }) %>
<%= turbo_stream.update(:notifications_bell_count, partial: 'unread_count') %>
<%= turbo_stream.update(:notification_create, partial: 'notification_create') %>
<%= turbo_stream.remove(:notifications_empty) %>

@ -0,0 +1,32 @@
<%#-- copyright
OpenProject is an open source project management software.
Copyright (C) 2012-2022 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.
++#%>
<%= turbo_stream.remove(@notification) %>
<%= turbo_stream.update(:notifications_bell_count, partial: 'unread_count') %>
<%= turbo_stream.update(:notifications_empty, partial: 'notifications_empty') %>

@ -0,0 +1,44 @@
<%#-- copyright
OpenProject is an open source project management software.
Copyright (C) 2012-2022 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.
++#%>
<%= turbo_stream_from 'notification_center' %>
<h1>Notifications</h1>
<%= turbo_frame_tag 'notifications_empty' do %>
<%= render partial: 'notifications_empty' %>
<% end %>
<%= turbo_frame_tag 'notifications_feed' do %>
<% render partial: 'notification', collection: @notifications %>
<% end %>
<div class="form--section">
<%= turbo_frame_tag 'notification_create' do %>
<%= render partial: 'notification_create' %>
<% end %>
</div>

@ -0,0 +1,42 @@
<%#-- copyright
OpenProject is an open source project management software.
Copyright (C) 2012-2022 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.
++#%>
<main class="container">
<%= link_to sanitize("&larr; Back to notifications"), notifications_path %>
<div class="header">
<h1>New notification</h1>
</div>
<%= turbo_frame_tag 'notification_create' do %>
<%= render partial: 'form', notification: @notification %>
<% end %>
</main>

@ -1,5 +1,6 @@
development:
adapter: async
adapter: redis
url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %>
test:
adapter: test

@ -1,6 +1,8 @@
# rubocop:disable Lint/PercentStringArray
Rails.application.config.after_initialize do
SecureHeaders::Configuration.default do |config|
config.csp = SecureHeaders::OPT_OUT
config.cookies = {
secure: true,
httponly: true
@ -47,6 +49,8 @@ Rails.application.config.after_initialize do
script_src += %w('unsafe-eval')
end
script_src += %w('unsafe-inline')
config.csp = {
preserve_schemes: true,

@ -575,9 +575,16 @@ OpenProject::Application.routes.draw do
root to: 'account#login'
scope :notifications do
get '(/*state)', to: 'angular#notifications_layout', as: :notifications_center
resources :notifications, only: %i[index destroy new create]
resources :hot_boards do
member do
post :delta
end
end
resources :hot_messages
# scope :notifications do
# get '(/*state)', to: 'angular#notifications_layout', as: :notifications_center
# end
# OAuthClient needs a "callback" URL that Nextcloud calls with a "code" (see OAuth2 RFC)
scope 'oauth_clients/:oauth_client_id' do

@ -0,0 +1,10 @@
class DumbNotification < ActiveRecord::Migration[7.0]
def change
create_table :dumb_notifications do |t|
t.belongs_to :author, class_name: 'User'
t.belongs_to :recipient, class_name: 'User'
t.text :message
t.timestamps
end
end
end

@ -0,0 +1,24 @@
class CreateHotBoards < ActiveRecord::Migration[7.0]
def change
create_table :hot_boards do |t|
t.string :title
t.timestamps
end
create_table :hot_lists do |t|
t.belongs_to :hot_board
t.string :title
t.timestamps
end
create_table :hot_items do |t|
t.belongs_to :hot_list
t.belongs_to :work_package
t.integer :position
t.timestamps
end
end
end

@ -0,0 +1,38 @@
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2022 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 CreateHotMessages < ActiveRecord::Migration[7.0]
def change
create_table :hot_messages do |t|
t.belongs_to :author, class_name: 'User', null: false
t.text :text
t.timestamps
end
end
end

File diff suppressed because it is too large Load Diff

@ -81,6 +81,10 @@
"@fullcalendar/resource-common": "^5.10.1",
"@fullcalendar/resource-timeline": "5.10.1",
"@fullcalendar/timegrid": "5.10.1",
"@hotwired/stimulus": "^3.0.1",
"@hotwired/stimulus-webpack-helpers": "^1.0.1",
"@hotwired/turbo": "^7.1.0",
"@hotwired/turbo-rails": "^7.1.2",
"@kolkov/ngx-gallery": "^1.0.11",
"@ng-select/ng-option-highlight": "0.0.5",
"@ng-select/ng-select": "^4.0.4",

@ -224,7 +224,7 @@ export const globalDynamicComponents:OptionalBootstrapDefinition[] = [
{ selector: hideSectionLinkSelector, cls: HideSectionLinkComponent },
{ selector: showSectionDropdownSelector, cls: ShowSectionDropdownComponent },
{ selector: addSectionDropdownSelector, cls: AddSectionDropdownComponent },
{ selector: autocompleteSelectDecorationSelector, cls: AutocompleteSelectDecorationComponent },
{ selector: autocompleteSelectDecorationSelector, cls: AutocompleteSelectDecorationComponent, embeddable: true },
{ selector: contentTabsSelector, cls: ContentTabsComponent },
{ selector: globalSearchTitleSelector, cls: GlobalSearchTitleComponent },
{ selector: copyToClipboardSelector, cls: CopyToClipboardDirective },

@ -40,6 +40,7 @@ import { listenToSettingChanges } from 'core-app/core/setup/globals/global-liste
import { detectOnboardingTour } from 'core-app/core/setup/globals/onboarding/onboarding_tour_trigger';
import { augmentedDatePicker } from './global-listeners/augmented-date-picker';
import { performAnchorHijacking } from './global-listeners/link-hijacking';
import { bootstrapTurboFrames } from 'core-app/core/setup/globals/global-listeners/bootstrap-turbo-frames';
/**
* A set of listeners that are relevant on every page to set sensible defaults
@ -148,5 +149,8 @@ import { performAnchorHijacking } from './global-listeners/link-hijacking';
// Bootstrap legacy app code
setupServerResponse();
// Bootstrap on turbo frames
bootstrapTurboFrames();
});
}(jQuery));

@ -0,0 +1,15 @@
import { FetchRequestOptions } from '@hotwired/turbo/dist/types/http/fetch_request';
export function bootstrapTurboFrames():void {
document.addEventListener('turbo:frame-render', async (event) => {
const context = await window.OpenProject.getPluginContext();
context.bootstrap(event.target as HTMLElement);
});
document.addEventListener('turbo:before-fetch-request', (event:CustomEvent) => {
const { fetchOptions } = event.detail as { fetchOptions:FetchRequestOptions };
const nonceEl = document.querySelector('meta[name="csp-nonce"]') as HTMLMetaElement;
fetchOptions.headers['X-Turbolinks-Referrer'] = window.location.href;
fetchOptions.headers['X-Turbolinks-Nonce'] = nonceEl.content;
});
}

@ -44,6 +44,7 @@ import {
OpWorkPackagesCalendarService,
} from 'core-app/features/calendar/op-work-packages-calendar.service';
import { OpCalendarService } from 'core-app/features/calendar/op-calendar.service';
import * as Turbo from '@hotwired/turbo';
@Component({
templateUrl: './wp-calendar.template.html',
@ -162,7 +163,13 @@ export class WorkPackagesCalendarComponent extends UntilDestroyedMixin implement
// Currently the calendar widget is shown on multiple pages,
// but only the calendar module itself is a partitioned query space which can deal with a split screen request
if (this.$state.includes('calendar')) {
this.workPackagesCalendar.openSplitView(workPackageId);
const url = new URL(window.location.href)
url.pathname += `/split/${workPackageId}`;
const frame = document.querySelector('turbo-frame#split_view') as any;
frame.src = url.toString();
frame.reload();
//Turbo.visit(url.toString(), { action: 'advance' });
// this.workPackagesCalendar.openSplitView(workPackageId);
} else {
void this.$state.go(
'work-packages.show',

@ -1,6 +1,7 @@
import {
ChangeDetectionStrategy,
Component,
ViewEncapsulation,
} from '@angular/core';
import {
combineLatest,

@ -0,0 +1,237 @@
.op-wp-single-card
display: flex
user-select: none
// Leave space for the shadow to be displayed
width: calc(100% - 2px)
max-width: 300px
border: 1px solid var(--widget-box-block-border-color)
border-radius: 2px
padding: 10px
position: relative
box-shadow: 1px 1px 3px 0px lightgrey
background: var(--body-background)
font-size: var(--card-font-size)
&:hover
.op-wp-single-card--inline-buttons
opacity: 1
z-index: 2
background-image: linear-gradient(to left, rgba($spot-color-basic-white, 1), rgba($spot-color-basic-white, 0))
&_new
padding-right: 25px
&_ghosted
opacity: 0.5
&_selected
background-color: $spot-color-main-light
.op-icon--wrapper
background: $spot-color-main-light
&:hover
.op-wp-single-card--inline-buttons
background-image: linear-gradient(to left, rgba($spot-color-main-light, 1), rgba($spot-color-main-light, 0))
&_closed:not(&_selected)
background-color: $spot-color-basic-gray-6
.op-icon--wrapper
background: $spot-color-basic-gray-6
&:hover
.op-wp-single-card--inline-buttons
background-image: linear-gradient(to left, rgba($spot-color-basic-gray-6, 1), rgba($spot-color-basic-gray-6, 0))
&_horizontal
height: 100%
&_vertical
margin-top: 10px
// Take care that the shadow of the last element is still visible
&:last-of-type
margin-bottom: 5px
&_inline &--content
grid-template-columns: max-content max-content auto auto 1fr
grid-template-rows: auto max-content
grid-template-areas: "status id project project project" "subject subject subject subject subject"
&-assignee
display: none
&-subject-line
display: flex
&-subject
flex-grow: 1
@include text-shortener
// Style shadow element while dragging
wp-single-card:host.gu-transit &
@include modifying--placeholder
&--content
&:not(.-new)
display: grid
grid-template-columns: max-content max-content auto auto 1fr
grid-template-rows: auto max-content max-content 1fr
grid-row-gap: 5px
grid-column-gap: 5px
grid-template-areas: "status id project project project" "subject subject subject subject subject" "image image image image image" "avatar avatar avatar dates dates"
overflow: hidden
flex-grow: 1
font-size: 14px
line-height: 16px
&-project-name
grid-area: project
font-style: italic
color: $spot-color-basic-gray-3
font-size: 12px
@include text-shortener
&-type
grid-area: type
margin-right: 4px
&-subject-line
grid-area: subject
@include text-shortener(false)
&-assignee
grid-area: avatar
max-width: 140px
color: $spot-color-basic-gray-3
font-size: 12px
&-id
grid-area: id
color: $spot-color-basic-gray-3
font-size: 12px
&-status
grid-area: status
margin-right: 5px
max-width: 92px
overflow: hidden
&-cover-image
grid-area: image
max-height: 350px
@media screen and (max-width: 679px)
max-height: 250px
&-dates
grid-area: dates
place-self: center end
white-space: nowrap
color: $spot-color-basic-gray-3
font-size: 12px
&-inline-date
font-size: 12px
color: $spot-color-basic-gray-3
margin: 0 8px
white-space: nowrap
&--highlighting
width: 100%
height: 2px
position: absolute
top: 0
left: 0
border-radius: 2px 2px 0 0
&--card-actions
display: flex
position: absolute
top: 9px
right: 0
&--card-action
z-index: 2
&_closed
color: $spot-color-basic-gray-2
.op-wp-single-card_selected &
background-color: $spot-color-main-light
&--inline-buttons
opacity: 0
padding-left: 40px
padding-right: 4px
.op-icon--wrapper:not(&_selected)
background: $spot-color-basic-white
&.-show
opacity: 1
.op-wp-single-card_selected &
background-color: $spot-color-main-light
&--inline-cancel-button
color: var(--warn)
@media only screen and (max-width: 679px)
&_shrink
border: none
box-shadow: none
padding: 15px
.op-wp-status-button
&--button
@include text-shortener(false)
padding: 5px
margin-bottom: 0
background-color: var(--status-selector-bg-color)
border: none
color: white
max-width: 100%
display: flex
&--text
@include text-shortener
&_small &--button
line-height: 16px
font-size: 12px
height: 16px
padding: 0px 5px
margin-right: 0
.op-hot-board
display: flex
.op-hot-list
height: 100%
width: 300px
padding: 0 15px
display: flex
flex-direction: column
&--container
min-height: 500px
.op-wp-single-card
margin-bottom: 1rem
.op-board-list--button-container
background-color: var(--body-background)
position: sticky
top: 0
z-index: 1
display: flex
align-items: center
.op-board-list--add-button
background-color: var(--body-background)
width: calc(100% - 2px)
margin: 0
margin-bottom: 15px
box-shadow: 1px 1px 3px 0px lightgrey

@ -82,3 +82,4 @@
@import modules/index
@import user-content/index
@import bim/index
@import cards

@ -1,3 +1,10 @@
.router--calendar
#content
height: 100%
display: flex
openproject-base
flex: 1
#projected-content
max-width: 300px

@ -35,6 +35,7 @@
@import breadcrumb
@import main_menu
@import main_menu_mobile
@import notifications
@import searchable_menu
@import colors
@import drop_down

@ -0,0 +1,9 @@
.op-ian-bell
position: relative
&--indicator
@include indicator-bubble
position: absolute
top: 10px
right: 3px
background: darkred

@ -7,6 +7,8 @@ import { whenDebugging } from 'core-app/shared/helpers/debug_output';
import { enableReactiveStatesLogging } from 'reactivestates';
import { initializeLocale } from 'core-app/core/setup/init-locale';
import { environment } from './environments/environment';
import '@hotwired/turbo';
import '@hotwired/turbo-rails';
(window as any).global = window;
@ -26,6 +28,7 @@ window.ErrorReporter = new SentryReporter();
require('core-app/core/setup/init-vendors');
require('core-app/core/setup/init-globals');
require('stimulus/bootstrap');
if (environment.production) {
enableProdMode();

@ -0,0 +1,8 @@
import { Application } from '@hotwired/stimulus';
import { definitionsFromContext } from '@hotwired/stimulus-webpack-helpers';
const stimulus = Application.start(document.documentElement);
// eslint-disable-next-line @typescript-eslint/no-explicit-any,@typescript-eslint/no-unsafe-member-access
(window as any).Stimulus = stimulus;
const context = require.context('./controllers', true, /\.ts$/);
stimulus.load(definitionsFromContext(context));

@ -0,0 +1,67 @@
import { Controller } from '@hotwired/stimulus';
import {
HttpClient,
HttpHeaders,
} from '@angular/common/http';
import { buildDelta } from 'core-app/shared/helpers/drag-and-drop/reorder-delta-builder';
export default class extends Controller {
http:HttpClient;
initialize() {
window
.OpenProject
.getPluginContext()
.then((context) => {
this.http = context.injector.get(HttpClient);
});
}
connect() {
// Make custom fields draggable
// eslint-disable-next-line no-undef
const drake = dragula([this.element], {
isContainer: (el:HTMLElement) => el.classList.contains('op-hot-list--container'),
moves: function (el, source, handle, sibling) {
return !!handle?.closest('.op-wp-single-card');
},
accepts: (el:HTMLElement, container:HTMLElement) => container.classList.contains('op-hot-list--container'),
invalid: () => false,
direction: 'vertical',
copy: false,
copySortSource: false,
revertOnSpill: true,
removeOnSpill: false,
ignoreInputTextSelection: true,
});
drake.on('drop', (el:HTMLElement, target:HTMLElement, source:HTMLElement, sibling:HTMLElement) => {
const headers = new HttpHeaders({ 'Content-Type': 'application/json' });
const children = Array.from(el.parentElement?.children || []);
const order:string[] = children.map((c:HTMLElement) => c.dataset.id as string);
const positions:{[wpId:string]:number} = {};
const index = children.findIndex(c => el === c);
children.forEach((c:HTMLElement) => {
if (c !== el) {
positions[c.dataset.id as string] = parseInt(c.dataset.position as string, 2);
}
});
const wpId = el.dataset.id as string;
const delta = buildDelta(order, positions, wpId, index, null);
this
.http
.post(
`/hot_boards/${this.boardId}/delta`,
{ delta },
{ withCredentials: true, headers }
)
.subscribe();
});
}
get boardId():string {
return (this.element as HTMLElement).dataset.boardId as string;
}
}

@ -0,0 +1,27 @@
import { Controller } from '@hotwired/stimulus';
export default class extends Controller {
static targets = ['authorName'];
static values = {
authorId: Number,
};
declare authorIdValue:number;
declare authorNameTarget:Element;
connect():void {
if (this.authorIdValue === this.currentUserId) {
this.authorNameTarget.innerHTML = 'You';
}
}
get currentUserId():number | undefined {
const element = document.head.querySelector('meta[name=\'current_user\']');
if (!element) {
return undefined;
}
return Number(element.getAttribute('data-id'));
}
}

@ -0,0 +1,11 @@
import { Controller } from '@hotwired/stimulus';
export default class extends Controller {
static targets = ['items'];
itemTargets:HTMLElement[];
initialize() {
}
}

@ -0,0 +1,9 @@
import { Controller } from '@hotwired/stimulus';
import { OpenProjectPluginContext } from 'core-app/features/plugins/plugin-context';
export default class extends Controller {
async connect():Promise<void> {
const context = await window.OpenProject.pluginContext.valuesPromise() as OpenProjectPluginContext;
context.bootstrap(this.element as unknown as HTMLElement);
}
}

@ -9,9 +9,10 @@
"main.ts",
"polyfills.ts",
"app/core/setup/init-globals.ts",
"app/core/setup/init-vendors.ts"
"app/core/setup/init-vendors.ts",
],
"include": [
"stimulus/**/*.ts",
"src/**/*.ts",
"**/*.d.ts",
"app/core/augmenting/dynamic-scripts/*.ts"

@ -54,7 +54,7 @@ module Redmine::MenuManager::TopMenuHelper
return ''.html_safe unless User.current.logged?
content_tag('li', class: 'op-app-menu--item') do
tag('op-in-app-notification-bell')
render partial: 'notifications/notification_bell'
end
end

@ -39,7 +39,21 @@ module ::Calendar
end
def show
render layout: 'angular/angular'
respond_to do |format|
format.html { render layout: 'angular/angular' }
end
end
def details
render layout: 'angular/angular', locals: { tab: :overview }
end
def overview
render template: 'calendar/calendars/details', layout: 'angular/angular', locals: { tab: :overview }
end
def relations
render template: 'calendar/calendars/details', layout: 'angular/angular', locals: { tab: :relations }
end
def destroy
@ -65,8 +79,8 @@ module ::Calendar
def find_calendar
@view = Query
.visible(current_user)
.find(params[:id])
.visible(current_user)
.find(params[:id])
rescue ActiveRecord::RecordNotFound
render_404
end

@ -0,0 +1,34 @@
<%#-- copyright
OpenProject is an open source project management software.
Copyright (C) 2012-2022 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.
++#%>
<div id="split_view_tab" data-turbo-action="replace" data-controller="split-view">
Overview!
<macro class="macro--wp-quickinfo" data-id="1899"></macro>
</div>

@ -0,0 +1,34 @@
<%#-- copyright
OpenProject is an open source project management software.
Copyright (C) 2012-2022 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.
++#%>
<div id="split_view_tab" data-turbo-action="replace" data-controller="split-view">
Relations!
<macro class="macro--wp-quickinfo" data-id="4742"></macro>
</div>

@ -0,0 +1,46 @@
<%#-- copyright
OpenProject is an open source project management software.
Copyright (C) 2012-2022 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.
++#%>
<%= turbo_frame_tag 'split_view', data: { 'turbo-action': 'advance' } do %>
<div class="cool-split-view">
<nav>
<%= link_to 'Overview',
{ action: :overview },
class: 'button' %>
<%= link_to 'Relations',
{ action: :relations },
class: 'button' %>
</nav>
</div>
<%= render partial: tab.to_s %>
<%= link_to 'Close',
{ action: :show },
class: 'button' %>
<% end %>

@ -28,3 +28,6 @@ See COPYRIGHT and LICENSE files for more details.
++#%>
<% html_title(t(:label_calendar_plural)) -%>
<%= turbo_frame_tag 'split_view', data: { 'turbo-action': 'advance' } do %>
<% end %>

@ -4,8 +4,12 @@ OpenProject::Application.routes.draw do
controller: 'calendar/calendars',
only: %i[index destroy],
as: :calendars do
get '/' => 'calendar/calendars#show', on: :member, as: ''
get '/new' => 'calendar/calendars#show', on: :collection, as: 'new'
get '(/*state)' => 'calendar/calendars#show', on: :member, as: ''
get '/split/:wp_id/' => 'calendar/calendars#details', on: :member, as: 'details'
get '/split/:wp_id/overview' => 'calendar/calendars#overview', on: :member
get '/split/:wp_id/relations' => 'calendar/calendars#relations', on: :member
end
end
end

@ -29,11 +29,11 @@ module OpenProject::Calendar
name: 'OpenProject Calendar' do
project_module :calendar_view, dependencies: :work_package_tracking do
permission :view_calendar,
{ 'calendar/calendars': %i[index show] },
{ 'calendar/calendars': %i[index show details overview relations] },
dependencies: %i[view_work_packages],
contract_actions: { calendar: %i[read] }
permission :manage_calendars,
{ 'calendar/calendars': %i[index show new destroy] },
{ 'calendar/calendars': %i[index show new destroy details overview relations] },
dependencies: %i[view_calendar add_work_packages edit_work_packages save_queries manage_public_queries],
contract_actions: { calendar: %i[create update destroy] }
end

Loading…
Cancel
Save