Merge branch 'dev' into housekeeping/avatar-cache

pull/7785/head
ulferts 5 years ago
commit 944ce28052
No known key found for this signature in database
GPG Key ID: A205708DE1284017
  1. 2
      .buildpacks
  2. 2
      Dockerfile
  3. 4
      Gemfile.lock
  4. BIN
      app/assets/images/boards_video_teaser.png
  5. BIN
      app/assets/images/new_feature_teaser.png
  6. 3
      app/assets/stylesheets/content/_advanced_filters.sass
  7. 4
      app/assets/stylesheets/content/_autocomplete.sass
  8. 5
      app/assets/stylesheets/content/_grid.sass
  9. 5
      app/assets/stylesheets/content/_my_page.sass
  10. 5
      app/assets/stylesheets/content/_project_overview.sass
  11. 5
      app/assets/stylesheets/content/_project_status.sass
  12. 2
      app/assets/stylesheets/content/_projects_list.sass
  13. 6
      app/assets/stylesheets/layout/work_packages/_full_view.sass
  14. 1
      app/controllers/my_controller.rb
  15. 50
      app/helpers/project_status_helper.rb
  16. 1
      app/helpers/projects_helper.rb
  17. 15
      app/helpers/user_consent_helper.rb
  18. 4
      app/models/attachment.rb
  19. 5
      app/models/queries/base_order.rb
  20. 5
      app/models/queries/filters/base.rb
  21. 2
      app/models/queries/projects.rb
  22. 1
      app/models/queries/projects/filters/project_filter.rb
  23. 65
      app/models/queries/projects/filters/project_status_filter.rb
  24. 49
      app/models/queries/projects/orders/project_status_order.rb
  25. 5
      app/services/set_localization_service.rb
  26. 45
      app/uploaders/fog_file_uploader.rb
  27. 1
      app/views/account/_user_consent_check.html.erb
  28. 25
      app/views/projects/filters/_form.html.erb
  29. 9
      app/views/projects/index.html.erb
  30. 7
      config/locales/crowdin/js-ar.yml
  31. 7
      config/locales/crowdin/js-bg.yml
  32. 7
      config/locales/crowdin/js-ca.yml
  33. 7
      config/locales/crowdin/js-cs.yml
  34. 7
      config/locales/crowdin/js-da.yml
  35. 7
      config/locales/crowdin/js-de.yml
  36. 7
      config/locales/crowdin/js-es.yml
  37. 7
      config/locales/crowdin/js-fi.yml
  38. 7
      config/locales/crowdin/js-fil.yml
  39. 7
      config/locales/crowdin/js-fr.yml
  40. 7
      config/locales/crowdin/js-hr.yml
  41. 7
      config/locales/crowdin/js-hu.yml
  42. 7
      config/locales/crowdin/js-id.yml
  43. 9
      config/locales/crowdin/js-it.yml
  44. 9
      config/locales/crowdin/js-ja.yml
  45. 7
      config/locales/crowdin/js-ko.yml
  46. 7
      config/locales/crowdin/js-lt.yml
  47. 7
      config/locales/crowdin/js-nl.yml
  48. 7
      config/locales/crowdin/js-no.yml
  49. 7
      config/locales/crowdin/js-pl.yml
  50. 7
      config/locales/crowdin/js-pt-BR.yml
  51. 7
      config/locales/crowdin/js-pt.yml
  52. 7
      config/locales/crowdin/js-ro.yml
  53. 9
      config/locales/crowdin/js-ru.yml
  54. 7
      config/locales/crowdin/js-sk.yml
  55. 11
      config/locales/crowdin/js-sv.yml
  56. 9
      config/locales/crowdin/js-tr.yml
  57. 7
      config/locales/crowdin/js-uk.yml
  58. 7
      config/locales/crowdin/js-vi.yml
  59. 7
      config/locales/crowdin/js-zh-CN.yml
  60. 7
      config/locales/crowdin/js-zh-TW.yml
  61. 16
      config/locales/js-en.yml
  62. 16
      docs/operations/backup/docker/backup.md
  63. 2
      frontend/src/app/components/homescreen/blocks/new-features.component.sass
  64. 25
      frontend/src/app/components/homescreen/blocks/new-features.component.ts
  65. 5
      frontend/src/app/components/work-packages/work-package-comment/work-package-comment-field-handler.ts
  66. 4
      frontend/src/app/components/wp-activity/activity-entry.component.html
  67. 2
      frontend/src/app/components/wp-activity/activity-entry.component.ts
  68. 4
      frontend/src/app/components/wp-activity/revision/revision-activity.component.html
  69. 1
      frontend/src/app/components/wp-activity/revision/revision-activity.component.ts
  70. 2
      frontend/src/app/components/wp-activity/user/user-activity.component.html
  71. 10
      frontend/src/app/components/wp-activity/user/user-activity.component.ts
  72. 3
      frontend/src/app/components/wp-relations/embedded/inline/add-existing/wp-relation-inline-add-existing.component.html
  73. 2
      frontend/src/app/components/wp-relations/wp-relations-create/wp-relation-create.template.html
  74. 13
      frontend/src/app/components/wp-relations/wp-relations-create/wp-relations-autocomplete/wp-relations-autocomplete.component.ts
  75. 2
      frontend/src/app/modules/boards/board-constants.const.ts
  76. 1
      frontend/src/app/modules/dashboards/dashboard-constants.const.ts
  77. 2
      frontend/src/app/modules/dashboards/openproject-dashboards.module.ts
  78. 4
      frontend/src/app/modules/fields/edit/field-types/project-status-edit-field.component.html
  79. 19
      frontend/src/app/modules/fields/edit/field-types/project-status-edit-field.component.ts
  80. 42
      frontend/src/app/modules/grids/widgets/project-status/project-status.component.sass
  81. 1
      frontend/src/app/modules/grids/widgets/project-status/project-status.component.ts
  82. 3
      frontend/src/app/modules/grids/widgets/wp-graph/wp-graph.component.html
  83. 2
      frontend/src/app/modules/my-page/openproject-my-page.module.ts
  84. 2
      frontend/src/app/modules/overview/openproject-overview.module.ts
  85. 10
      frontend/src/app/modules/router/openproject.routes.ts
  86. 21
      frontend/src/app/modules/work-package-graphs/embedded/wp-embedded-graph.component.ts
  87. 5
      frontend/src/app/modules/work-package-graphs/embedded/wp-embedded-graph.html
  88. 22
      lib/api/helpers/attachment_renderer.rb
  89. 2
      lib/open_project/configuration.rb
  90. 2
      lib/open_project/design.rb
  91. 33
      lib/open_project/patches/carrierwave.rb
  92. 2
      modules/avatars/lib/api/v3/users/user_avatar_api.rb
  93. 23
      modules/avatars/spec/requests/user_avatar_api_spec.rb
  94. 10
      modules/dashboards/spec/features/work_package_graph_spec.rb
  95. 12
      spec/features/auth/consent_auth_stage_spec.rb
  96. 107
      spec/features/projects/projects_index_spec.rb
  97. 8
      spec/features/versions/graph_spec.rb
  98. 23
      spec/models/attachment_spec.rb
  99. 50
      spec/models/queries/projects/filters/project_status_filter_spec.rb
  100. 2
      spec/support/shared/with_config.rb
  101. Some files were not shown because too many files have changed in this diff Show More

@ -1,2 +1,2 @@
https://github.com/heroku/heroku-buildpack-nodejs.git#v162
https://github.com/pkgr/heroku-buildpack-ruby.git#v199-1
https://github.com/pkgr/heroku-buildpack-ruby.git#v206-1

@ -2,7 +2,7 @@ FROM ruby:2.6-stretch
MAINTAINER operations@openproject.com
ENV NODE_VERSION "10.15.0"
ENV BUNDLER_VERSION "2.0.1"
ENV BUNDLER_VERSION "2.0.2"
ENV APP_USER app
ENV APP_PATH /app
ENV APP_DATA_PATH /var/openproject/assets

@ -58,7 +58,7 @@ GIT
GIT
remote: https://github.com/opf/openproject-translations.git
revision: db3a22f2aaa173cadb98494e001d75594c1ce70f
revision: b70a654ae018268cfddf57f444670f87b7bc31dc
branch: dev
specs:
openproject-translations (7.4.0)
@ -1109,4 +1109,4 @@ RUBY VERSION
ruby 2.6.1p33
BUNDLED WITH
2.0.1
2.0.2

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

@ -113,7 +113,6 @@ $advanced-filters--grid-gap: 10px
&:hover
text-decoration: none
.advanced-filters--remove-filter-icon
@extend .icon-close, .icon4
@ -124,7 +123,6 @@ $advanced-filters--grid-gap: 10px
@include grid-content()
@include grid-visible-overflow
.advanced-filters--spacer
border-top: 1px solid $filters--border-color
height: 1px
@ -138,7 +136,6 @@ $advanced-filters--grid-gap: 10px
.work-packages-embedded-view--container .advanced-filters--container
margin: 0 0 1rem 0
@include breakpoint(680px down)
.advanced-filters--filters
.advanced-filters--filter

@ -179,10 +179,6 @@ mark.ui-autocomplete-match
.ng-dropdown-panel
z-index: 9500 !important
// Fix to avoid misplacing the ng-select container
&.-hidden-until-positioned
display: none
.ng-option
font-size: 14px
line-height: 22px

@ -8,6 +8,11 @@ $grid--widget-padding: 20px 20px 20px 20px
@mixin grid--commons
display: grid
body.widget-grid-layout
#content-wrapper,
#content
background-color: $grid-background-color
.grid--container
@include grid--commons

@ -26,11 +26,6 @@
// See docs/COPYRIGHT.rdoc for more details.
//++
.controller-my_page\/angular
#content-wrapper,
#content
background-color: $grid-background-color
.my-page--container
#right,
#left

@ -26,11 +26,6 @@
// See docs/COPYRIGHT.rdoc for more details.
//++
.controller-overviews\/overviews
#content-wrapper,
#content
background-color: $grid-background-color
/* Align widget boxes with description above on project overview */
.project-overview
margin: 0 -10px

@ -39,6 +39,11 @@
border-color: $project-status-green
background-color: adjust-color($project-status-green, $alpha: -0.7)
&.-inline
height: 24px
width: 24px
border-width: 6px
.project-status--container
display: inline-block

@ -46,7 +46,7 @@ form.project-filters
.advanced-filters--filter-value
// visibility based on operator type
&.hidden
display: none
visibility: hidden
// visibility for list value selectors
.multi-select

@ -205,12 +205,6 @@
display: flex
position: relative
// Fix: align and size hover border like buttons in toolbar.
.inline-edit--container .inline-edit--display-field
padding-top: 3px
padding-bottom: 3px
margin-top: 2px
.work-packages--type-selector:not(.wp-new-top-row--element)
.inline-edit--display-field
padding-right: 5px !important

@ -32,6 +32,7 @@ class MyController < ApplicationController
include Concerns::PasswordConfirmation
include Concerns::UserPasswordChange
include ActionView::Helpers::TagHelper
layout 'my'
helper_method :gon

@ -0,0 +1,50 @@
#-- encoding: UTF-8
#-- copyright
# OpenProject is a project management system.
# Copyright (C) 2012-2018 the OpenProject Foundation (OPF)
#
# 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-2017 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 docs/COPYRIGHT.rdoc for more details.
#++
module ProjectStatusHelper
def project_status_css_class(status)
code = project_status_ensure_default_code(status)
'-' + code.tr('_', '-')
end
def project_status_name(status)
code = project_status_ensure_default_code(status)
project_status_name_for_code(code)
end
def project_status_name_for_code(code)
code ||= 'not_set'
I18n.t('js.grid.widgets.project_status.' + code)
end
def project_status_ensure_default_code(status)
status.try(:code) || 'not_set'
end
end

@ -129,6 +129,7 @@ module ProjectsHelper
def whitelisted_project_filter?(filter)
whitelist = [
Queries::Projects::Filters::ActiveFilter,
Queries::Projects::Filters::ProjectStatusFilter,
Queries::Projects::Filters::CreatedAtFilter,
Queries::Projects::Filters::LatestActivityAtFilter,
Queries::Projects::Filters::NameAndIdentifierFilter,

@ -28,7 +28,6 @@
#++
module ::UserConsentHelper
def consent_param?
params[:consent_check].present?
end
@ -38,10 +37,18 @@ module ::UserConsentHelper
Setting.consent_required? && consent_configured?
end
def user_consent_instructions(user)
language = user.try(:language) || Setting.default_language
##
# Gets consent instructions for the given user.
#
# @param user [User] The user to get instructions for.
# @param locale [String] ISO-639-1 code for the desired locale (e.g. de, en, fr).
# `I18n.locale` is set for each request individually depending
# among other things on the user's Accept-Language headers.
# @return [String] Instructions in the respective language.
def user_consent_instructions(user, locale: I18n.locale)
all = Setting.consent_info
all.fetch(language) { all.values.first }
all.fetch(locale) { all.values.first }
end
def consent_configured?

@ -59,8 +59,8 @@ class Attachment < ActiveRecord::Base
##
# Returns an URL if the attachment is stored in an external (fog) attachment storage
# or nil otherwise.
def external_url
url = URI.parse file.download_url(content_disposition: content_disposition) # returns a path if local
def external_url(expires_in: nil)
url = URI.parse file.download_url(content_disposition: content_disposition, expires_in: expires_in) # returns a path if local
url if url.host
rescue URI::InvalidURIError

@ -54,6 +54,7 @@ class Queries::BaseOrder
def scope
scope = order
scope = scope.joins(joins) if joins
scope = scope.left_outer_joins(left_outer_joins) if left_outer_joins
scope
end
@ -71,6 +72,10 @@ class Queries::BaseOrder
nil
end
def left_outer_joins
nil
end
def with_raise_on_invalid
if VALID_DIRECTIONS.include?(direction)
yield

@ -109,6 +109,7 @@ class Queries::Filters::Base
def scope
scope = model.where(where)
scope = scope.joins(joins) if joins
scope = scope.left_outer_joins(left_outer_joins) if left_outer_joins
scope
end
@ -132,6 +133,10 @@ class Queries::Filters::Base
nil
end
def left_outer_joins
nil
end
def includes
nil
end

@ -44,9 +44,11 @@ module Queries::Projects
register.filter query, filters::PrincipalFilter
register.filter query, filters::ParentFilter
register.filter query, filters::IdFilter
register.filter query, filters::ProjectStatusFilter
register.order query, orders::DefaultOrder
register.order query, orders::LatestActivityAtOrder
register.order query, orders::RequiredDiskSpaceOrder
register.order query, orders::CustomFieldOrder
register.order query, orders::ProjectStatusOrder
end

@ -1,4 +1,5 @@
#-- encoding: UTF-8
#-- copyright
# OpenProject is a project management system.
# Copyright (C) 2012-2018 the OpenProject Foundation (OPF)

@ -0,0 +1,65 @@
#-- encoding: UTF-8
#-- copyright
# OpenProject is a project management system.
# Copyright (C) 2012-2018 the OpenProject Foundation (OPF)
#
# 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-2017 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 docs/COPYRIGHT.rdoc for more details.
#++
module Queries
module Projects
module Filters
class ProjectStatusFilter < ::Queries::Projects::Filters::ProjectFilter
include ProjectStatusHelper
def allowed_values
@allowed_values ||= Project::Status.codes.map do |code, id|
[project_status_name_for_code(code), id.to_s]
end
end
def left_outer_joins
:status
end
def where
operator_strategy.sql_for_field(values, Project::Status.table_name, :code)
end
def type
:list_optional
end
def self.key
:project_status_code
end
def human_name
I18n.t('js.grid.widgets.project_status.title')
end
end
end
end
end

@ -0,0 +1,49 @@
#-- encoding: UTF-8
#-- copyright
# OpenProject is a project management system.
# Copyright (C) 2012-2018 the OpenProject Foundation (OPF)
#
# 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-2017 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 docs/COPYRIGHT.rdoc for more details.
#++
class Queries::Projects::Orders::ProjectStatusOrder < Queries::BaseOrder
self.model = Project
def self.key
:project_status
end
def left_outer_joins
:status
end
private
def order
with_raise_on_invalid do
model.order(Arel.sql("project_statuses.code").send(direction))
end
end
end

@ -29,6 +29,7 @@ class SetLocalizationService
def header_language
return unless http_accept_header
accept_lang = parse_qvalues(http_accept_header).first
find_language_or_prefix accept_lang
end
@ -54,13 +55,15 @@ class SetLocalizationService
tmp = tmp.sort_by { |_val, q| -q }
tmp.map! { |val, _q| val }
end
return tmp
tmp
rescue
nil
end
def find_language_or_prefix(language)
return nil unless language
language = language.to_s.downcase
find_language(language) || find_language(language.split('-').first)
end

@ -27,6 +27,7 @@
#++
require 'carrierwave/storage/fog'
require 'open_project/patches/carrierwave'
class FogFileUploader < CarrierWave::Uploader::Base
include FileUploader
@ -57,18 +58,20 @@ class FogFileUploader < CarrierWave::Uploader::Base
super
end
##
# Generates a download URL for this file.
#
# @param options [Hash] Options hash.
# @option options [String] :content_disposition Pass this content disposition to S3 so that it serves the file with it.
# @option options [DateTime] :expires_at Date at which the link should expire (default: now + 5 minutes)
# @option options [ActiveSupport::Duration] :expires_in Duration in which the link should expire.
#
# @return [String] The URL to download the file from.
def download_url(options = {})
url_options = {}
if options[:content_disposition].present?
url_options[:query] = {
# Passing this option to S3 will make it serve the file with the
# respective content disposition. Without it no content disposition
# header is sent. This only works for S3 but we don't support
# anything else anyway (see carrierwave.rb).
"response-content-disposition" => options[:content_disposition]
}
end
set_content_disposition! url_options, options: options
set_expires_at! url_options, options: options
remote_file.url url_options
end
@ -85,4 +88,28 @@ class FogFileUploader < CarrierWave::Uploader::Base
rescue Excon::Errors::Forbidden
false
end
private
def set_content_disposition!(url_options, options:)
if options[:content_disposition].present?
url_options[:query] = {
# Passing this option to S3 will make it serve the file with the
# respective content disposition. Without it no content disposition
# header is sent. This only works for S3 but we don't support
# anything else anyway (see carrierwave.rb).
"response-content-disposition" => options[:content_disposition]
}
end
end
def set_expires_at!(url_options, options:)
if options[:expires_in].present?
url_options[:expire_at] = ::Fog::Time.now + options[:expires_in]
end
if options[:expires_at].present?
url_options[:expire_at] = ::Fog::Time.at options[:expires_at] - ::Fog::Time.offset
end
end
end

@ -11,4 +11,3 @@
<%= t('consent.checkbox_label') %>
</label>
</section>

@ -46,7 +46,6 @@
</li>
<% end %>
<li class="advanced-filters--spacer <%= query.filters.blank? ? 'hidden' : '' %>"></li>
<li class="advanced-filters--add-filter">
@ -74,22 +73,22 @@
focus: "false",
'aria-invalid': "false" %>
</div>
<% unless EnterpriseToken.allows_to?(:custom_fields_in_projects_list)%>
<div class="advanced-filters--add-filter-info">
<div class="notification-box">
<div class="notification-box--content">
<%= t('ee.upsale.project_filters.description_html',
link: link_to(t(:label_enterprise_edition),
"#{OpenProject::Static::Links.links[:upsale][:href]}/?utm_source=unknown&utm_medium=community-edition&utm_campaign=project-list-filter",
target: '_blank')) %>
</div>
</div>
</div>
<% end %>
</li>
<li class="advanced-filters--controls">
<%= submit_tag t('button_apply'), class: 'button -small -highlight', name: nil %>
</li>
</ul>
<% unless EnterpriseToken.allows_to?(:custom_fields_in_projects_list)%>
<div class="advanced-filters--add-filter-info">
<div class="notification-box">
<div class="notification-box--content">
<%= t('ee.upsale.project_filters.description_html',
link: link_to(t(:label_enterprise_edition),
"#{OpenProject::Static::Links.links[:upsale][:href]}/?utm_source=unknown&utm_medium=community-edition&utm_campaign=project-list-filter",
target: '_blank')) %>
</div>
</div>
</div>
<% end %>
</fieldset>
<% end %>

@ -65,6 +65,7 @@ See docs/COPYRIGHT.rdoc for more details.
<tr>
<%= render partial: 'hierarchy_header' %>
<%= projects_sort_header_tag('name', caption: Project.human_attribute_name(:name), param: :json) %>
<%= projects_sort_header_tag('project_status', caption: Project.human_attribute_name(:status), param: :json) %>
<%= projects_sort_header_tag('public', caption: Project.human_attribute_name(:public), param: :json) %>
<% if EnterpriseToken.allows_to?(:custom_fields_in_projects_list) %>
<% @custom_fields.each do |custom_field| %>
@ -100,6 +101,12 @@ See docs/COPYRIGHT.rdoc for more details.
<% end %>
<%= link_to_project(project, {}, {}, false) %>
</td>
<td>
<% if project.status.try(:code) %>
<span class="project-status--bulb -inline <%= project_status_css_class(project.status) %>"></span>
<span class="project-status--name <%= project_status_css_class(project.status) %>"><%= project_status_name(project.status) %></span>
<% end %>
</td>
<td><%= checked_image project.public? %></td>
<% if EnterpriseToken.allows_to?(:custom_fields_in_projects_list) %>
<% @custom_fields.each do |custom_field| %>
@ -144,7 +151,7 @@ See docs/COPYRIGHT.rdoc for more details.
<% unless project.description.blank? %>
<tr class="project-description <%= project_css_classes(project) %> <%= level > 0 ? "idnt idnt-#{level}" : nil %> <%= params[:expand] == 'all' ? '-expanded' : '' %>">
<td></td>
<td colspan="<%= @custom_fields.size + (User.current.admin? ? 6 : 3) %>" class="project--hierarchy">
<td colspan="<%= @custom_fields.size + (User.current.admin? ? 7 : 4) %>" class="project--hierarchy">
<div class="description-container">
<span class="wiki"><%= format_text(short_project_description(project), project: project) %></span>
</div>

@ -203,12 +203,9 @@ ar:
blocks:
new_features:
text_new_features: "Read about new features and product updates."
current_new_feature_html: "OpenProject contains a new <b>Boards view</b> for Agile project management. </br> To activate this new feature for your existing projects, please do the following steps: <ul><li>Activate the module Boards within existing projects' settings.</li> <li>Configure your Boards in a project.</li> <li>Verify roles and permissions</li></ul>"
image_alt_text: "Board teaser image"
learn_about: "Learn more about Agile Boards"
current_new_feature_html: "OpenProject contains a new <b>Overview page</b> to <b>display important project information</b> and show whether the project is on track. </br> You can insert various new status widgets, such as: <ul><li>project status,</li> <li>overview of work package status,</li> <li>task progress,</li> <li>tasks assigned to users.</li></ul>"
learn_about: "Learn more about the new status widgets"
label_activate: "تفعيل"
label_activity_no: "رقم إدخال النشاط%{activityNo}"
label_activity_with_comment_no: "رقم إدخال النشاط %{activityNo}. يمتلك تعليق مستخدم."
label_add_column_after: "Add column after"
label_add_column_before: "Add column before"
label_add_columns: "Add columns"

@ -203,12 +203,9 @@ bg:
blocks:
new_features:
text_new_features: "Read about new features and product updates."
current_new_feature_html: "OpenProject contains a new <b>Boards view</b> for Agile project management. </br> To activate this new feature for your existing projects, please do the following steps: <ul><li>Activate the module Boards within existing projects' settings.</li> <li>Configure your Boards in a project.</li> <li>Verify roles and permissions</li></ul>"
image_alt_text: "Board teaser image"
learn_about: "Learn more about Agile Boards"
current_new_feature_html: "OpenProject contains a new <b>Overview page</b> to <b>display important project information</b> and show whether the project is on track. </br> You can insert various new status widgets, such as: <ul><li>project status,</li> <li>overview of work package status,</li> <li>task progress,</li> <li>tasks assigned to users.</li></ul>"
learn_about: "Learn more about the new status widgets"
label_activate: "Activate"
label_activity_no: "Дейност запис номер %{activityNo}"
label_activity_with_comment_no: "Дейност запис номер %{activityNo}. Има коментар от потребител."
label_add_column_after: "Add column after"
label_add_column_before: "Add column before"
label_add_columns: "Add columns"

@ -203,12 +203,9 @@ ca:
blocks:
new_features:
text_new_features: "Read about new features and product updates."
current_new_feature_html: "OpenProject contains a new <b>Boards view</b> for Agile project management. </br> To activate this new feature for your existing projects, please do the following steps: <ul><li>Activate the module Boards within existing projects' settings.</li> <li>Configure your Boards in a project.</li> <li>Verify roles and permissions</li></ul>"
image_alt_text: "Board teaser image"
learn_about: "Learn more about Agile Boards"
current_new_feature_html: "OpenProject contains a new <b>Overview page</b> to <b>display important project information</b> and show whether the project is on track. </br> You can insert various new status widgets, such as: <ul><li>project status,</li> <li>overview of work package status,</li> <li>task progress,</li> <li>tasks assigned to users.</li></ul>"
learn_about: "Learn more about the new status widgets"
label_activate: "Activar"
label_activity_no: "Número d'entrada d'activitat %{activityNo}"
label_activity_with_comment_no: "Número d'entrada d'activitat %{activityNo}. Disposa d'un comentari d'usuari."
label_add_column_after: "Add column after"
label_add_column_before: "Add column before"
label_add_columns: "Add columns"

@ -203,12 +203,9 @@ cs:
blocks:
new_features:
text_new_features: "Read about new features and product updates."
current_new_feature_html: "OpenProject contains a new <b>Boards view</b> for Agile project management. </br> To activate this new feature for your existing projects, please do the following steps: <ul><li>Activate the module Boards within existing projects' settings.</li> <li>Configure your Boards in a project.</li> <li>Verify roles and permissions</li></ul>"
image_alt_text: "Board teaser image"
learn_about: "Learn more about Agile Boards"
current_new_feature_html: "OpenProject contains a new <b>Overview page</b> to <b>display important project information</b> and show whether the project is on track. </br> You can insert various new status widgets, such as: <ul><li>project status,</li> <li>overview of work package status,</li> <li>task progress,</li> <li>tasks assigned to users.</li></ul>"
learn_about: "Learn more about the new status widgets"
label_activate: "Aktivovat"
label_activity_no: "Activity entry number %{activityNo}"
label_activity_with_comment_no: "Activity entry number %{activityNo}. Has a user comment."
label_add_column_after: "Add column after"
label_add_column_before: "Add column before"
label_add_columns: "Přidat sloupce"

@ -202,12 +202,9 @@ da:
blocks:
new_features:
text_new_features: "Read about new features and product updates."
current_new_feature_html: "OpenProject contains a new <b>Boards view</b> for Agile project management. </br> To activate this new feature for your existing projects, please do the following steps: <ul><li>Activate the module Boards within existing projects' settings.</li> <li>Configure your Boards in a project.</li> <li>Verify roles and permissions</li></ul>"
image_alt_text: "Board teaser image"
learn_about: "Learn more about Agile Boards"
current_new_feature_html: "OpenProject contains a new <b>Overview page</b> to <b>display important project information</b> and show whether the project is on track. </br> You can insert various new status widgets, such as: <ul><li>project status,</li> <li>overview of work package status,</li> <li>task progress,</li> <li>tasks assigned to users.</li></ul>"
learn_about: "Learn more about the new status widgets"
label_activate: "Aktivér"
label_activity_no: "Aktivitetsindlægsnummer %{activityNo}"
label_activity_with_comment_no: "Aktivitetsindlægsnummer %{activityNo}. Har en brugerkommentar."
label_add_column_after: "Add column after"
label_add_column_before: "Add column before"
label_add_columns: "Add columns"

@ -202,12 +202,9 @@ de:
blocks:
new_features:
text_new_features: "Lesen Sie über neue Funktionen und Updates."
current_new_feature_html: "OpenProject enthält eine neue <b>Boards-Ansicht</b> für das agile Projektmanagement. </br> Um diese Funktion für Ihre bestehenden Projekte zu aktivieren, bitte folgende Schritte ausführen: <ul><li>Aktivieren Sie die Modul-Boards in den bestehenden Projekten-Einstellungen.</li> <li>Konfigurieren Sie Ihre Boards in einem Projekt.</li> <li>Überprüfen Sie die Rollen und Berechtigungen Ihres Systems</li></ul>"
image_alt_text: "Board Teaser-Bild"
learn_about: "Erfahren Sie mehr über agile Boards"
current_new_feature_html: "OpenProject contains a new <b>Overview page</b> to <b>display important project information</b> and show whether the project is on track. </br> You can insert various new status widgets, such as: <ul><li>project status,</li> <li>overview of work package status,</li> <li>task progress,</li> <li>tasks assigned to users.</li></ul>"
learn_about: "Learn more about the new status widgets"
label_activate: "Aktiviere"
label_activity_no: "Aktivitäts-Nummer: %{activityNo}"
label_activity_with_comment_no: "Aktivitäts-Nummer: %{activityNo}. Hat einen Benutzerkommentar."
label_add_column_after: "Spalte danach hinzufügen"
label_add_column_before: "Spalte davor hinzufügen"
label_add_columns: "Spalte hinzufügen"

@ -203,12 +203,9 @@ es:
blocks:
new_features:
text_new_features: "Obtenga información sobre nuevas características y actualizaciones de productos."
current_new_feature_html: "OpenProject ahora ofrece la nueva <b>vista Panel</b> para la administración de proyectos ágil. </br> Para activar esta nueva característica para sus proyectos existentes, siga este procedimiento: <ul><li>Active el módulo Paneles en la configuración de los proyectos existentes.</li> <li>Configure los paneles en un proyecto.</li> <li>Verifique los roles y los permisos</li></ul>"
image_alt_text: "Imagen promocional de los paneles"
learn_about: "Obtenga más información sobre los paneles ágiles"
current_new_feature_html: "OpenProject contains a new <b>Overview page</b> to <b>display important project information</b> and show whether the project is on track. </br> You can insert various new status widgets, such as: <ul><li>project status,</li> <li>overview of work package status,</li> <li>task progress,</li> <li>tasks assigned to users.</li></ul>"
learn_about: "Learn more about the new status widgets"
label_activate: "Activar"
label_activity_no: "Entrada de actividad número %{activityNo}"
label_activity_with_comment_no: "Entrada de actividad número %{activityNo} tiene un comentario."
label_add_column_after: "Añadir columna a la derecha"
label_add_column_before: "Añadir columna a la izquierda"
label_add_columns: "Añadir columnas"

@ -203,12 +203,9 @@ fi:
blocks:
new_features:
text_new_features: "Read about new features and product updates."
current_new_feature_html: "OpenProject contains a new <b>Boards view</b> for Agile project management. </br> To activate this new feature for your existing projects, please do the following steps: <ul><li>Activate the module Boards within existing projects' settings.</li> <li>Configure your Boards in a project.</li> <li>Verify roles and permissions</li></ul>"
image_alt_text: "Board teaser image"
learn_about: "Learn more about Agile Boards"
current_new_feature_html: "OpenProject contains a new <b>Overview page</b> to <b>display important project information</b> and show whether the project is on track. </br> You can insert various new status widgets, such as: <ul><li>project status,</li> <li>overview of work package status,</li> <li>task progress,</li> <li>tasks assigned to users.</li></ul>"
learn_about: "Learn more about the new status widgets"
label_activate: "Aktivoi"
label_activity_no: "Aktiviteettimerkinnän numero %{activityNo}"
label_activity_with_comment_no: "Aktiviteettimerkinnän numero %{activityNo}. Sisältää käyttäjän kommentin."
label_add_column_after: "Add column after"
label_add_column_before: "Add column before"
label_add_columns: "Lisää sarakkeita"

@ -203,12 +203,9 @@ fil:
blocks:
new_features:
text_new_features: "Read about new features and product updates."
current_new_feature_html: "OpenProject contains a new <b>Boards view</b> for Agile project management. </br> To activate this new feature for your existing projects, please do the following steps: <ul><li>Activate the module Boards within existing projects' settings.</li> <li>Configure your Boards in a project.</li> <li>Verify roles and permissions</li></ul>"
image_alt_text: "Board teaser image"
learn_about: "Learn more about Agile Boards"
current_new_feature_html: "OpenProject contains a new <b>Overview page</b> to <b>display important project information</b> and show whether the project is on track. </br> You can insert various new status widgets, such as: <ul><li>project status,</li> <li>overview of work package status,</li> <li>task progress,</li> <li>tasks assigned to users.</li></ul>"
learn_about: "Learn more about the new status widgets"
label_activate: "Aktibo"
label_activity_no: "Bilang ng aktibidad entry %{activityNo}"
label_activity_with_comment_no: "Bilang ng aktibidad entry %{activityNo}. Mayroong komento ng gumagamit."
label_add_column_after: "Add column after"
label_add_column_before: "Add column before"
label_add_columns: "Magdagdag ng hanay"

@ -203,12 +203,9 @@ fr:
blocks:
new_features:
text_new_features: "En savoir plus sur les nouvelles fonctionnalités et les mises à jour des produits."
current_new_feature_html: "OpenProject contient un nouvel <b>affichage de Tableaux</b> pour la gestion de projet Agile. </br> Afin d'activer cette nouvelle fonctionnalité pour vos projets existants, veuillez suivre les étapes suivantes : <ul><li>Activez le module Tableaux dans les paramètres des projets existants.</li> <li>Configurez vos Tableaux dans un projet.</li> <li>Vérifiez les rôles et les permissions</li></ul>"
image_alt_text: "Image teaser du Tableau"
learn_about: "En savoir plus sur les Tableaux Agile"
current_new_feature_html: "OpenProject contains a new <b>Overview page</b> to <b>display important project information</b> and show whether the project is on track. </br> You can insert various new status widgets, such as: <ul><li>project status,</li> <li>overview of work package status,</li> <li>task progress,</li> <li>tasks assigned to users.</li></ul>"
learn_about: "Learn more about the new status widgets"
label_activate: "Activer"
label_activity_no: "Entrée d'activité numéro %{activityNo}"
label_activity_with_comment_no: "Entrée d'activité numéro %{activityNo}. A un commentaire utilisateur."
label_add_column_after: "Ajouter une colonne au-dessus"
label_add_column_before: "Ajouter une colonne avant"
label_add_columns: "Ajouter des colonnes"

@ -203,12 +203,9 @@ hr:
blocks:
new_features:
text_new_features: "Read about new features and product updates."
current_new_feature_html: "OpenProject contains a new <b>Boards view</b> for Agile project management. </br> To activate this new feature for your existing projects, please do the following steps: <ul><li>Activate the module Boards within existing projects' settings.</li> <li>Configure your Boards in a project.</li> <li>Verify roles and permissions</li></ul>"
image_alt_text: "Board teaser image"
learn_about: "Learn more about Agile Boards"
current_new_feature_html: "OpenProject contains a new <b>Overview page</b> to <b>display important project information</b> and show whether the project is on track. </br> You can insert various new status widgets, such as: <ul><li>project status,</li> <li>overview of work package status,</li> <li>task progress,</li> <li>tasks assigned to users.</li></ul>"
learn_about: "Learn more about the new status widgets"
label_activate: "Aktiviraj"
label_activity_no: "Broj unosa aktivnosti %{activityNo}"
label_activity_with_comment_no: "Broj unosa aktivnosti %{activityNo}. Postoji komentar korisnika."
label_add_column_after: "Add column after"
label_add_column_before: "Add column before"
label_add_columns: "Add columns"

@ -202,12 +202,9 @@ hu:
blocks:
new_features:
text_new_features: "Read about new features and product updates."
current_new_feature_html: "OpenProject contains a new <b>Boards view</b> for Agile project management. </br> To activate this new feature for your existing projects, please do the following steps: <ul><li>Activate the module Boards within existing projects' settings.</li> <li>Configure your Boards in a project.</li> <li>Verify roles and permissions</li></ul>"
image_alt_text: "Board teaser image"
learn_about: "Learn more about Agile Boards"
current_new_feature_html: "OpenProject contains a new <b>Overview page</b> to <b>display important project information</b> and show whether the project is on track. </br> You can insert various new status widgets, such as: <ul><li>project status,</li> <li>overview of work package status,</li> <li>task progress,</li> <li>tasks assigned to users.</li></ul>"
learn_about: "Learn more about the new status widgets"
label_activate: "Aktivál"
label_activity_no: "Tevékenységi bejegyzések száma %{activityNo}"
label_activity_with_comment_no: "Tevékenységi bejegyzések száma %{activityNo}. Felhasználói megjegyzéssel."
label_add_column_after: "Oszlop hozzáadása utána"
label_add_column_before: "Oszlop hozzáadása előtte"
label_add_columns: "Oszlopok hozzáadása"

@ -203,12 +203,9 @@ id:
blocks:
new_features:
text_new_features: "Read about new features and product updates."
current_new_feature_html: "OpenProject contains a new <b>Boards view</b> for Agile project management. </br> To activate this new feature for your existing projects, please do the following steps: <ul><li>Activate the module Boards within existing projects' settings.</li> <li>Configure your Boards in a project.</li> <li>Verify roles and permissions</li></ul>"
image_alt_text: "Board teaser image"
learn_about: "Learn more about Agile Boards"
current_new_feature_html: "OpenProject contains a new <b>Overview page</b> to <b>display important project information</b> and show whether the project is on track. </br> You can insert various new status widgets, such as: <ul><li>project status,</li> <li>overview of work package status,</li> <li>task progress,</li> <li>tasks assigned to users.</li></ul>"
learn_about: "Learn more about the new status widgets"
label_activate: "Aktifkan"
label_activity_no: "Activity entry number %{activityNo}"
label_activity_with_comment_no: "Activity entry number %{activityNo}. Has a user comment."
label_add_column_after: "Add column after"
label_add_column_before: "Add column before"
label_add_columns: "Tambah kolom"

@ -203,12 +203,9 @@ it:
blocks:
new_features:
text_new_features: "Informati sulle nuove funzionalità e sugli aggiornamenti dei prodotti."
current_new_feature_html: "OpenProject contiene una nuova <b>vista Tabellone</b> per la gestione di progetti Agile. </br> Per attivare questa nuova funzionalità sui progetti esistenti, effettua i seguenti passi: <ul><li>Attiva il modulo Schede nelle impostazioni dei progetti esistenti.</li> <li>Configura le tue Schede in un progetto.</li> <li>Verifica ruoli e permessi</li></ul>"
image_alt_text: "Immagine di esempio di Tabellone"
learn_about: "Ulteriori informazioni sui Tabelloni Agile"
current_new_feature_html: "OpenProject contiene una nuova pagina di panoramica <b></b> per visualizzare <b>importanti informazioni del progetto</b> e mostrare se il progetto è sulla traccia. </br> Puoi inserire vari nuovi widget di stato, come: <ul><li>stato del progetto,</li> <li>panoramica dello stato del pacchetto di lavoro,</li> <li>progresso del task,</li> <li>attività assegnate agli utenti.</li></ul>"
learn_about: "Ulteriori informazioni sui nuovi widget di stato"
label_activate: "Attiva"
label_activity_no: "Voce attività numero %{activityNo}"
label_activity_with_comment_no: "Voce attività numero %{activityNo}. Ha un commento da un utente."
label_add_column_after: "Aggiungi colonna dopo"
label_add_column_before: "Aggiungi colonna prima"
label_add_columns: "Aggiungi colonne"
@ -695,7 +692,7 @@ it:
label_content: "Clicca qui per saltare il menu ed andare al contenuto"
placeholders:
default: "-"
formattable: "%{name}: Click to edit..."
formattable: "%{name}: Clicca per modificare..."
query:
column_names: "Colonne"
group_by: "Raggruppa i risultati per"

@ -204,12 +204,9 @@ ja:
blocks:
new_features:
text_new_features: "新しい機能と製品の更新について表示する"
current_new_feature_html: "OpenProject には、アジャイルプロジェクトを管理する新しい<b>ボードビュー</b>が含まれています。 </br>既存のプロジェクトに対してこの新機能を有効にするには、次の手順に従ってください。<ul><li>既存のプロジェクトの設定で、ボードのモジュールを有効にします。</li> <li>プロジェクトでボードを設定します。 </li> <li>役割と権限を確認してください</li></ul>"
image_alt_text: "ボードのティーザー画像"
learn_about: "アジャイルボードについて知る"
current_new_feature_html: "OpenProject には、<b>重要なプロジェクト情報を表示</b> して、プロジェクトが順調に進んでいるかどうかを表示する、新しい <b>概要ページ</b> が含まれています。 </br> <ul><li>プロジェクトのステータス</li> <li>作業項目のステータスの概要</li> <li>タスクの進捗状況</li> <li>ユーザーに割り当てられたタスク</li></ul> など、さまざまな新しいステータスウィジェットを挿入できます。"
learn_about: "新しいステータスウィジェットの詳細"
label_activate: "有効にする"
label_activity_no: "アクティビティのエントリ番号 %{activityNo}"
label_activity_with_comment_no: "アクティビティのエントリ番号 %{activityNo}。ユーザー コメントがあります。"
label_add_column_after: "後に列を追加"
label_add_column_before: "前に列を追加"
label_add_columns: "列を追加"
@ -696,7 +693,7 @@ ja:
label_content: "ここをクリックすると、メニューをスキップして、コンテンツへ移動します"
placeholders:
default: "-"
formattable: "%{name}: Click to edit..."
formattable: "%{name}: クリックして編集..."
query:
column_names: "列"
group_by: "グループ化"

@ -203,12 +203,9 @@ ko:
blocks:
new_features:
text_new_features: "새로운 기능 및 제품 업데이트에 대해 읽어보십시오."
current_new_feature_html: "OpenProject에는 애자일 프로젝트 관리를 위한 새로운 <b>보드 보기</b>가 포함되어 있습니다. </br> 기존 프로젝트에서 이 새로운 기능을 활성화하려면 다음 단계를 따르십시오. <ul><li>기존 프로젝트 설정에서 보드 모듈을 활성화합니다.</li> <li>프로젝트에서 보드를 구성합니다.</li> <li>역할 및 사용 권한을 확인합니다.</li></ul>"
image_alt_text: "보드 티저 이미지"
learn_about: "애자일 보드에 대해 자세히 알아보기"
current_new_feature_html: "OpenProject contains a new <b>Overview page</b> to <b>display important project information</b> and show whether the project is on track. </br> You can insert various new status widgets, such as: <ul><li>project status,</li> <li>overview of work package status,</li> <li>task progress,</li> <li>tasks assigned to users.</li></ul>"
learn_about: "Learn more about the new status widgets"
label_activate: "활성화"
label_activity_no: "활동 항목 번호 %{activityNo}"
label_activity_with_comment_no: "활동 항목 번호 %{activityNo}. 사용자 의견 포함."
label_add_column_after: "다음 뒤에 열 추가"
label_add_column_before: "다음 앞에 열 추가"
label_add_columns: "열 추가"

@ -203,12 +203,9 @@ lt:
blocks:
new_features:
text_new_features: "Skaitykite apie naujas savybes ir produkto atnaujinimus."
current_new_feature_html: "OpenProject yra naujas <b>Lentų rodinys</b> skirtas Agile projektų valdymui. </br> Norėdami aktyvuoti šią naują savybę esamiems projektams: <ul><li>Aktyvuokite modulį Lentos esamų projektų nustatymuose.</li> <li>Sukonfigūruokite jūsų Lentas projekte.</li> <li>Patikrinkite roles ir teises</li></ul>"
image_alt_text: "Lentos iliustracija"
learn_about: "Sužinokite daugiau apie Agile Lentas"
current_new_feature_html: "OpenProject contains a new <b>Overview page</b> to <b>display important project information</b> and show whether the project is on track. </br> You can insert various new status widgets, such as: <ul><li>project status,</li> <li>overview of work package status,</li> <li>task progress,</li> <li>tasks assigned to users.</li></ul>"
learn_about: "Learn more about the new status widgets"
label_activate: "Aktyvuoti"
label_activity_no: "Veiklos įrašo numeris %{activityNo}"
label_activity_with_comment_no: "Veiklos įrašo numeris %{activityNo}. Turintis vartotojo komentarą."
label_add_column_after: "Pridėti stulpelį po"
label_add_column_before: "Pridėti stulpelį prieš"
label_add_columns: "Pridėti stulpelių"

@ -203,12 +203,9 @@ nl:
blocks:
new_features:
text_new_features: "Read about new features and product updates."
current_new_feature_html: "OpenProject contains a new <b>Boards view</b> for Agile project management. </br> To activate this new feature for your existing projects, please do the following steps: <ul><li>Activate the module Boards within existing projects' settings.</li> <li>Configure your Boards in a project.</li> <li>Verify roles and permissions</li></ul>"
image_alt_text: "Board teaser image"
learn_about: "Learn more about Agile Boards"
current_new_feature_html: "OpenProject contains a new <b>Overview page</b> to <b>display important project information</b> and show whether the project is on track. </br> You can insert various new status widgets, such as: <ul><li>project status,</li> <li>overview of work package status,</li> <li>task progress,</li> <li>tasks assigned to users.</li></ul>"
learn_about: "Learn more about the new status widgets"
label_activate: "Activeren"
label_activity_no: "Activiteit ingangsnummer %{activityNo}"
label_activity_with_comment_no: "Activiteit ingangsnummer %{activityNo}. Bevat gebruikerscommentaar."
label_add_column_after: "Kolom toevoegen na"
label_add_column_before: "Kolom toevoegen voor"
label_add_columns: "Kolommen toevoegen"

@ -203,12 +203,9 @@
blocks:
new_features:
text_new_features: "Read about new features and product updates."
current_new_feature_html: "OpenProject contains a new <b>Boards view</b> for Agile project management. </br> To activate this new feature for your existing projects, please do the following steps: <ul><li>Activate the module Boards within existing projects' settings.</li> <li>Configure your Boards in a project.</li> <li>Verify roles and permissions</li></ul>"
image_alt_text: "Board teaser image"
learn_about: "Learn more about Agile Boards"
current_new_feature_html: "OpenProject contains a new <b>Overview page</b> to <b>display important project information</b> and show whether the project is on track. </br> You can insert various new status widgets, such as: <ul><li>project status,</li> <li>overview of work package status,</li> <li>task progress,</li> <li>tasks assigned to users.</li></ul>"
learn_about: "Learn more about the new status widgets"
label_activate: "Aktiver"
label_activity_no: "Activity entry number %{activityNo}"
label_activity_with_comment_no: "Activity entry number %{activityNo}. Has a user comment."
label_add_column_after: "Add column after"
label_add_column_before: "Add column before"
label_add_columns: "Add columns"

@ -203,12 +203,9 @@ pl:
blocks:
new_features:
text_new_features: "Przeczytaj o nowych funkcjach i aktualizacjach produktów."
current_new_feature_html: "OpenProject zawiera nowy <b>widok Tablice</b> do zwinnego zarządzania projektami. </br> Aby aktywować tę nową funkcję w istniejących projektach, wykonaj następujące kroki: <ul><li>Aktywuj moduł Tablice w ustawieniach istniejących projektów.</li> <li>Skonfiguruj swoje tablice w projekcie.</li> <li>Zweryfikuj role i uprawnienia.</li></ul>"
image_alt_text: "Obraz zapowiedzi tablic"
learn_about: "Dowiedz się więcej o tablicach zwinnych"
current_new_feature_html: "OpenProject contains a new <b>Overview page</b> to <b>display important project information</b> and show whether the project is on track. </br> You can insert various new status widgets, such as: <ul><li>project status,</li> <li>overview of work package status,</li> <li>task progress,</li> <li>tasks assigned to users.</li></ul>"
learn_about: "Learn more about the new status widgets"
label_activate: "Aktywuj"
label_activity_no: "Aktywność %{activityNo}"
label_activity_with_comment_no: "Aktywność %{activityNo} została skomentowana."
label_add_column_after: "Dodaj kolumnę po"
label_add_column_before: "Dodaj kolumnę przed"
label_add_columns: "Dodaj kolumny"

@ -202,12 +202,9 @@ pt-BR:
blocks:
new_features:
text_new_features: "Ler sobre os novos recursos e atualizações de produtos."
current_new_feature_html: "O OpenProject contém uma nova <b>visualização de Quadros</b> para gestão de projetos Agile. </br> Para ativar este novo recurso em seus projetos existentes, por favor, siga as seguintes etapas: <ul><li>Ative os Quadros de módulo dentro das configurações dos projetos existentes.</li> <li>Configure os seus Quadros em um projeto.</li> <li>Verifique as funções e permissões</li></ul>"
image_alt_text: "Imagem teaser do Quadro"
learn_about: "Saiba mais sobre os Quadros Agile"
current_new_feature_html: "OpenProject contains a new <b>Overview page</b> to <b>display important project information</b> and show whether the project is on track. </br> You can insert various new status widgets, such as: <ul><li>project status,</li> <li>overview of work package status,</li> <li>task progress,</li> <li>tasks assigned to users.</li></ul>"
learn_about: "Learn more about the new status widgets"
label_activate: "Ativar"
label_activity_no: "Número da atividade %{activityNo}"
label_activity_with_comment_no: "Atividade número %{activityNo}. Tem um comentário de um usuário."
label_add_column_after: "Adicionar coluna depois"
label_add_column_before: "Adicionar coluna antes"
label_add_columns: "Adicionar colunas"

@ -203,12 +203,9 @@ pt:
blocks:
new_features:
text_new_features: "Leia sobre novos recursos e atualizações de produtos."
current_new_feature_html: "O OpenProject contém uma nova <b>visualização de Quadro</b> para gestão de projetos Agile. </br> Para ativar esta nova função nos seus projetos existentes, por favor siga os seguintes passos: <ul><li>Ativar os Quadros de módulo dentro das configurações dos projetos existentes.</li> <li>Configure os seus Quadros num projeto.</li> <li>Verifique funções e permissões</li></ul>"
image_alt_text: "Imagem de teaser Board"
learn_about: "Saiba mais sobre os Quadros Agile"
current_new_feature_html: "OpenProject contains a new <b>Overview page</b> to <b>display important project information</b> and show whether the project is on track. </br> You can insert various new status widgets, such as: <ul><li>project status,</li> <li>overview of work package status,</li> <li>task progress,</li> <li>tasks assigned to users.</li></ul>"
learn_about: "Learn more about the new status widgets"
label_activate: "Ativar"
label_activity_no: "Número de entrada da atividade %{activityNo}"
label_activity_with_comment_no: "Número de entrada da atividade %{activityNo}. Tem um comentário de utilizador."
label_add_column_after: "Adicionar coluna após"
label_add_column_before: "Adicionar coluna antes"
label_add_columns: "Adicionar colunas"

@ -202,12 +202,9 @@ ro:
blocks:
new_features:
text_new_features: "Read about new features and product updates."
current_new_feature_html: "OpenProject contains a new <b>Boards view</b> for Agile project management. </br> To activate this new feature for your existing projects, please do the following steps: <ul><li>Activate the module Boards within existing projects' settings.</li> <li>Configure your Boards in a project.</li> <li>Verify roles and permissions</li></ul>"
image_alt_text: "Board teaser image"
learn_about: "Learn more about Agile Boards"
current_new_feature_html: "OpenProject contains a new <b>Overview page</b> to <b>display important project information</b> and show whether the project is on track. </br> You can insert various new status widgets, such as: <ul><li>project status,</li> <li>overview of work package status,</li> <li>task progress,</li> <li>tasks assigned to users.</li></ul>"
learn_about: "Learn more about the new status widgets"
label_activate: "Activare"
label_activity_no: "Acțiunea cu numărul %{activityNo}"
label_activity_with_comment_no: "Acțiunea cu numărul %{activityNo}. Are un comentariu de utilizator."
label_add_column_after: "Adauga o coloana dupa"
label_add_column_before: "Adauga o coloana inainte"
label_add_columns: "Adaugați coloane"

@ -202,12 +202,9 @@ ru:
blocks:
new_features:
text_new_features: "Читайте о новых возможностях и обновлениях продуктов."
current_new_feature_html: "В OpenProject появилось новое <b>представление \"Доски\" (Boards)</b> для управления agile-проектами. </br> Чтобы включить эту функцию для уже существующих проектов, выполните следующее: <ul><li>Включите модуль \"Доски\" (Boards) в настройках существующих проектов.</li> <li>Настройте Доски в проектах.</li> <li>Проверьте роли и разрешения</li></ul>"
image_alt_text: "Тизер доски"
learn_about: "Подробнее о Agile Boards"
current_new_feature_html: "OpenProject contains a new <b>Overview page</b> to <b>display important project information</b> and show whether the project is on track. </br> You can insert various new status widgets, such as: <ul><li>project status,</li> <li>overview of work package status,</li> <li>task progress,</li> <li>tasks assigned to users.</li></ul>"
learn_about: "Learn more about the new status widgets"
label_activate: "Активировать"
label_activity_no: "Деятельность номер %{activityNo}"
label_activity_with_comment_no: "Деятельность номер %{activityNo}. Есть комментарий пользователя."
label_add_column_after: "Добавить столбец после"
label_add_column_before: "Добавить столбец перед"
label_add_columns: "Добавить столбец"
@ -698,7 +695,7 @@ ru:
label_content: "Кликните здесь, чтобы пропустить меню и перейти к содержанию"
placeholders:
default: "-"
formattable: "%{name}: Click to edit..."
formattable: "%{name}: Нажмите для редактирования..."
query:
column_names: "Столбцы"
group_by: "Результаты группы по"

@ -203,12 +203,9 @@ sk:
blocks:
new_features:
text_new_features: "Read about new features and product updates."
current_new_feature_html: "OpenProject contains a new <b>Boards view</b> for Agile project management. </br> To activate this new feature for your existing projects, please do the following steps: <ul><li>Activate the module Boards within existing projects' settings.</li> <li>Configure your Boards in a project.</li> <li>Verify roles and permissions</li></ul>"
image_alt_text: "Board teaser image"
learn_about: "Learn more about Agile Boards"
current_new_feature_html: "OpenProject contains a new <b>Overview page</b> to <b>display important project information</b> and show whether the project is on track. </br> You can insert various new status widgets, such as: <ul><li>project status,</li> <li>overview of work package status,</li> <li>task progress,</li> <li>tasks assigned to users.</li></ul>"
learn_about: "Learn more about the new status widgets"
label_activate: "Aktivovať"
label_activity_no: "Záznam aktivity číslo %{activityNo}"
label_activity_with_comment_no: "Záznam aktivity číslo %{activityNo} (obsahuje komentár)"
label_add_column_after: "Pridať stĺpec po"
label_add_column_before: "Pridať stĺpec pred"
label_add_columns: "Pridať stĺpce"

@ -54,7 +54,7 @@ sv:
button_duplicate: "Duplicera"
button_edit: "Redigera"
button_filter: "Filter"
button_advanced_filter: "Advanced filter"
button_advanced_filter: "Avancerat filter"
button_list_view: "Listvy"
button_show_view: "Helskärmsläge"
button_log_time: "Logga tid"
@ -108,7 +108,7 @@ sv:
editor:
preview: 'Växla förhandsgranskningsläge'
source_code: 'Toggle Markdown source mode'
error_saving_failed: 'Saving the document failed with the following error: %{error}'
error_saving_failed: 'Misslyckades med att spara dokumentet på grund av följande fel: %{error}'
error_initialization_failed: 'Failed to initialize CKEditor!'
mode:
manual: 'Switch to Markdown source'
@ -202,12 +202,9 @@ sv:
blocks:
new_features:
text_new_features: "Read about new features and product updates."
current_new_feature_html: "OpenProject contains a new <b>Boards view</b> for Agile project management. </br> To activate this new feature for your existing projects, please do the following steps: <ul><li>Activate the module Boards within existing projects' settings.</li> <li>Configure your Boards in a project.</li> <li>Verify roles and permissions</li></ul>"
image_alt_text: "Board teaser image"
learn_about: "Learn more about Agile Boards"
current_new_feature_html: "OpenProject contains a new <b>Overview page</b> to <b>display important project information</b> and show whether the project is on track. </br> You can insert various new status widgets, such as: <ul><li>project status,</li> <li>overview of work package status,</li> <li>task progress,</li> <li>tasks assigned to users.</li></ul>"
learn_about: "Learn more about the new status widgets"
label_activate: "Aktivera"
label_activity_no: "Aktivitetspost nummer %{activityNo}"
label_activity_with_comment_no: "Aktivitetspost nummer %{activityNo} har en användarkommentar."
label_add_column_after: "Add column after"
label_add_column_before: "Add column before"
label_add_columns: "Lägg till kolumn"

@ -203,12 +203,9 @@ tr:
blocks:
new_features:
text_new_features: "Yeni özellikler ve ürün güncellemeleri hakkında bilgi edinin."
current_new_feature_html: "OpenProject, Çevik proje yönetimi için yeni bir <b> Pano görünümü </b> içerir. </br> Bu yeni özelliği mevcut projeleriniz için etkinleştirmek için lütfen aşağıdaki adımları uygulayın: <ul> <li> Modül Panolarını mevcut projelerin ayarları dahilinde etkinleştirin. </li> <li> Panolarınızı bir projede yapılandırın. </li> <li> Rolleri ve izinleri doğrula </li> </ul>"
image_alt_text: "Yönetim Kurulu teaser image"
learn_about: "Çevik Kurullar hakkında daha fazla bilgi edinin"
current_new_feature_html: "OpenProject, <b> önemli proje bilgilerini görüntülemek </b> ve projenin yolunda olup olmadığını göstermek için yeni bir <b> Genel bakış sayfası </b> içerir. </br> Şunlar gibi çeşitli yeni durum widget'ları ekleyebilirsiniz: <ul> <li> proje durumu, </li> <li> iş paketi durumuna genel bakış, </li> <li> görev ilerlemesi, </ li > <li> kullanıcılara atanan görevler. </li> </ul>"
learn_about: "Yeni durum widget'ları hakkında daha fazla bilgi edinin"
label_activate: "Etkinleştir"
label_activity_no: "Etkinlik giriş numarası %{activityNo}"
label_activity_with_comment_no: "Etkinlik giriş numarası %{activityNo}. Kullanıcı yorumu var."
label_add_column_after: "Sonrasına sütun ekle"
label_add_column_before: "Öncesine sütun ekle"
label_add_columns: "Sütunlar ekle"
@ -695,7 +692,7 @@ tr:
label_content: "Menüyü geçerek içeriği görmek için tıklayın"
placeholders:
default: "-"
formattable: "%{name}: Click to edit..."
formattable: "%{name}: Düzenlemek için tıklayın ..."
query:
column_names: "Sütunlar"
group_by: "Sonuçları grupla"

@ -203,12 +203,9 @@ uk:
blocks:
new_features:
text_new_features: "Читайте про нові функції та оновлення продуктів."
current_new_feature_html: "OpenProject містить новий <b> Перегляд плати </b> для керування Agile проектом. </br> Щоб активувати цю нову функцію для існуючих проектів, виконайте такі дії: <ul> <li> Активуйте панелі модулів у налаштуваннях існуючих проектів. </li> <li> Налаштуйте плати в проекті. </li> <li> Перевірте ролі та дозволи </li> </ul>"
image_alt_text: "Зображення тизера дошки\n"
learn_about: "Дізнайтеся більше про Agile Boards"
current_new_feature_html: "OpenProject contains a new <b>Overview page</b> to <b>display important project information</b> and show whether the project is on track. </br> You can insert various new status widgets, such as: <ul><li>project status,</li> <li>overview of work package status,</li> <li>task progress,</li> <li>tasks assigned to users.</li></ul>"
learn_about: "Learn more about the new status widgets"
label_activate: "Активувати"
label_activity_no: "Запис активності номер %{activityNo}"
label_activity_with_comment_no: "Запис активності номер %{activityNo}. Має коментар користувача."
label_add_column_after: "Додати стовпець після"
label_add_column_before: "Додати стовпець перед"
label_add_columns: "Додати стовпці"

@ -202,12 +202,9 @@ vi:
blocks:
new_features:
text_new_features: "Read about new features and product updates."
current_new_feature_html: "OpenProject contains a new <b>Boards view</b> for Agile project management. </br> To activate this new feature for your existing projects, please do the following steps: <ul><li>Activate the module Boards within existing projects' settings.</li> <li>Configure your Boards in a project.</li> <li>Verify roles and permissions</li></ul>"
image_alt_text: "Board teaser image"
learn_about: "Learn more about Agile Boards"
current_new_feature_html: "OpenProject contains a new <b>Overview page</b> to <b>display important project information</b> and show whether the project is on track. </br> You can insert various new status widgets, such as: <ul><li>project status,</li> <li>overview of work package status,</li> <li>task progress,</li> <li>tasks assigned to users.</li></ul>"
learn_about: "Learn more about the new status widgets"
label_activate: "Activate"
label_activity_no: "Số chỉ mục hoạt động %{activityNo}"
label_activity_with_comment_no: "Số chỉ mục hoạt động %{activityNo}. Có một nhận xét của người dùng."
label_add_column_after: "Thêm cột phía sau"
label_add_column_before: "Thêm cột phía trước"
label_add_columns: "Add columns"

@ -203,12 +203,9 @@ zh-CN:
blocks:
new_features:
text_new_features: "了解新功能和产品更新。"
current_new_feature_html: "OpenProject 包含一个用于敏捷项目管理的新<b>开发板视图</b>。</br>要为现有项目激活此新功能,请按以下步骤操作:<ul><li>在现有项目的设置中激活开发板模块。</li><li>在项目中配置您的开发板。</li><li>验证角色和权限</li></ul>"
image_alt_text: "开发板宣传图像"
learn_about: "详细了解敏捷开发板"
current_new_feature_html: "OpenProject contains a new <b>Overview page</b> to <b>display important project information</b> and show whether the project is on track. </br> You can insert various new status widgets, such as: <ul><li>project status,</li> <li>overview of work package status,</li> <li>task progress,</li> <li>tasks assigned to users.</li></ul>"
learn_about: "Learn more about the new status widgets"
label_activate: "激活"
label_activity_no: "活动条目编号 %{activityNo}"
label_activity_with_comment_no: "活动条目编号 %{activityNo},有用户评论。"
label_add_column_after: "之后添加列"
label_add_column_before: "在之前添加列"
label_add_columns: "增添列"

@ -202,12 +202,9 @@ zh-TW:
blocks:
new_features:
text_new_features: "Read about new features and product updates."
current_new_feature_html: "OpenProject contains a new <b>Boards view</b> for Agile project management. </br> To activate this new feature for your existing projects, please do the following steps: <ul><li>Activate the module Boards within existing projects' settings.</li> <li>Configure your Boards in a project.</li> <li>Verify roles and permissions</li></ul>"
image_alt_text: "Board teaser image"
learn_about: "Learn more about Agile Boards"
current_new_feature_html: "OpenProject contains a new <b>Overview page</b> to <b>display important project information</b> and show whether the project is on track. </br> You can insert various new status widgets, such as: <ul><li>project status,</li> <li>overview of work package status,</li> <li>task progress,</li> <li>tasks assigned to users.</li></ul>"
learn_about: "Learn more about the new status widgets"
label_activate: "啟用"
label_activity_no: "活動條目編號 %{activityNo}"
label_activity_with_comment_no: "活動條目編號 %{activityNo}。有的使用者評論。"
label_add_column_after: "在後面增加一欄"
label_add_column_before: "在前面增加一欄"
label_add_columns: "增加欄"

@ -224,16 +224,14 @@ en:
blocks:
new_features:
text_new_features: "Read about new features and product updates."
current_new_feature_html: "OpenProject contains a new <b>Boards view</b> for Agile project management. </br>
To activate this new feature for your existing projects, please do the following steps:
<ul><li>Activate the module Boards within existing projects' settings.</li>
<li>Configure your Boards in a project.</li>
<li>Verify roles and permissions</li></ul>"
image_alt_text: "Board teaser image"
learn_about: "Learn more about Agile Boards"
current_new_feature_html: "OpenProject contains a new <b>Overview page</b> to <b>display important project information</b> and show whether the project is on track. </br>
You can insert various new status widgets, such as:
<ul><li>project status,</li>
<li>overview of work package status,</li>
<li>task progress,</li>
<li>tasks assigned to users.</li></ul>"
learn_about: "Learn more about the new status widgets"
label_activate: "Activate"
label_activity_no: "Activity entry number %{activityNo}"
label_activity_with_comment_no: "Activity entry number %{activityNo}. Has a user comment."
label_add_column_after: "Add column after"
label_add_column_before: "Add column before"
label_add_columns: "Add columns"

@ -21,3 +21,19 @@ S3 or FTP).
If at any point you want to restore from a backup, just put your backup in
`/var/lib/openproject` on your local host, and re-launch the docker container.
## Dumping the database
**Note:** this only applies for the self-contained OpenProject container not using
an external database but instead a database right in the container.
If you need a SQL dump of your database straight from the container you can do the
following to dump it into the current directory:
```
docker exec $CONTAINER_ID bash -c \
'export PGPASSWORD=openproject && pg_dump -U openproject -h 127.0.0.1' \
> openproject.sql
```
If you don't know the container id (or name) you can find it out using `docker ps`.

@ -2,7 +2,7 @@
display: flex
.widget-box--teaser-image
background-image: var(--board-teaser-image)
background-image: var(--new-feature-teaser-image)
min-width: 170px
background-size: contain
background-repeat: no-repeat

@ -26,13 +26,11 @@
// See doc/COPYRIGHT.rdoc for more details.
// ++
import {Component, Injector} from '@angular/core';
import {Component} from '@angular/core';
import {DynamicBootstrapper} from "core-app/globals/dynamic-bootstrapper";
import {I18nService} from "core-app/modules/common/i18n/i18n.service";
import {boardTeaserWebsiteURL} from "core-app/modules/boards/board-constants.const";
import {OpModalService} from "core-components/op-modals/op-modal.service";
import {BoardVideoTeaserModalComponent} from "core-app/modules/boards/board/board-video-teaser-modal/board-video-teaser-modal.component";
import {DomSanitizer} from "@angular/platform-browser";
import {dashboardWebsiteUrl} from "core-app/modules/dashboards/dashboard-constants.const";
@Component({
template: `
@ -43,10 +41,10 @@ import {DomSanitizer} from "@angular/platform-browser";
<div class="widget-box--description">
<p [innerHtml]="text.currentNewFeatureHtml"></p>
<a class="widget-box--teaser-image" (click)="showBoardTeaserVideo()"></a>
<a class="widget-box--teaser-image"></a>
</div>
<a [href]="boardTeaserWebsiteUrl()" target="_blank">{{ text.learnAbout }}</a>
<a [href]="teaserWebsiteUrl()" target="_blank">{{ text.learnAbout }}</a>
`,
selector: 'homescreen-new-features-block',
styleUrls: ['./new-features.component.sass'],
@ -56,7 +54,6 @@ import {DomSanitizer} from "@angular/platform-browser";
* Component for the homescreen block to promote new features.
* When updating this for the next release, be sure to cleanup stuff is not needed any more:
* Locals (js-en.yml), Styles (new-features.component.sass), HTML (above), TS (below)
* Further cleanup additional stuff (and update this list): The boardVideoTeaserModal, the image shown as modalLink
*/
export class HomescreenNewFeaturesBlockComponent {
public text = {
@ -64,24 +61,14 @@ export class HomescreenNewFeaturesBlockComponent {
descriptionNewFeatures: this.i18n.t('js.homescreen.blocks.new_features.text_new_features'),
currentNewFeatureHtml: this.i18n.t('js.homescreen.blocks.new_features.current_new_feature_html'),
learnAbout: this.i18n.t('js.homescreen.blocks.new_features.learn_about'),
imageAltText: this.i18n.t('js.homescreen.blocks.new_features.image_alt_text'),
};
constructor(readonly i18n:I18nService,
readonly opModalService:OpModalService,
readonly injector:Injector,
readonly domSanitizer:DomSanitizer) {
}
public showBoardTeaserVideo() {
this.opModalService.show(
BoardVideoTeaserModalComponent,
this.injector
);
}
public boardTeaserWebsiteUrl() {
return this.domSanitizer.bypassSecurityTrustResourceUrl(boardTeaserWebsiteURL);
public teaserWebsiteUrl() {
return this.domSanitizer.bypassSecurityTrustResourceUrl(dashboardWebsiteUrl);
}
}

@ -36,11 +36,6 @@ export abstract class WorkPackageCommentFieldHandler extends EditFieldHandler im
*/
public abstract get htmlId():string;
/**
* Required field label translation
*/
public abstract get fieldLabel():string;
public abstract get workPackage():WorkPackageResource;
public reset(withText:string = '') {

@ -3,14 +3,12 @@
<revision-activity *ngSwitchCase="'Revision'"
[workPackage]="workPackage"
[activity]="activity"
[activityNo]="activityNo"
[activityLabel]="activityLabel">
[activityNo]="activityNo">
</revision-activity>
<user-activity *ngSwitchDefault
[workPackage]="workPackage"
[activity]="activity"
[activityNo]="activityNo"
[activityLabel]="activityLabel"
[isInitial]="isInitial">
</user-activity>
</div>

@ -44,7 +44,6 @@ export class ActivityEntryComponent implements OnInit {
public projectId:string;
public activityType:string;
public activityLabel:string;
constructor(readonly PathHelper:PathHelperService,
readonly I18n:I18nService) {
@ -55,7 +54,6 @@ export class ActivityEntryComponent implements OnInit {
this.projectId = this.workPackage.project.idFromLink;
this.activityType = this.activity._type;
this.activityLabel = this.I18n.t('js.label_activity_no', {activityNo: this.activityNo});
}
}

@ -1,7 +1,5 @@
<div class="work-package-details-activities-activity-contents"
*ngIf="workPackage"
tabindex="0"
[attr.aria-label]="activityLabel">
*ngIf="workPackage">
<div class="comments-number">
<activity-link [workPackage]="workPackage"
[activityNo]="activityNo">

@ -43,7 +43,6 @@ export class RevisionActivityComponent implements OnInit {
@Input() public workPackage:WorkPackageResource;
@Input() public activity:any;
@Input() public activityNo:number;
@Input() public activityLabel:string;
public userId:string | number;
public userName:string;

@ -1,7 +1,5 @@
<div class="work-package-details-activities-activity-contents"
tabindex="0"
*ngIf="workPackage"
[attr.aria-label]="fieldLabel || activityLabel"
(mouseenter)="focus()"
(mouseleave)="blur()">
<user-avatar *ngIf="userName"

@ -59,7 +59,6 @@ export class UserActivityComponent extends WorkPackageCommentFieldHandler implem
@Input() public workPackage:WorkPackageResource;
@Input() public activity:HalResource;
@Input() public activityNo:number;
@Input() public activityLabel:string;
@Input() public isInitial:boolean;
public userCanEdit = false;
@ -71,7 +70,6 @@ export class UserActivityComponent extends WorkPackageCommentFieldHandler implem
public userPath:string | null;
public userLabel:string;
public userAvatar:string;
public fieldLabel:string;
public details:any[] = [];
public isComment:boolean;
public isBcfComment:boolean;
@ -118,14 +116,6 @@ export class UserActivityComponent extends WorkPackageCommentFieldHandler implem
this.userCanEdit = !!this.activity.update;
this.userCanQuote = !!this.workPackage.addComment;
if (this.postedComment) {
this.fieldLabel = this.I18n.t('js.label_activity_with_comment_no', {
activityNo: this.activityNo
});
} else {
this.fieldLabel = this.I18n.t('js.label_activity_no', {activityNo: this.activityNo});
}
this.$element.bind('focusin', this.focus.bind(this));
this.$element.bind('focusout', this.blur.bind(this));

@ -6,7 +6,8 @@
[workPackage]="workPackage"
(onSelected)="onSelected($event)"
[additionalFilters]="queryFilters"
[filterCandidatesFor]="relationType">
[filterCandidatesFor]="relationType"
hiddenOverflowContainer=".work-packages-full-view--split-left">
</wp-relations-autocomplete>
</div>
<div class="wp-relations-controls-section relation-row">

@ -37,7 +37,7 @@
[workPackage]="workPackage"
(onSelected)="onSelected($event)"
(onCancel)="toggleRelationsCreateForm()"
[appendToContainer]="'.work-packages-tab-view--overflow'"
[hiddenOverflowContainer]="'.work-packages-tab-view--overflow'"
[selectedRelationType]="selectedRelationType">
</wp-relations-autocomplete>
</div>

@ -72,7 +72,7 @@ export class WorkPackageRelationsAutocomplete implements AfterContentInit {
/** Do we take the current query filters into account? */
@Input() additionalFilters:ApiV3Filter[] = [];
@Input() appendToContainer:string = 'body';
@Input() hiddenOverflowContainer:string = 'body';
@ViewChild(NgSelectComponent, { static: true }) public ngSelectComponent:NgSelectComponent;
@Output() onCancel = new EventEmitter<undefined>();
@ -85,6 +85,8 @@ export class WorkPackageRelationsAutocomplete implements AfterContentInit {
// Search input from ng-select
public searchInput$ = new Subject<string>();
public appendToContainer = 'body';
// Search results mapped to input
public results$:Observable<WorkPackageResource[]> = this.searchInput$.pipe(
debounceTime(250),
@ -165,7 +167,14 @@ export class WorkPackageRelationsAutocomplete implements AfterContentInit {
// https://github.com/ng-select/ng-select/issues/1259
setTimeout(() => {
const component = (this.ngSelectComponent) as any;
component.dropdownPanel._updatePosition();
if (component) {
component.dropdownPanel._updatePosition();
}
jQuery(this.hiddenOverflowContainer).one('scroll', () => {
this.ngSelectComponent.close();
});
}, 25);
}
}

@ -1,3 +1 @@
export const boardTeaserVideoURL = "https://player.vimeo.com/video/337280106";
export const boardTeaserWebsiteURL = "https://www.openproject.org/scrum-agile-boards";

@ -0,0 +1 @@
export const dashboardWebsiteUrl = "https://www.openproject.org/collaboration-software-features/dashboards/";

@ -42,7 +42,7 @@ export const DASHBOARDS_ROUTES:Ng2StateDeclaration[] = [
// cf., https://community.openproject.com/wp/29754
url: '/dashboards/',
data: {
bodyClasses: 'router--dashboards-view-base',
bodyClasses: ['router--dashboards-view-base', 'widget-grid-layout'],
menuItem: menuItemClass
},
component: DashboardComponent

@ -2,11 +2,11 @@
[(ngModel)]="currentStatusCode"
bindLabel="name"
bindValue="code"
class="project-status -hidden-until-positioned"
class="project-status"
(open)="onOpen()"
(close)="onClose()"
(change)="onChange()"
[appendTo]="hiddenOverflowContainer"
[appendTo]="appendToContainer"
[hideSelected]="true"
[disabled]="inFlight">
<ng-template ng-label-tmp let-item="item">

@ -53,6 +53,7 @@ export class ProjectStatusEditFieldComponent extends EditFieldComponent implemen
});
public hiddenOverflowContainer = '#content-wrapper';
public appendToContainer = 'body';
ngOnInit() {
this.currentStatusCode = this.resource['status'] === null ? 'not set' : this.resource['status'];
@ -71,19 +72,21 @@ export class ProjectStatusEditFieldComponent extends EditFieldComponent implemen
}
public onOpen() {
// Force reposition as a workaround for BUG
// https://github.com/ng-select/ng-select/issues/1259
setTimeout(() => {
const dropdown = document.getElementById(this.ngSelectComponent.dropdownId);
if (dropdown) {
dropdown.classList.remove('-hidden-until-positioned');
const component = (this.ngSelectComponent) as any;
if (component.dropdownPanel) {
component.dropdownPanel._updatePosition();
}
}, 25);
jQuery(this.hiddenOverflowContainer).one('scroll', () => {
this.ngSelectComponent.close();
});
jQuery(this.hiddenOverflowContainer).one('scroll.autocompleteContainer', () => {
this.ngSelectComponent.close();
});
}, 25);
}
public onClose() {
// Nothing to do
jQuery(this.hiddenOverflowContainer).off('scroll.autocompleteContainer');
}
}

@ -1,42 +0,0 @@
$gray: #CCCCCC
$red: #E73E3D
$orange: #FFB030
$green: #00D12D
.bulb
display: inline-block
width: 40px
height: 40px
border-radius: 50%
border-width: 10px
border-style: solid
margin-right: 7px
vertical-align: middle
&.-gray
border-color: $gray
background-color: adjust-color($gray, $alpha: -0.7)
&.-red
border-color: $red
background-color: adjust-color($red, $alpha: -0.7)
&.-orange
border-color: $orange
background-color: adjust-color($orange, $alpha: -0.7)
&.-green
border-color: $green
background-color: adjust-color($green, $alpha: -0.7)
.status-name
text-transform: uppercase
font-weight: bold
&.-gray
color: $gray
&.-red
color: $red
&.-orange
color: $orange
&.-green
color: $green
.explanation
margin-top: 9px

@ -42,7 +42,6 @@ import {HalResourceEditingService} from "core-app/modules/fields/edit/services/h
@Component({
templateUrl: './project-status.component.html',
styleUrls: ['./project-status.component.sass'],
changeDetection: ChangeDetectionStrategy.OnPush,
providers: [
// required by the displayField service to render the fields

@ -10,6 +10,5 @@
<wp-embedded-graph class='grid--widget-content'
[datasets]="datasets"
[chartType]="chartType"
*ngIf="datasets.length > 0">
[chartType]="chartType">
</wp-embedded-graph>

@ -38,7 +38,7 @@ export const MY_PAGE_ROUTES:Ng2StateDeclaration[] = [
url: '/my/page',
component: MyPageComponent,
data: {
bodyClasses: 'router--work-packages-my-page',
bodyClasses: ['router--work-packages-my-page', 'widget-grid-layout'],
parent: 'work-packages'
}
},

@ -42,7 +42,7 @@ export const OVERVIEW_ROUTES:Ng2StateDeclaration[] = [
// cf., https://community.openproject.com/wp/29754
url: '/',
data: {
bodyClasses: 'router--overview-view-base',
bodyClasses: ['router--overview-view-base', 'widget-grid-layout'],
menuItem: menuItemClass
},
component: OverviewComponent

@ -67,9 +67,15 @@ export const OPENPROJECT_ROUTES = [
* @param className
* @param action
*/
export function bodyClass(className:string|null|undefined, action:'add'|'remove' = 'add') {
export function bodyClass(className:string[]|string|null|undefined, action:'add'|'remove' = 'add') {
if (className) {
document.body.classList[action](className);
if (Array.isArray(className)) {
className.forEach((cssClass:string) => {
document.body.classList[action](cssClass);
});
} else {
document.body.classList[action](className);
}
}
}
export function updateMenuItem(menuItemClass:string|undefined, action:'add'|'remove' = 'add') {

@ -10,6 +10,10 @@ export interface WorkPackageEmbeddedGraphDataset {
queryId?:number|string;
groups?:GroupObject[];
}
interface ChartDataSet {
label:string;
data:number[];
}
@Component({
selector: 'wp-embedded-graph',
@ -21,14 +25,18 @@ export class WorkPackageEmbeddedGraphComponent {
@Input('chartOptions') public inputChartOptions:ChartOptions;
@Input('chartType') chartType:ChartType = 'horizontalBar';
public showTablePagination = false;
public configuration:WorkPackageTableConfiguration;
public error:string|null = null;
public chartHeight = '100%';
public chartLabels:string[] = [];
public chartData:any = [];
public chartData:ChartDataSet[] = [];
public chartOptions:ChartOptions;
public initialized = false;
public text = {
noResults: this.i18n.t('js.work_packages.no_results.title'),
};
constructor(readonly i18n:I18nService) {}
@ -36,6 +44,11 @@ export class WorkPackageEmbeddedGraphComponent {
if (changes.datasets) {
this.setChartOptions();
this.updateChartData();
if (!changes.datasets.firstChange) {
this.initialized = true;
}
} else if (changes.chartType) {
this.setChartOptions();
}
@ -114,6 +127,10 @@ export class WorkPackageEmbeddedGraphComponent {
this.chartOptions = Object.assign({}, defaults, chartTypeDefaults, this.inputChartOptions);
}
public get hasDataToDisplay() {
return this.chartData.length > 0 && this.chartData.some(set => set.data.length > 0);
}
private setHeight() {
if (this.chartType === 'horizontalBar' && this.datasets && this.datasets[0]) {
let labels:string[] = [];

@ -4,7 +4,10 @@
[labels]="chartLabels"
[chartType]="chartType"
[options]="chartOptions"
*ngIf="chartData.length > 0">
*ngIf="hasDataToDisplay">
</canvas>
<no-results *ngIf="!hasDataToDisplay && initialized"
[title]="text.noResults">
</no-results>
</div>

@ -38,9 +38,13 @@ module API
# to the external storage,
#
# or by directly rendering the file
def respond_with_attachment(attachment)
#
# @param attachment [Attachment] Attachment to be responded with.
# @param external_link_expires_in [ActiveSupport::Duration] Time after which link expires. Default is 5 minutes.
# Only applicable in case of external storage.
def respond_with_attachment(attachment, external_link_expires_in: nil)
if attachment.external_storage?
redirect attachment.external_url.to_s
redirect attachment.external_url(expires_in: external_link_expires_in).to_s
else
content_type attachment.content_type
header['Content-Disposition'] = "#{attachment.content_disposition}; filename=#{attachment.filename}"
@ -48,6 +52,20 @@ module API
attachment.diskfile.read
end
end
def external_avatar_link_expires_in
seconds = external_avatar_link_expiry_seconds
if seconds == 0
nil
else
seconds.seconds
end
end
def external_avatar_link_expiry_seconds
@external_avatar_link_expiry_seconds ||= OpenProject::Configuration.external_avatar_link_expiry_seconds.to_i
end
end
end
end

@ -133,6 +133,8 @@ module OpenProject
# Allow in-context translations to be loaded with CSP
'crowdin_in_context_translations' => true,
'external_avatar_link_expiry_seconds' => 24.hours.to_i,
# Default gravatar image, set to something other than 404
# to ensure a default is returned
'gravatar_fallback_image' => '404',

@ -203,7 +203,7 @@ module OpenProject
'status-selector-bg-color' => '#F99601',
'status-selector-bg-hover-color' => '#E08600',
'card-font-size' => '16px',
'board-teaser-image' => '#{image-url("boards_video_teaser.png")}',
'new-feature-teaser-image' => '#{image-url("new_feature_teaser.png")}',
'project-status-gray' => '#CCCCCC',
'project-status-red' => '#E73E3D',
'project-status-orange' => '#FFB030',

@ -0,0 +1,33 @@
require 'carrierwave'
##
# Code copied straight from the CarrierWave source.
# All we did is add `options[:expire_at]`.
#
# @todo Upgrade to CarrierWave 2.0.2 to make this patch obsolete.
class CarrierWave::Storage::Fog::File
def authenticated_url(options = {})
if ['AWS', 'Google', 'Rackspace', 'OpenStack'].include?(@uploader.fog_credentials[:provider])
# avoid a get by using local references
local_directory = connection.directories.new(:key => @uploader.fog_directory)
local_file = local_directory.files.new(:key => path)
expire_at = options[:expire_at] || ::Fog::Time.now + @uploader.fog_authenticated_url_expiration
case @uploader.fog_credentials[:provider]
when 'AWS', 'Google'
# Older versions of fog-google do not support options as a parameter
if url_options_supported?(local_file)
local_file.url(expire_at, options)
else
warn "Options hash not supported in #{local_file.class}. You may need to upgrade your Fog provider."
local_file.url(expire_at)
end
when 'Rackspace'
connection.get_object_https_url(@uploader.fog_directory, path, expire_at, options)
when 'OpenStack'
connection.get_object_https_url(@uploader.fog_directory, path, expire_at)
else
local_file.url(expire_at)
end
end
end
end

@ -49,7 +49,7 @@ module API
set_cache_headers!
if local_avatar = local_avatar?(@user)
respond_with_attachment(local_avatar)
respond_with_attachment(local_avatar, external_link_expires_in: external_avatar_link_expires_in)
elsif avatar_manager.gravatar_enabled?
redirect build_gravatar_image_url(@user)
else

@ -37,6 +37,8 @@ describe 'API v3 User avatar resource', type: :request, content_type: :json do
subject(:response) { last_response }
let(:setup) { nil }
before do
login_as user
end
@ -47,6 +49,8 @@ describe 'API v3 User avatar resource', type: :request, content_type: :json do
.to receive(:plugin_openproject_avatars)
.and_return(enable_gravatars: gravatars, enable_local_avatars: local_avatars)
setup
get api_v3_paths.user(user.id) + "/avatar"
end
@ -82,6 +86,25 @@ describe 'API v3 User avatar resource', type: :request, content_type: :json do
it 'serves the attachment file' do
expect(response.status).to eq 200
end
context 'with external file storage (S3)' do
let(:setup) do
allow_any_instance_of(Attachment).to receive(:external_storage?).and_return true
expect_any_instance_of(Attachment)
.to receive(:external_url)
.with(expires_in: 86400)
.and_return("external URL")
end
# we test that Attachment#external_url works in `attachments_spec.rb`
# so here we just make sue it's called accordingly when the external
# storage is configured
it 'redirects to temporary external URL' do
expect(response.status).to eq 302
expect(response.location).to eq "external URL"
end
end
end
end
end

@ -142,6 +142,16 @@ describe 'Arbitrary WorkPackage query graph widget dashboard', type: :feature, j
modal.switch_to('General')
general.expect_axis 'Type'
general.expect_type 'Bar'
# A notification is displayed if no work package is returned for the graph
modal.switch_to('Filters')
filters.add_filter_by('Subject', 'contains', '!!!!!!!!!!!!!!!!!')
modal.save
within filter_area.area do
expect(page)
.to have_content(I18n.t('js.work_packages.no_results.title'))
end
end
end

@ -28,7 +28,7 @@
require 'spec_helper'
describe 'Authentication Stages', type: :feature, js: true do
describe 'Authentication Stages', type: :feature do
let(:language) { 'en' }
let(:user_password) { 'bob' * 4 }
let(:user) do
@ -84,12 +84,16 @@ describe 'Authentication Stages', type: :feature, js: true do
expect_logged_in
end
end
context 'when enabled, localized consent exists',
with_settings: { consent_info: { de: '# Einwilligung', en: '# Consent header!' } } do
let(:consent_required) { true }
let(:language) { 'de' }
it 'should show localized consent' do
before do
Capybara.current_session.driver.header('Accept-Language', 'de')
end
it 'should show localized consent as defined by the accept language header (ignoring users language)' do
login_with user.login, user_password
expect(page).to have_selector('.account-consent')
@ -97,7 +101,7 @@ describe 'Authentication Stages', type: :feature, js: true do
end
end
context 'when enabled, but consent exists', with_settings: { consent_info: { en: '# Consent header!' } } do
context 'when enabled, but consent exists', js: true, with_settings: { consent_info: { en: '# Consent header!' } } do
let(:consent_required) { true }
after do

@ -76,6 +76,18 @@ describe 'Projects index page',
page.find("li[filter-name='#{name}'] .filter_rem").click
end
def expect_project_at_place(project, place)
expect(page)
.to have_selector("#project-table .project:nth-of-type(#{place}) td.name",
text: project.name)
end
def expect_projects_in_order(*projects)
projects.each_with_index do |project, index|
expect_project_at_place(project, index + 1)
end
end
feature 'restricts project visibility' do
feature 'for a anonymous user' do
scenario 'only public projects shall be visible' do
@ -394,6 +406,89 @@ describe 'Projects index page',
end
end
feature 'project status filter' do
let!(:no_status_project) do
# A project that never had project status associated.
FactoryBot.create(:project,
name: 'No status project')
end
let!(:green_project) do
# A project that has a project status associated.
FactoryBot.create(:project,
name: 'Green project',
status: FactoryBot.create(:project_status))
end
let!(:gray_project) do
# A project that once had a project status associated, that was later unset.
FactoryBot.create(:project,
name: 'Gray project',
status: FactoryBot.create(:project_status, code: nil))
end
scenario 'sort and filter on project status' do
login_as(admin)
projects_page.visit!
click_link('Sort by "Status"')
expect_project_at_place(green_project, 1)
expect(page).to have_text('(1 - 8/8)')
click_link('Ascending sorted by "Status"')
expect_project_at_place(green_project, 8)
expect(page).to have_text('(1 - 8/8)')
projects_page.open_filters
projects_page.set_filter('project_status_code',
'Project status',
'is',
['On track'])
click_on 'Apply'
expect(page).to have_text(green_project.name)
expect(page).to_not have_text(gray_project.name)
expect(page).to_not have_text(no_status_project.name)
projects_page.set_filter('project_status_code',
'Project status',
'all',
[])
click_on 'Apply'
expect(page).to have_text(green_project.name)
expect(page).to_not have_text(gray_project.name)
expect(page).to_not have_text(no_status_project.name)
projects_page.set_filter('project_status_code',
'Project status',
'none',
[])
click_on 'Apply'
expect(page).to_not have_text(green_project.name)
expect(page).to have_text(gray_project.name)
expect(page).to have_text(no_status_project.name)
projects_page.set_filter('project_status_code',
'Project status',
'is not',
['On track'])
click_on 'Apply'
expect(page).to_not have_text(green_project.name)
expect(page).to have_text(gray_project.name)
expect(page).to have_text(no_status_project.name)
end
end
feature 'other filter types' do
let!(:list_custom_field) { FactoryBot.create :list_project_custom_field }
let!(:date_custom_field) { FactoryBot.create :date_project_custom_field }
@ -744,18 +839,6 @@ describe 'Projects index page',
child_project_a.save!
end
def expect_project_at_place(project, place)
expect(page)
.to have_selector("#project-table .project:nth-of-type(#{place}) td.name",
text: project.name)
end
def expect_projects_in_order(*projects)
projects.each_with_index do |project, index|
expect_project_at_place(project, index + 1)
end
end
scenario 'allows to alter the order in which projects are displayed' do
# initially, ordered by name asc on each hierarchical level
expect_projects_in_order(development_project,

@ -31,9 +31,13 @@ require 'spec_helper'
describe 'version show graph', type: :feature, js: true do
let(:user) { FactoryBot.create :admin }
let(:project) { FactoryBot.create(:project) }
let(:version) { FactoryBot.create(:version) }
let(:version) { FactoryBot.create(:version, project: project) }
let!(:wp) { FactoryBot.create :work_package, fixed_version: version }
let!(:wp) do
FactoryBot.create :work_package,
project: project,
fixed_version: version
end
before do
login_as(user)

@ -268,6 +268,24 @@ describe Attachment, type: :model do
CarrierWave::Configuration.configure_fog! credentials: {}, directory: "my-bucket", public: false
end
shared_examples "it has a temporary download link" do
let(:url_options) { {} }
let(:query) { attachment.external_url(url_options).to_s.split("?").last }
it "should have a default expiry time" do
expect(query).to include "X-Amz-Expires="
expect(query).not_to include "X-Amz-Expires=3600"
end
context "with a custom expiry time" do
let(:url_options) { { expires_in: 1.hour } }
it "should use that time" do
expect(query).to include "X-Amz-Expires=3600"
end
end
end
describe "for an image file" do
before { image_attachment.save! }
@ -275,6 +293,11 @@ describe Attachment, type: :model do
expect(image_attachment.content_disposition).to eq "inline"
expect(image_attachment.external_url.to_s).to include "response-content-disposition=inline"
end
# this is independent from the type of file uploaded so we just test this for the first one
it_behaves_like "it has a temporary download link" do
let(:attachment) { image_attachment }
end
end
describe "for a text file" do

@ -0,0 +1,50 @@
#-- encoding: UTF-8
#-- copyright
# OpenProject is a project management system.
# Copyright (C) 2012-2018 the OpenProject Foundation (OPF)
#
# 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-2017 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 docs/COPYRIGHT.rdoc for more details.
#++
require 'spec_helper'
describe Queries::Projects::Filters::ProjectStatusFilter, type: :model do
it_behaves_like 'basic query filter' do
let(:class_key) { :project_status_code }
let(:type) { :list_optional }
let(:model) { Project }
let(:attribute) { :project_status_code }
let(:values) { ['On track'] }
let(:human_name) { 'Project status' }
let(:admin) { FactoryBot.build_stubbed(:admin) }
let(:user) { FactoryBot.build_stubbed(:user) }
describe '#allowed_values' do
it 'is a list of the possible values' do
expect(instance.allowed_values).to match_array([["At risk", "1"], ["Off track", "2"], ["On track", "0"]])
end
end
end
end

@ -30,7 +30,7 @@
def aggregate_mocked_configuration(example, config)
# We have to manually check parent groups for with_config:,
# since they are being ignored otherwise
example.example_group.parents.each do |parent|
example.example_group.module_parents.each do |parent|
if parent.respond_to?(:metadata) && parent.metadata[:with_config]
config.reverse_merge!(parent.metadata[:with_config])
end

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save