Merge branch 'dev' into 44455-replace-weekdays-api-with-individual-nwd-days-api-in-gantt

pull/11934/head
bsatarnejad 2 years ago
commit eea8e64f43
  1. 2
      Gemfile
  2. 114
      Gemfile.lock
  3. 2
      app/models/work_package.rb
  4. 53
      app/models/work_packages/scopes/covering_dates_and_days_of_week.rb
  5. 29
      app/services/settings/update_service.rb
  6. 14
      app/services/settings/working_days_update_service.rb
  7. 43
      app/workers/work_packages/apply_working_days_change_job.rb
  8. 14
      config/constants/settings/definition.rb
  9. 5
      config/constants/settings/definitions.rb
  10. 3
      config/locales/crowdin/af.yml
  11. 3
      config/locales/crowdin/ar.yml
  12. 3
      config/locales/crowdin/az.yml
  13. 3
      config/locales/crowdin/be.yml
  14. 3
      config/locales/crowdin/bg.yml
  15. 3
      config/locales/crowdin/ca.yml
  16. 3
      config/locales/crowdin/ckb-IR.yml
  17. 3
      config/locales/crowdin/cs.yml
  18. 3
      config/locales/crowdin/da.yml
  19. 3
      config/locales/crowdin/de.yml
  20. 3
      config/locales/crowdin/el.yml
  21. 3
      config/locales/crowdin/eo.yml
  22. 33
      config/locales/crowdin/es.yml
  23. 3
      config/locales/crowdin/et.yml
  24. 3
      config/locales/crowdin/eu.yml
  25. 3
      config/locales/crowdin/fa.yml
  26. 3
      config/locales/crowdin/fi.yml
  27. 3
      config/locales/crowdin/fil.yml
  28. 5
      config/locales/crowdin/fr.yml
  29. 3
      config/locales/crowdin/he.yml
  30. 3
      config/locales/crowdin/hi.yml
  31. 3
      config/locales/crowdin/hr.yml
  32. 3
      config/locales/crowdin/hu.yml
  33. 3
      config/locales/crowdin/id.yml
  34. 3
      config/locales/crowdin/it.yml
  35. 3
      config/locales/crowdin/ja.yml
  36. 8
      config/locales/crowdin/js-es.yml
  37. 2
      config/locales/crowdin/js-fr.yml
  38. 98
      config/locales/crowdin/js-tr.yml
  39. 3
      config/locales/crowdin/ko.yml
  40. 3
      config/locales/crowdin/lol.yml
  41. 3
      config/locales/crowdin/lt.yml
  42. 3
      config/locales/crowdin/lv.yml
  43. 3
      config/locales/crowdin/ne.yml
  44. 3
      config/locales/crowdin/nl.yml
  45. 3
      config/locales/crowdin/no.yml
  46. 3
      config/locales/crowdin/pl.yml
  47. 3
      config/locales/crowdin/pt.yml
  48. 3
      config/locales/crowdin/ro.yml
  49. 3
      config/locales/crowdin/ru.yml
  50. 3
      config/locales/crowdin/rw.yml
  51. 3
      config/locales/crowdin/si.yml
  52. 3
      config/locales/crowdin/sk.yml
  53. 3
      config/locales/crowdin/sl.yml
  54. 7
      config/locales/crowdin/sv.yml
  55. 3
      config/locales/crowdin/th.yml
  56. 35
      config/locales/crowdin/tr.yml
  57. 3
      config/locales/crowdin/uk.yml
  58. 3
      config/locales/crowdin/vi.yml
  59. 3
      config/locales/crowdin/zh-TW.yml
  60. 3
      config/locales/en.yml
  61. 34
      docs/api/apiv3/components/schemas/storage_file_upload_link_model.yml
  62. 20
      docs/api/apiv3/components/schemas/storage_file_upload_preparation_model.yml
  63. 2
      docs/api/apiv3/components/schemas/time_entry_create_form.yml
  64. 2
      docs/api/apiv3/components/schemas/time_entry_update_form.yml
  65. 2
      docs/api/apiv3/components/schemas/unlock_user.yml
  66. 2
      docs/api/apiv3/components/schemas/update_group.yml
  67. 2
      docs/api/apiv3/components/schemas/update_user.yml
  68. 16
      docs/api/apiv3/openapi-spec.yml
  69. 10
      docs/api/apiv3/paths/storage.yml
  70. 71
      docs/api/apiv3/paths/storage_files_prepare_upload.yml
  71. 6
      docs/use-cases/README.md
  72. 69
      docs/use-cases/portfolio-management/README.md
  73. BIN
      docs/use-cases/portfolio-management/Wiki.png
  74. BIN
      docs/use-cases/portfolio-management/chose-project.jpg
  75. BIN
      docs/use-cases/portfolio-management/custom-reports.jpg
  76. BIN
      docs/use-cases/portfolio-management/dynamic-data.jpg
  77. BIN
      docs/use-cases/portfolio-management/export_options.png
  78. BIN
      docs/use-cases/portfolio-management/gantt_view.png
  79. BIN
      docs/use-cases/portfolio-management/open_as_gantt_view.png
  80. BIN
      docs/use-cases/portfolio-management/openproject_export.png
  81. BIN
      docs/use-cases/portfolio-management/openproject_filter_projects.png
  82. BIN
      docs/use-cases/portfolio-management/openproject_projects_overview.png
  83. BIN
      docs/use-cases/portfolio-management/openproject_select_projects_list.png
  84. BIN
      docs/use-cases/portfolio-management/openproject_settings_for_project_overview_list.png
  85. BIN
      docs/use-cases/portfolio-management/openproject_wiki_editing.png
  86. BIN
      docs/use-cases/portfolio-management/openrpoject_configure_projects_overview.png
  87. BIN
      docs/use-cases/portfolio-management/sort_by_status.png
  88. 36
      docs/use-cases/resource-management/README.md
  89. BIN
      docs/use-cases/resource-management/configure_wp_view.png
  90. BIN
      docs/use-cases/resource-management/openproject_display_sums.png
  91. BIN
      docs/use-cases/resource-management/openproject_save_wp_adjusted_view.png
  92. BIN
      docs/use-cases/resource-management/openproject_work_packages_sum.png
  93. BIN
      docs/use-cases/resource-management/openproject_wp_gantt_view.png
  94. 12
      frontend/package-lock.json
  95. 18
      frontend/src/app/core/file-upload/op-direct-file-upload.service.ts
  96. 44
      frontend/src/app/core/file-upload/op-file-upload.service.ts
  97. 2
      frontend/src/app/core/state/attachments/attachments.service.ts
  98. 7
      frontend/src/app/core/state/days/day.service.ts
  99. 16
      frontend/src/app/core/state/file-links/file-links.service.ts
  100. 10
      frontend/src/app/core/state/in-app-notifications/in-app-notifications.service.ts
  101. Some files were not shown because too many files have changed in this diff Show More

@ -92,7 +92,7 @@ gem 'escape_utils', '~> 1.3'
# Syntax highlighting used in html-pipeline with rouge
gem 'rouge', '~> 4.0.0'
# HTML sanitization used for html-pipeline
gem 'sanitize', '~> 6.0.0'
gem 'sanitize', '~> 6.0.1'
# HTML autolinking for mails and urls (replaces autolink)
gem 'rinku', '~> 2.0.4'
# Version parsing with semver

@ -188,34 +188,34 @@ GEM
remote: https://rubygems.org/
specs:
Ascii85 (1.1.0)
actioncable (7.0.4.1)
actionpack (= 7.0.4.1)
activesupport (= 7.0.4.1)
actioncable (7.0.4.2)
actionpack (= 7.0.4.2)
activesupport (= 7.0.4.2)
nio4r (~> 2.0)
websocket-driver (>= 0.6.1)
actionmailbox (7.0.4.1)
actionpack (= 7.0.4.1)
activejob (= 7.0.4.1)
activerecord (= 7.0.4.1)
activestorage (= 7.0.4.1)
activesupport (= 7.0.4.1)
actionmailbox (7.0.4.2)
actionpack (= 7.0.4.2)
activejob (= 7.0.4.2)
activerecord (= 7.0.4.2)
activestorage (= 7.0.4.2)
activesupport (= 7.0.4.2)
mail (>= 2.7.1)
net-imap
net-pop
net-smtp
actionmailer (7.0.4.1)
actionpack (= 7.0.4.1)
actionview (= 7.0.4.1)
activejob (= 7.0.4.1)
activesupport (= 7.0.4.1)
actionmailer (7.0.4.2)
actionpack (= 7.0.4.2)
actionview (= 7.0.4.2)
activejob (= 7.0.4.2)
activesupport (= 7.0.4.2)
mail (~> 2.5, >= 2.5.4)
net-imap
net-pop
net-smtp
rails-dom-testing (~> 2.0)
actionpack (7.0.4.1)
actionview (= 7.0.4.1)
activesupport (= 7.0.4.1)
actionpack (7.0.4.2)
actionview (= 7.0.4.2)
activesupport (= 7.0.4.2)
rack (~> 2.0, >= 2.2.0)
rack-test (>= 0.6.3)
rails-dom-testing (~> 2.0)
@ -223,31 +223,31 @@ GEM
actionpack-xml_parser (2.0.1)
actionpack (>= 5.0)
railties (>= 5.0)
actiontext (7.0.4.1)
actionpack (= 7.0.4.1)
activerecord (= 7.0.4.1)
activestorage (= 7.0.4.1)
activesupport (= 7.0.4.1)
actiontext (7.0.4.2)
actionpack (= 7.0.4.2)
activerecord (= 7.0.4.2)
activestorage (= 7.0.4.2)
activesupport (= 7.0.4.2)
globalid (>= 0.6.0)
nokogiri (>= 1.8.5)
actionview (7.0.4.1)
activesupport (= 7.0.4.1)
actionview (7.0.4.2)
activesupport (= 7.0.4.2)
builder (~> 3.1)
erubi (~> 1.4)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.1, >= 1.2.0)
activejob (7.0.4.1)
activesupport (= 7.0.4.1)
activejob (7.0.4.2)
activesupport (= 7.0.4.2)
globalid (>= 0.3.6)
activemodel (7.0.4.1)
activesupport (= 7.0.4.1)
activemodel (7.0.4.2)
activesupport (= 7.0.4.2)
activemodel-serializers-xml (1.0.2)
activemodel (> 5.x)
activesupport (> 5.x)
builder (~> 3.1)
activerecord (7.0.4.1)
activemodel (= 7.0.4.1)
activesupport (= 7.0.4.1)
activerecord (7.0.4.2)
activemodel (= 7.0.4.2)
activesupport (= 7.0.4.2)
activerecord-import (1.4.1)
activerecord (>= 4.2)
activerecord-nulldb-adapter (0.8.0)
@ -258,14 +258,14 @@ GEM
multi_json (~> 1.11, >= 1.11.2)
rack (>= 2.0.8, < 3)
railties (>= 5.2.4.1)
activestorage (7.0.4.1)
actionpack (= 7.0.4.1)
activejob (= 7.0.4.1)
activerecord (= 7.0.4.1)
activesupport (= 7.0.4.1)
activestorage (7.0.4.2)
actionpack (= 7.0.4.2)
activejob (= 7.0.4.2)
activerecord (= 7.0.4.2)
activesupport (= 7.0.4.2)
marcel (~> 1.0)
mini_mime (>= 1.1.0)
activesupport (7.0.4.1)
activesupport (7.0.4.2)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 1.6, < 2)
minitest (>= 5.1)
@ -361,7 +361,7 @@ GEM
commonmarker (0.23.7)
compare-xml (0.66)
nokogiri (~> 1.8)
concurrent-ruby (1.1.10)
concurrent-ruby (1.2.0)
cookiejar (0.3.3)
cork (0.3.0)
colored2 (~> 3.1)
@ -494,7 +494,7 @@ GEM
fastimage (2.2.6)
ffi (1.15.5)
flamegraph (0.9.5)
fog-aws (3.15.0)
fog-aws (3.16.0)
fog-core (~> 2.1)
fog-json (~> 1.1)
fog-xml (~> 0.1)
@ -758,20 +758,20 @@ GEM
rack_session_access (0.2.0)
builder (>= 2.0.0)
rack (>= 1.0.0)
rails (7.0.4.1)
actioncable (= 7.0.4.1)
actionmailbox (= 7.0.4.1)
actionmailer (= 7.0.4.1)
actionpack (= 7.0.4.1)
actiontext (= 7.0.4.1)
actionview (= 7.0.4.1)
activejob (= 7.0.4.1)
activemodel (= 7.0.4.1)
activerecord (= 7.0.4.1)
activestorage (= 7.0.4.1)
activesupport (= 7.0.4.1)
rails (7.0.4.2)
actioncable (= 7.0.4.2)
actionmailbox (= 7.0.4.2)
actionmailer (= 7.0.4.2)
actionpack (= 7.0.4.2)
actiontext (= 7.0.4.2)
actionview (= 7.0.4.2)
activejob (= 7.0.4.2)
activemodel (= 7.0.4.2)
activerecord (= 7.0.4.2)
activestorage (= 7.0.4.2)
activesupport (= 7.0.4.2)
bundler (>= 1.15.0)
railties (= 7.0.4.1)
railties (= 7.0.4.2)
rails-controller-testing (1.0.5)
actionpack (>= 5.0.1.rc1)
actionview (>= 5.0.1.rc1)
@ -784,9 +784,9 @@ GEM
rails-i18n (7.0.6)
i18n (>= 0.7, < 2)
railties (>= 6.0.0, < 8)
railties (7.0.4.1)
actionpack (= 7.0.4.1)
activesupport (= 7.0.4.1)
railties (7.0.4.2)
actionpack (= 7.0.4.2)
activesupport (= 7.0.4.2)
method_source
rake (>= 12.2)
thor (~> 1.0)
@ -886,7 +886,7 @@ GEM
rubytree (2.0.0)
json (~> 2.0, > 2.3.1)
rubyzip (2.3.2)
sanitize (6.0.0)
sanitize (6.0.1)
crass (~> 1.0.2)
nokogiri (>= 1.12.0)
sassc (2.4.0)
@ -1138,7 +1138,7 @@ DEPENDENCIES
ruby-prof
ruby-progressbar (~> 1.11.0)
rubytree (~> 2.0.0)
sanitize (~> 6.0.0)
sanitize (~> 6.0.1)
sassc-rails
secure_headers (~> 6.5.0)
selenium-webdriver (~> 4.0)

@ -120,7 +120,7 @@ class WorkPackage < ApplicationRecord
where(author_id: author.id)
}
scopes :covering_days_of_week,
scopes :covering_dates_and_days_of_week,
:for_scheduling,
:include_derived_dates,
:include_spent_time,

@ -26,27 +26,29 @@
# See COPYRIGHT and LICENSE files for more details.
#++
module WorkPackages::Scopes::CoveringDaysOfWeek
module WorkPackages::Scopes::CoveringDatesAndDaysOfWeek
extend ActiveSupport::Concern
using CoreExtensions::SquishSql
class_methods do
# Fetches all work packages that cover specific days of the week.
# Fetches all work packages that cover specific days of the week, and/or specific dates.
#
# The period considered is from the work package start date to the due date.
#
# @param dates Date[] An array of the Date objects.
# @param days_of_week number[] An array of the ISO days of the week to
# consider. 1 is Monday, 7 is Sunday.
def covering_days_of_week(days_of_week)
def covering_dates_and_days_of_week(days_of_week: [], dates: [])
days_of_week = Array(days_of_week)
return none if days_of_week.empty?
dates = Array(dates)
return none if days_of_week.empty? && dates.empty?
where("id IN (#{query(days_of_week)})")
where("id IN (#{query(days_of_week, dates)})")
end
private
def query(days_of_week)
def query(days_of_week, dates)
sql = <<~SQL.squish
-- select work packages dates with their followers dates
WITH work_packages_with_dates AS (
@ -59,7 +61,6 @@ module WorkPackages::Scopes::CoveringDaysOfWeek
work_packages.start_date IS NOT NULL
OR work_packages.due_date IS NOT NULL
)
ORDER BY work_packages.id
),
-- coalesce non-existing dates of work package to get period start/end
work_packages_periods AS (
@ -68,29 +69,29 @@ module WorkPackages::Scopes::CoveringDaysOfWeek
GREATEST(work_package_start_date, work_package_due_date) AS end_date
FROM work_packages_with_dates
),
-- expand period into days of the week. Limit to 7 days (more would be useless).
work_packages_days_of_week AS (
SELECT id,
extract(
isodow
from generate_series(
work_packages_periods.start_date,
LEAST(
work_packages_periods.start_date + 6,
work_packages_periods.end_date
),
'1 day'
)
) AS dow
FROM work_packages_periods
-- All days between the start date of a work package and its due date
covered_dates AS (
SELECT
id,
generate_series(work_packages_periods.start_date,
work_packages_periods.end_date,
'1 day') AS date
FROM work_packages_periods
),
-- All days between the start date of a work package and its due date including the day of the week for each date
covered_dates_and_wday AS (
SELECT
id,
date,
EXTRACT(isodow FROM date) dow
FROM covered_dates
)
-- select id of work packages covering the given days
SELECT DISTINCT id
FROM work_packages_days_of_week
WHERE dow IN (:days_of_week)
SELECT id FROM covered_dates_and_wday
WHERE dow IN (:days_of_week) OR date IN (:dates)
SQL
sanitize_sql([sql, { days_of_week: }])
sanitize_sql([sql, { days_of_week:, dates: }])
end
end
end

@ -32,13 +32,6 @@ class Settings::UpdateService < BaseServices::BaseContracted
contract_class: Settings::UpdateContract
end
def after_validate(params, call)
params.keys.each(&method(:remember_previous_value))
call
end
# We will have a problem with error handling on the form.
# How can we still display the user changed values in case the form is not successfully saved?
def persist(call)
params.each do |name, value|
set_setting_value(name, value)
@ -46,34 +39,12 @@ class Settings::UpdateService < BaseServices::BaseContracted
call
end
def after_perform(call)
super.tap do
params.each_key do |name|
run_on_change_callback(name)
end
end
end
private
def remember_previous_value(name)
previous_values[name] = Setting[name]
end
def set_setting_value(name, value)
Setting[name] = derive_value(value)
end
def previous_values
@previous_values ||= {}
end
def run_on_change_callback(name)
if (definition = Settings::Definition[name]) && definition.on_change
definition.on_change.call(previous_values[name])
end
end
def derive_value(value)
case value
when Array, Hash

@ -30,6 +30,8 @@ class Settings::WorkingDaysUpdateService < Settings::UpdateService
def call(params)
params = params.to_h.deep_symbolize_keys
self.non_working_days_params = params.delete(:non_working_days) || []
self.previous_working_days = Setting[:working_days]
self.previous_non_working_days = NonWorkingDay.pluck(:date)
super
end
@ -54,9 +56,19 @@ class Settings::WorkingDaysUpdateService < Settings::UpdateService
results
end
def after_perform(call)
super.tap do
WorkPackages::ApplyWorkingDaysChangeJob.perform_later(
user_id: User.current.id,
previous_working_days:,
previous_non_working_days:
)
end
end
private
attr_accessor :non_working_days_params
attr_accessor :non_working_days_params, :previous_working_days, :previous_non_working_days
def persist_non_working_days
# We don't support update for now

@ -30,18 +30,19 @@ class WorkPackages::ApplyWorkingDaysChangeJob < ApplicationJob
queue_with_priority :above_normal
include ::ScheduledJob
def perform(user_id:, previous_working_days:)
def perform(user_id:, previous_working_days:, previous_non_working_days:)
user = User.find(user_id)
User.execute_as user do
updated_work_package_ids = collect_id_for_each(applicable_work_package(previous_working_days)) do |work_package|
updated_work_package_ids = collect_id_for_each(applicable_work_package(previous_working_days,
previous_non_working_days)) do |work_package|
apply_change_to_work_package(user, work_package)
end
updated_work_package_ids += collect_id_for_each(applicable_predecessor(updated_work_package_ids)) do |predecessor|
apply_change_to_predecessor(user, predecessor)
end
set_journal_notice(updated_work_package_ids, previous_working_days)
set_journal_notice(updated_work_package_ids, previous_working_days, previous_non_working_days)
end
end
@ -68,11 +69,11 @@ class WorkPackages::ApplyWorkingDaysChangeJob < ApplicationJob
end
end
def applicable_work_package(previous_working_days)
changed_days = changed_days(previous_working_days)
def applicable_work_package(previous_working_days, previous_non_working_days)
days_of_week = changed_days(previous_working_days).keys
dates = changed_non_working_dates(previous_non_working_days).keys
WorkPackage
.covering_days_of_week(changed_days)
.covering_dates_and_days_of_week(days_of_week:, dates:)
.order(WorkPackage.arel_table[:start_date].asc.nulls_first,
WorkPackage.arel_table[:due_date].asc)
end
@ -83,7 +84,16 @@ class WorkPackages::ApplyWorkingDaysChangeJob < ApplicationJob
# `^` is a Set method returning a new set containing elements exclusive to
# each other
(previous ^ current).to_a
(previous ^ current).index_with { |day| current.include?(day) }
end
def changed_non_working_dates(previous_non_working_days)
previous = Set.new(previous_non_working_days)
current = Set.new(NonWorkingDay.pluck(:date))
# `^` is a Set method returning a new set containing elements exclusive to
# each other
(previous ^ current).index_with { |day| current.exclude?(day) }
end
def applicable_predecessor(excluded)
@ -92,9 +102,10 @@ class WorkPackages::ApplyWorkingDaysChangeJob < ApplicationJob
.where.not(id: excluded)
end
def set_journal_notice(updated_work_package_ids, previous_working_days)
day_changes = changed_days(previous_working_days).index_with { |day| Setting.working_days.include?(day) }
journal_note = journal_notice_text(day_changes)
def set_journal_notice(updated_work_package_ids, previous_working_days, previous_non_working_days)
day_changes = changed_days(previous_working_days)
date_changes = changed_non_working_dates(previous_non_working_days)
journal_note = journal_notice_text(day_changes, date_changes)
WorkPackage
.where(id: updated_work_package_ids.uniq)
@ -105,10 +116,12 @@ class WorkPackages::ApplyWorkingDaysChangeJob < ApplicationJob
end
end
def journal_notice_text(day_changes)
def journal_notice_text(day_changes, date_changes)
I18n.with_locale(Setting.default_language) do
day_changes_messages = day_changes.collect { |day, working| working_day_change_message(day, working) }
date_changes_messages = date_changes.collect { |date, working| working_date_change_message(date, working) }
I18n.t(:'working_days.journal_note.changed',
changes: day_changes.collect { |day, working| working_day_change_message(day, working) }.join(', '))
changes: (day_changes_messages + date_changes_messages).join(', '))
end
end
@ -117,6 +130,10 @@ class WorkPackages::ApplyWorkingDaysChangeJob < ApplicationJob
day: WeekDay.find_by!(day:).name)
end
def working_date_change_message(date, working)
I18n.t(:"working_days.journal_note.dates.#{working ? :working : :non_working}", date:)
end
def collect_id_for_each(scope)
scope.pluck(:id).map do |id|
yield(WorkPackage.find(id)).pluck(:id)

@ -33,8 +33,7 @@ module Settings
attr_accessor :name,
:format,
:env_alias,
:on_change
:env_alias
attr_writer :value,
:allowed
@ -44,8 +43,7 @@ module Settings
format: nil,
writable: true,
allowed: nil,
env_alias: nil,
on_change: nil)
env_alias: nil)
self.name = name.to_s
@default = default.is_a?(Hash) ? default.deep_stringify_keys : default
@default.freeze
@ -54,7 +52,6 @@ module Settings
self.writable = writable
self.allowed = allowed
self.env_alias = env_alias
self.on_change = on_change
end
def default
@ -136,14 +133,12 @@ module Settings
# @param [nil] env_alias Alternative for the default env name to also look up. E.g. with the alias set to
# `OPENPROJECT_2FA` for a definition with the name `two_factor_authentication`, the value is fetched
# from the ENV OPENPROJECT_2FA as well.
# @param [nil] on_change A callback lambda to be triggered whenever the setting is stored to the database.
def add(name,
default:,
format: nil,
writable: true,
allowed: nil,
env_alias: nil,
on_change: nil)
env_alias: nil)
return if @by_name.present? && @by_name[name.to_s].present?
@by_name = nil
@ -153,8 +148,7 @@ module Settings
default:,
writable:,
allowed:,
env_alias:,
on_change:)
env_alias:)
override_value(definition)

@ -938,10 +938,7 @@ Settings::Definition.define do
add :working_days,
format: :array,
allowed: Array(1..7),
default: Array(1..5), # Sat, Sun being non-working days
on_change: ->(previous_working_days) do
WorkPackages::ApplyWorkingDaysChangeJob.perform_later(user_id: User.current.id, previous_working_days:)
end
default: Array(1..5) # Sat, Sun being non-working days
add :youtube_channel,
default: 'https://www.youtube.com/c/OpenProjectCommunity',

@ -2966,6 +2966,9 @@ af:
days:
working: "%{day} is now working"
non_working: "%{day} is now non-working"
dates:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
nothing_to_preview: "Niks om te voorskou"
api_v3:
attributes:

@ -3043,6 +3043,9 @@ ar:
days:
working: "%{day} is now working"
non_working: "%{day} is now non-working"
dates:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
nothing_to_preview: "لا شيء للمعاينة"
api_v3:
attributes:

@ -2966,6 +2966,9 @@ az:
days:
working: "%{day} is now working"
non_working: "%{day} is now non-working"
dates:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
nothing_to_preview: "Nothing to preview"
api_v3:
attributes:

@ -3008,6 +3008,9 @@ be:
days:
working: "%{day} is now working"
non_working: "%{day} is now non-working"
dates:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
nothing_to_preview: "Nothing to preview"
api_v3:
attributes:

@ -2966,6 +2966,9 @@ bg:
days:
working: "%{day} is now working"
non_working: "%{day} is now non-working"
dates:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
nothing_to_preview: "Nothing to preview"
api_v3:
attributes:

@ -2955,6 +2955,9 @@ ca:
days:
working: "%{day} és ara laboral"
non_working: "%{day} és ara no laboral"
dates:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
nothing_to_preview: "Res per previsualitzar"
api_v3:
attributes:

@ -2966,6 +2966,9 @@ ckb-IR:
days:
working: "%{day} is now working"
non_working: "%{day} is now non-working"
dates:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
nothing_to_preview: "Nothing to preview"
api_v3:
attributes:

@ -3006,6 +3006,9 @@ cs:
days:
working: "%{day} is now working"
non_working: "%{day} is now non-working"
dates:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
nothing_to_preview: "Nic pro náhled"
api_v3:
attributes:

@ -2962,6 +2962,9 @@ da:
days:
working: "%{day} is now working"
non_working: "%{day} is now non-working"
dates:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
nothing_to_preview: "Intet at forhåndsvise"
api_v3:
attributes:

@ -2960,6 +2960,9 @@ de:
days:
working: "%{day} ist jetzt ein Arbeitstag"
non_working: "%{day} ist jetzt kein Arbeitstag"
dates:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
nothing_to_preview: "Keine Vorschau verfügbar"
api_v3:
attributes:

@ -2960,6 +2960,9 @@ el:
days:
working: "%{day} is now working"
non_working: "%{day} is now non-working"
dates:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
nothing_to_preview: "Δεν υπάρχει κάτι για προεπισκόπηση"
api_v3:
attributes:

@ -2966,6 +2966,9 @@ eo:
days:
working: "%{day} is now working"
non_working: "%{day} is now non-working"
dates:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
nothing_to_preview: "Nothing to preview"
api_v3:
attributes:

@ -49,7 +49,7 @@ es:
main-menu-border-color: "Borde del menú principal"
custom_colors: "Colores personalizados"
customize: "Personalice su instalación de OpenProject con su logotipo y colores."
enterprise_notice: "As a special 'Thank you!' for their financial contribution to develop OpenProject, this tiny add-on is only available for Enterprise edition support subscribers."
enterprise_notice: "Como un agradecimiento especial por su contribución financiera para desarrollar OpenProject, este pequeño complemento solo está disponible para suscriptores de la edición Enterprise."
enterprise_more_info: "Nota: el logotipo utilizado será de acceso público."
manage_colors: "Editar opciones de selección de colores"
instructions:
@ -67,12 +67,12 @@ es:
upgrade_to_ee: "Actualizar a la edición Enterprise"
add_token: "Cargue el token de soporte de la edición Enterprise"
delete_token_modal:
text: "Are you sure you want to remove the current Enterprise edition token used?"
text: "¿Está seguro que desea eliminar el token actual de la edición Enterpise usado?"
title: "Eliminar token"
replace_token: "Reemplace su token de apoyo actual"
order: "Solicitar la edición Enterprise on-premises"
paste: "Pegue su token de soporte de la edición Enterprise"
required_for_feature: "This add-on is only available with an active Enterprise edition support token."
required_for_feature: "Este add-on solo está disponible con un token de soporte activo de la edición Enterprise."
enterprise_link: "Para obtener más información, haga clic aquí."
start_trial: 'Iniciar prueba gratuita'
book_now: 'Reservar ahora'
@ -80,7 +80,7 @@ es:
buttons:
upgrade: "Actualizar ahora"
contact: "Contáctenos para una demostración"
enterprise_info_html: "is an Enterprise <span class='spot-icon spot-icon_enterprise-addons'></span> add-on."
enterprise_info_html: "es un add-on de la edición Enterprise <span class='spot-icon spot-icon_enterprise-badge'></span>."
upgrade_info: "Actualice a un plan de pago para activarlo y empezar a usarlo en su equipo."
journal_aggregation:
explanation:
@ -319,7 +319,7 @@ es:
settings: "Configuración"
form_configuration: "Configuración del formulario"
more_info_text_html: >
Enterprise edition allows you to customize form configuration with these additional add-ons: <br> <ul class="%{list_styling_class}"> <li><b>Add new attribute groups</b></li> <li><b>Rename attribute groups</b></li> <li><b>Add a table of related work packages</b></li> </ul>
La edición Enterprise te permite personalizar el formulario de configuración con estos add-ons adicionales: <br><ul class="%{list_styling_class}"><li><b>Añade nuevos grupos de atributo</b></li> <li><b>Renombra grupos de atributo</b></li> <li><b>Añada tablas de paquetes de trabajo relacionados</b></li> </ul>
projects: "Proyectos"
enabled_projects: "Proyectos habilitados"
edit_query: "Editar tabla"
@ -373,7 +373,7 @@ es:
account:
delete: "Borrar cuenta"
delete_confirmation: "¿Está seguro que desea eliminar la cuenta?"
deletion_pending: "Account has been locked and was scheduled for deletion. Note that this process takes place in the background. It might take a few moments until the user is fully deleted."
deletion_pending: "La cuenta ha sido bloqueada y está programada para su eliminación. Tenga en cuenta que este proceso tiene lugar en segundo plano. Puede tardar un tiempo hasta que el usuario se borre por completo."
deletion_info:
data_consequences:
other: "De los datos del usuario creado (por ejemplo correo electrónico, preferencias, paquetes de trabajo, entradas wiki) serán eliminados, en la medida de lo posible. Sin embargo, tenga en cuenta que no se pueden eliminar datos como entradas wiki y paquetes de trabajo sin obstaculizar el trabajo de los demás usuarios. Dichos datos, por lo tanto, serán reasignados a una cuenta denominada \"Usuarios Eliminados\". Como los datos de cada cuenta borrada son reasignados al eliminarla, no será posible distinguir los datos del usuario creado a partir de los datos de otra cuenta eliminada."
@ -585,7 +585,7 @@ es:
confirmation: "no coincide con %{attribute}."
could_not_be_copied: "%{dependency} no se pudo copiar (en su totalidad)."
does_not_exist: "no existe."
error_enterprise_only: "%{action} is only available in the OpenProject Enterprise edition"
error_enterprise_only: "%{action} solo está disponible en OpenProject edición Enterprise"
error_unauthorized: "no se puede acceder."
error_readonly: "se intentó escribir pero no se puede escribir."
email: "no es una dirección de correo válida."
@ -635,7 +635,7 @@ es:
auth_source:
attributes:
tls_certificate_string:
invalid_certificate: "The provided SSL certificate is invalid: %{additional_message}"
invalid_certificate: "El certificado SSL proporcionado no es válido: %{additional_message}"
format: "%{message}"
attachment:
attributes:
@ -690,7 +690,7 @@ es:
non_working_day:
attributes:
date:
taken: "A non-working day already exists for %{value}."
taken: "Ya existe un día no laboral para %{value}."
format: "%{message}"
parse_schema_filter_params_service:
attributes:
@ -703,7 +703,7 @@ es:
foreign_wps_reference_version: 'Los paquetes de trabajo en los proyectos no descendientes hacen referencia a versiones del proyecto o a sus descendientes.'
attributes:
base:
archive_permission_missing_on_subprojects: "You do not have the permissions required to archive all sub-projects. Please contact an administrator."
archive_permission_missing_on_subprojects: "No tiene los permisos necesarios para archivar todos los subproyectos. Por favor, póngase en contacto con un administrador."
types:
in_use_by_work_packages: "todavia en uso por los paquetes de trabajo: %{types}"
enabled_modules:
@ -1268,11 +1268,11 @@ es:
ee:
upsale:
form_configuration:
description: "Customize the form configuration with these additional add-ons:"
description: "Personalice la configuración del formulario con estos add-ons extra:"
add_groups: "Añadir nuevos grupos de atributos"
rename_groups: "Cambiar nombre de grupos de atributos"
project_filters:
description_html: "Filtering and sorting on custom fields is an Enterprise edition add-on."
description_html: "Filtrar y ordenar en campos personalizados es un add-on de la edición Enterprise."
enumeration_activities: "Actividades de seguimiento del tiempo"
enumeration_work_package_priorities: "Prioridades del paquete de trabajo"
enumeration_reported_project_statuses: "Estatus del proyecto reportado"
@ -1294,7 +1294,7 @@ es:
error_cookie_missing: 'No se encuentra la cookie de OpenProject. Por favor asegúrese de que las cookies están habilitadas, ya que sin ellas esta aplicación no funcionará correctamente.'
error_custom_option_not_found: "Esta opción no existe."
error_enterprise_activation_user_limit: "Su cuenta no puede ser activada (se alcanzó el límite del usuario). Por favor, contacte su administrador para obtener acceso."
error_enterprise_token_invalid_domain: "The Enterprise edition is not active. Your Enterprise token's domain (%{actual}) does not match the system's host name (%{expected})."
error_enterprise_token_invalid_domain: "La edición Enterprise no está activa. Su dominio del token de Enterprise (%{actual}) no coincide con el nombre de host del sistema (%{expected})."
error_failed_to_delete_entry: 'No se puede eliminar esta entrada.'
error_in_dependent: "Error al intentar alterar el objeto dependiente: %{dependent_class} #%{related_id} - %{related_subject}: %{error}" #%{related_id} - %{related_subject}: %{error}"
error_in_new_dependent: "Error al crear el objeto dependiente: %{dependent_class} - %{related_subject}: %{error}"
@ -1794,7 +1794,7 @@ es:
label_product_version: "Versión del producto"
label_professional_support: "Soporte profesional"
label_profile: "Perfil"
label_project_activity: "Project activity"
label_project_activity: "Actividad del proyecto"
label_project_attribute_plural: "Atributos del proyecto"
label_project_count: "Número total de proyectos"
label_project_copy_notifications: "Enviar notificaciones por correo electrónico durante la copia del proyecto"
@ -2217,7 +2217,7 @@ es:
permission_add_work_packages: "Añadir paquetes de trabajo"
permission_add_messages: "Publicar mensajes"
permission_add_project: "Crear proyecto"
permission_archive_project: "Archive project"
permission_archive_project: "Archivar proyecto"
permission_manage_user: "Crear y editar usuarios"
permission_manage_placeholder_user: "Crear, editar y eliminar usuarios de marcador de posición"
permission_add_subprojects: "Crear subproyectos"
@ -2961,6 +2961,9 @@ es:
days:
working: "%{day} es ahora laboral"
non_working: "%{day} es ahora no laboral"
dates:
working: "%{day} es ahora laboral"
non_working: "%{day} es ahora no laboral"
nothing_to_preview: "Nada para previsualizar"
api_v3:
attributes:

@ -2966,6 +2966,9 @@ et:
days:
working: "%{day} is now working"
non_working: "%{day} is now non-working"
dates:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
nothing_to_preview: "Eelvaateks pole midagi näidata"
api_v3:
attributes:

@ -2966,6 +2966,9 @@ eu:
days:
working: "%{day} is now working"
non_working: "%{day} is now non-working"
dates:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
nothing_to_preview: "Nothing to preview"
api_v3:
attributes:

@ -2966,6 +2966,9 @@ fa:
days:
working: "%{day} is now working"
non_working: "%{day} is now non-working"
dates:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
nothing_to_preview: "Nothing to preview"
api_v3:
attributes:

@ -2966,6 +2966,9 @@ fi:
days:
working: "%{day} is now working"
non_working: "%{day} is now non-working"
dates:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
nothing_to_preview: "Ei esikatseltavaa"
api_v3:
attributes:

@ -2964,6 +2964,9 @@ fil:
days:
working: "%{day} is now working"
non_working: "%{day} is now non-working"
dates:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
nothing_to_preview: "Walang mai-preview"
api_v3:
attributes:

@ -337,7 +337,7 @@ fr:
wiki:
page_not_editable_index: La page demandée n'existe pas (encore). Vous avez été redirigé vers l'index de toutes les pages du wiki.
no_results_title_text: Il n'y a actuellement aucune page wiki.
print_hint: This will print the content of this wiki page without any navigation bars.
print_hint: Ceci affichera le contenu de cette page wiki sans aucune barre de navigation.
index:
no_results_content_text: Ajouter une nouvelle page wiki
work_flows:
@ -2965,6 +2965,9 @@ fr:
days:
working: "%{day} est maintenant un jour ouvrable"
non_working: "%{day} est maintenant un jour non ouvrable"
dates:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
nothing_to_preview: "Rien à afficher en apperçu"
api_v3:
attributes:

@ -3008,6 +3008,9 @@ he:
days:
working: "%{day} is now working"
non_working: "%{day} is now non-working"
dates:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
nothing_to_preview: "Nothing to preview"
api_v3:
attributes:

@ -2964,6 +2964,9 @@ hi:
days:
working: "%{day} is now working"
non_working: "%{day} is now non-working"
dates:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
nothing_to_preview: "Nothing to preview"
api_v3:
attributes:

@ -2987,6 +2987,9 @@ hr:
days:
working: "%{day} is now working"
non_working: "%{day} is now non-working"
dates:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
nothing_to_preview: "Ne postoji zapis za pregled"
api_v3:
attributes:

@ -2962,6 +2962,9 @@ hu:
days:
working: "%{day} is now working"
non_working: "%{day} is now non-working"
dates:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
nothing_to_preview: "Nincs előnézet"
api_v3:
attributes:

@ -2937,6 +2937,9 @@ id:
days:
working: "%{day} is now working"
non_working: "%{day} is now non-working"
dates:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
nothing_to_preview: "Tidak ada pre-view"
api_v3:
attributes:

@ -2963,6 +2963,9 @@ it:
days:
working: "%{day} ora è lavorativo"
non_working: "%{day} ora non è lavorativo"
dates:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
nothing_to_preview: "Niente in anteprima"
api_v3:
attributes:

@ -2940,6 +2940,9 @@ ja:
days:
working: "%{day} is now working"
non_working: "%{day} is now non-working"
dates:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
nothing_to_preview: "プレビューできるものは何もありません。"
api_v3:
attributes:

@ -478,7 +478,7 @@ es:
label_drop_files: "Arrastra archivos aquí para adjuntarlos."
label_drop_or_click_files: "Arrastra los archivos o haz clic aquí para adjuntar archivos."
label_drop_folders_hint: No se pueden cargar carpetas como archivos adjuntos. Seleccione archivos individuales.
label_add_attachments: "Attach files"
label_add_attachments: "Adjuntar archivos"
label_formattable_attachment_hint: "Para adjuntar y vincular archivos, colóquelos en este campo o péguelos desde el portapapeles."
label_remove_file: "Eliminar %{fileName}"
label_remove_watcher: "Eliminar observador %{name}"
@ -572,7 +572,7 @@ es:
one: 'y 1 más'
other: 'y %{count} más'
no_results:
at_all: 'New notifications will appear here when there is activity that concerns you.'
at_all: 'Aquí se mostrarán las nuevas notificaciones cuando haya actividad que le resulte pertinente.'
with_current_filter: 'No hay notificaciones en esta vista actualmente'
mark_all_read: 'Marcar todas como leídas'
mark_as_read: 'Marcar como leída'
@ -595,7 +595,7 @@ es:
watched: 'Observador'
date_alert: 'Alerta de fecha'
settings:
change_notification_settings: 'You can modify your <a target="_blank" href="%{url}">notification settings</a> to ensure you never miss an important update.'
change_notification_settings: 'Puede modificar su <a target="_blank" href="%{url}">configuración de notificaciones</a> para asegurarse que nunca se pierda una actualización importante.'
title: "Ajustes de notificación"
notify_me: "Notifícame"
reminders:
@ -657,7 +657,7 @@ es:
project:
required_outside_context: >
Seleccione el proyecto donde quiere crear el paquete de trabajo para ver todos los atributos. Solo puede seleccionar proyectos que tengan activado el tipo de paquete utilizado.
details_activity: 'Project details activity'
details_activity: 'Actividad de detalles del proyecto'
context: 'Contexto del proyecto'
work_package_belongs_to: 'Este paquete de trabajo pertenece al proyecto %{projectname}.'
click_to_switch_context: 'Abra este paquete de trabajo en ese proyecto.'

@ -478,7 +478,7 @@ fr:
label_drop_files: "Déposez des fichiers ici pour joindre des fichiers."
label_drop_or_click_files: "Déposez des fichiers ici ou cliquez pour joindre des fichiers."
label_drop_folders_hint: Vous ne pouvez pas télécharger les dossiers en pièce jointe. S’il vous plaît sélectionnez des fichiers seuls.
label_add_attachments: "Attach files"
label_add_attachments: "Joindre fichiers"
label_formattable_attachment_hint: "Insérer des fichiers en les glissant sur ce champ, ou en les collant depuis le presse-papiers."
label_remove_file: "Supprimer %{fileName}"
label_remove_watcher: "Retirer l'observateur %{name}"

@ -224,19 +224,19 @@ tr:
status_label: "Durum:"
status_confirmed: "onaylanmış"
status_waiting: "e-posta gönderildi - onay bekleniyor"
test_ee: "Test the Enterprise edition 14 days for free"
quick_overview: "Get a quick overview of project management and team collaboration with OpenProject Enterprise edition."
test_ee: "Enterprise Edition ürününü 14 gün ücretsiz test edin"
quick_overview: "OpenProject Enterprise sürümü ile proje yönetimi ve ekip işbirliğine hızlı bir genel bakış elde edin."
upsale:
become_hero: "Kahraman olun!"
enterprise_info_html: "%{feature_title} is an Enterprise <span class='spot-icon spot-icon_enterprise-addons'></span> add-on."
upgrade_info: "Please upgrade to a paid plan to activate and start using it in your team."
benefits:
description: "What are the benefits of the Enterprise on-premises edition?"
description: "Enterprise şirket içi sürümünün avantajları nelerdir?"
high_security: "Güvenlik özellikleri"
high_security_text: "Single sign on (SAML, OpenID Connect, CAS), LDAP groups."
installation: "Kurulum desteği"
installation_text: "Deneyimli yazılım mühendisleri, kendi altyapınızdaki eksiksiz kurulum ve kurulum sürecinde size rehberlik eder."
premium_features: "Enterprise add-ons"
premium_features: "Enterprise eklentiler"
premium_features_text: "Çevik tahtalar, özel tema ve logo, grafikler, özel eylemlerle akıllı iş akışları, iş paketi ekleri için tam metin araması ve çoklu seçim özel alanları."
professional_support: "Profesyonel destek"
professional_support_text: "İş açısından kritik ortamlarda OpenProject çalıştırma konusunda uzman bilgiye sahip kıdemli destek mühendislerinden güvenilir, yüksek dokunuşlu destek alın."
@ -249,9 +249,9 @@ tr:
link_quote: "Fiyat teklifi alın"
more_info: "Daha fazla bilgi"
text: >
The OpenProject Enterprise edition builds on top of the Community edition. It includes Enterprise add-ons and professional support mainly aimed at organizations with more than 10 users that manage business critical projects with OpenProject.
OpenProject Enterprise sürümü, Community sürümünün üzerine kuruludur. OpenProject ile iş açısından kritik projeleri yöneten 10'dan fazla kullanıcısı olan kuruluşlara yönelik Kurumsal eklentiler ve profesyonel destek içerir.
unlimited: "Sınırsız"
you_contribute: "Developers need to pay their bills, too. By upgrading to the Enterprise edition, you will be supporting this open source community effort and contributing to its development, maintenance and continuous improvement."
you_contribute: "Geliştiricilerin de faturalarını ödemeleri gerekiyor. Enterprise sürümüne yükselterek, bu açık kaynak topluluk çabasını destekleyecek ve geliştirilmesine, sürdürülmesine ve sürekli iyileştirilmesine katkıda bulunacaksınız."
custom_actions:
date:
specific: 'açık'
@ -280,7 +280,7 @@ tr:
one: "İlk sıralama ölçütü"
two: "İkinci sıralama ölçütü"
three: "Üçüncü sıralama ölçütleri"
upsale_for_more: "Advanced filters allow you to also filter for file names and content of work package attachments. Please upgrade to a paid plan to use this add-on."
upsale_for_more: "Gelişmiş filtreler, iş paketi eklerinin dosya adları ve içeriği için de filtre uygulamanıza olanak tanır. Bu eklentiyi kullanmak için lütfen ücretli bir plana yükseltin."
upsale_link: 'Enterprise sürümü'
general_text_no: "hayır"
general_text_yes: "evet"
@ -400,7 +400,7 @@ tr:
label_no_data: "Görüntülenecek veri yok"
label_no_due_date: "bitiş tarihi yok"
label_no_start_date: "başlangıç tarihi yok"
label_no_date: "no date"
label_no_date: "tarih yok"
label_no_value: "Değer yok"
label_none: "hiçbiri"
label_not_contains: "içermiyor"
@ -476,7 +476,7 @@ tr:
label_columns: "Sütunlar"
label_attachments: Ekler
label_drop_files: "Dosya eklemek için dosyaları buraya bırakın."
label_drop_or_click_files: "Drop files here or click to attach files."
label_drop_or_click_files: "Dosyaları buraya bırakın veya eklemek için tıklayın"
label_drop_folders_hint: Klasörleri ek olarak karşıya yükleyemezsiniz. Lütfen tekil dosyalar seçiniz.
label_add_attachments: "Dosyaları ekle"
label_formattable_attachment_hint: "Dosyaları bu alana sürükleyerek ekleyebilir veya panodan yapıştırabilirsiniz."
@ -549,31 +549,31 @@ tr:
commented: 'yorumlandı'
processed: 'işlem uygulandı'
prioritized: 'öncelik verildi'
dateAlert: 'Date alert'
dateAlert: 'Tarih uyarısı'
date_alerts:
milestone_date: 'Milestone date'
overdue: 'Overdue'
overdue_since: 'since %{difference_in_days}'
property_today: 'is today'
property_today: 'bugün'
property_is: 'is in %{difference_in_days}'
property_was: 'was %{difference_in_days} ago'
property_is_deleted: 'silindi'
upsale:
title: 'Date alerts'
title: 'Tarih uyarısı'
description: 'With date alerts, you will be notified of upcoming start or finish dates so that you never miss or forget an important deadline.'
facets:
unread: 'okunmamış'
unread_title: 'Show unread'
unread_title: 'Okunmayanları göster'
all: 'Hepsi'
all_title: 'Tümünü göster'
center:
label_actor_and: 'and'
label_actor_and: 've'
and_more_users:
one: 've 1 diğer'
other: 've 1 diğer'
no_results:
at_all: 'New notifications will appear here when there is activity that concerns you.'
with_current_filter: 'There are no notifications in this view at the moment'
at_all: 'Sizi ilgilendiren bir etkinlik olduğunda yeni bildirimler burada görünecektir.'
with_current_filter: 'Şu anda bu görünümde bildirim yok'
mark_all_read: 'Tümünü okundu olarak işaretle'
mark_as_read: 'Okundu olarak işaretle'
text_update_date: "%{date} by"
@ -608,13 +608,13 @@ tr:
P7D: 1 hafta önce
overdue:
P1D: her gün
P3D: every 3 days
P3D: Her 3 günde bir
P7D: her hafta
reasons:
mentioned:
title: 'Bahsedilen'
description: 'Receive a notification every time someone mentions me anywhere'
assignee: 'Assignee'
assignee: 'Atanan'
responsible: 'Sorumlu'
watched: 'İzleyici'
work_package_commented: 'Tüm yeni yorumlar'
@ -624,19 +624,19 @@ tr:
work_package_scheduled: 'Tüm tarih değişiklikleri'
global:
immediately:
title: 'Participating'
description: 'Notifications for all activities in work packages you are involved in (assignee, accountable or watcher).'
title: 'Katılım'
description: 'Dahil olduğunuz (vekil, sorumlu veya gözlemci) iş paketlerindeki tüm faaliyetler için bildirimler.'
delayed:
title: 'Non-participating'
description: 'Additional notifications for activities in all projects.'
description: 'Tüm projelerdeki faaliyetler için ek bildirimler.'
date_alerts:
title: 'Date alerts'
description: 'Automatic notifications when important dates are approaching for open work packages you are involved in (assignee, accountable or watcher).'
title: 'Tarih uyarısı'
description: 'Dahil olduğunuz (vekil, sorumlu veya gözlemci) açık iş paketleri için önemli tarihler yaklaştığında otomatik bildirimler.'
teaser_text: 'With date alerts, you will be notified of upcoming start or finish dates so that you never miss or forget an important deadline.'
overdue: When overdue
project_specific:
title: 'Project-specific notification settings'
description: 'These project-specific settings override default settings above.'
title: 'Projeye özel bildirim ayarları'
description: 'Bu projeye özgü ayarlar, yukarıdaki varsayılan ayarları geçersiz kılar.'
add: 'Proje için ayar ekle'
already_selected: 'Bu proje zaten seçildi'
remove: 'Proje ayarlarını sil'
@ -657,7 +657,7 @@ tr:
project:
required_outside_context: >
Lütfen tüm özellikleri görmek için çalışma paketini oluşturacak bir proje seçin. Yalnızca yukarıdaki türden etkin olan projeleri seçebilirsiniz.
details_activity: 'Project details activity'
details_activity: 'Proje ayrıntıları etkinliği'
context: 'Proje içeriği'
work_package_belongs_to: 'Bu iş paketi %{projectname} projesine ait.'
click_to_switch_context: 'Bu iş paketini o projede aç.'
@ -673,8 +673,8 @@ tr:
daily:
add_time: 'Süre ekle'
enable: 'Günlük email hatırlatıcılarını etkinleştir'
explanation: 'You will receive these reminders only for unread notifications and only at hours you specify. %{no_time_zone}'
no_time_zone: 'Until you configure a time zone for your account, the times will be interpreted to be in UTC.'
explanation: 'Bu hatırlatıcıları yalnızca okunmamış bildirimler için ve yalnızca sizin belirlediğiniz saatlerde alacaksınız. %{no_time_zone}'
no_time_zone: 'Hesabınız için bir saat dilimi yapılandırana kadar, saatler UTC olarak yorumlanacaktır.'
time_label: 'Zaman %{counter}:'
title: 'Okunmamış bildirimler için bana günlük e-posta hatırlatıcıları gönder'
workdays:
@ -683,11 +683,11 @@ tr:
title: 'Bana email hatırlatıcısı gönder'
mentioned: 'Immediately when someone @mentions me'
alerts:
title: 'Email alerts for other items (that are not work packages)'
title: 'Diğer öğeler için e-posta uyarıları (iş paketleri olmayanlar)'
explanation: >
Notifications today are limited to work packages. You can choose to continue receiving email alerts for these events until they are included in notifications:
Bildirimler bugün iş paketleri ile sınırlıdır. Bildirimlere eklenene kadar bu etkinlikler için e-posta uyarıları almaya devam etmeyi seçebilirsiniz:
news_added: 'Haberler eklendi'
news_commented: 'Comment on a news item'
news_commented: 'Bir habere yorum yapın'
document_added: 'Belgeler eklendi'
forum_messages: 'Yeni forum mesajları'
wiki_page_added: 'Viki sayfası eklendi'
@ -708,8 +708,8 @@ tr:
reset_title: "Form ayarlarlarını sıfırlayın"
confirm_reset: >
Uyarı: Form yapılandırmasını sıfırlamak istediğinizden emin misiniz? Bu, nitelikleri varsayılan gruplarına sıfırlar ve TÜM özel alanları devre dışı bırakır.
upgrade_to_ee: "Upgrade to Enterprise on-premises edition"
upgrade_to_ee_text: "Wow! If you need this add-on you are a super pro! Would you mind supporting us OpenSource developers by becoming an Enterprise edition client?"
upgrade_to_ee: "Enterprise on-premises edition'a yükseltin"
upgrade_to_ee_text: "Vay! Bu eklentiye ihtiyacınız varsa, siz bir süper profesyonelsiniz! Enterprise sürümü müşterisi olarak biz OpenSource geliştiricilerini destekler misiniz?"
more_information: "Daha fazla bilgi"
nevermind: "Boşver"
edit:
@ -885,11 +885,11 @@ tr:
comment_updated: "Yorum başarıyla güncelleştirildi."
confirm_edit_cancel: "İş paketini düzenlemeyi iptal etmek istediğinizden emin misiniz?"
datepicker_modal:
automatically_scheduled_parent: "Automatically scheduled. Dates are derived from relations."
manually_scheduled: "Manual scheduling enabled, all relations ignored."
start_date_limited_by_relations: "Available start and finish dates are limited by relations."
changing_dates_affects_follow_relations: "Changing these dates will affect dates of related work packages."
click_on_show_relations_to_open_gantt: 'Click on "%{button_name}" for GANTT overview.'
automatically_scheduled_parent: "Otomatik olarak planlandı. Tarihler ilişkilerden türetilir."
manually_scheduled: "Manuel planlama etkinleştirildi, tüm ilişkiler göz ardı edildi."
start_date_limited_by_relations: "Kullanılabilir başlangıç ve bitiş tarihleri ilişkilerle sınırlıdır."
changing_dates_affects_follow_relations: "Bu tarihlerin değiştirilmesi, ilgili iş paketlerinin tarihlerini etkileyecektir."
click_on_show_relations_to_open_gantt: 'GANTT''ye genel bakış için "%{button_name}" üzerine tıklayın.'
show_relations: 'İlişkileri göster'
ignore_non_working_days:
title: 'Sadece iş günleri'
@ -913,7 +913,7 @@ tr:
message_work_package_status_blocked: "İş paketi durumu, kapalı durum ve kapalı sürüm tahsis edildiğinden dolayı yazılamaz."
placeholder_filter_by_text: "Konu, açıklama, yorumlar, ..."
filters:
title: 'Filter work packages'
title: 'İş paketlerini filtrele'
inline_create:
title: 'Listeden yeni bir iş paketi eklemek için buraya tıklayınız'
create:
@ -937,7 +937,7 @@ tr:
no_results:
title: Görüntülecek bir iş paketi bulunmuyor.
description: Ya hiç iş paketi oluşturulmamış, ya da tüm iş paketeri filtrelenmiş.
limited_results: Only %{count} work packages can be shown in manual sorting mode. Please reduce the results by filtering, or switch to automatic sorting.
limited_results: Manuel sıralama modunda yalnızca %{count} iş paketi gösterilebilir. Lütfen filtreleyerek sonuçları azaltın veya otomatik sıralamaya geçin.
property_groups:
details: "Detaylar"
people: "Kişiler"
@ -1047,7 +1047,7 @@ tr:
upsale:
attribute_highlighting: 'Kitleden sıyrılmak için bazı iş paketlerine mi ihtiyacınız var?'
relation_columns: 'İş paketleri listesindeki ilişkileri görmek ister misiniz?'
check_out_link: 'Check out the Enterprise edition.'
check_out_link: 'Enterprise sürümünü inceleyin.'
relation_filters:
filter_work_packages_by_relation_type: 'İş paketlerini ilişki türüne göre filtreleme'
tabs:
@ -1056,7 +1056,7 @@ tr:
relations: İlişkiler
watchers: Takip Edenler
files: Dosyalar
files_tab_migration_help: 'You can now attach files to work packages via the new tab:'
files_tab_migration_help: 'Artık yeni sekme aracılığıyla iş paketlerine dosya ekleyebilirsiniz:'
time_relative:
days: "gün"
weeks: "hafta"
@ -1093,8 +1093,8 @@ tr:
text: 'Bu işlemi gerçekleştirmek istediğinizden emin misiniz?'
destroy_work_package:
title: "%{label} için silme işlimini onaylayın"
single_text: "Are you sure you want to delete the work package"
bulk_text: "Are you sure you want to delete the following %{label}?"
single_text: "Bu iş paketini silmek istediğinize emin misiniz?"
bulk_text: "Aşağıdaki %{label}'i silmek istediğinizden emin misiniz?"
has_children: "İş paketi %{childUnits} alt paketlerine sahip:"
confirm_deletion_children: "Listelenen iş paketlerinin TÜM soylarının tekrar tekrar kaldırılacağını kabul ediyorum."
deletes_children: "Tüm çocuk iş paketleri ve torunları da tekrar tekrar silinir."
@ -1191,9 +1191,9 @@ tr:
description: 'Seçilen projede atanan role dayalı izinler'
placeholder:
title: 'Yer tutucu kullanıcı'
title_no_ee: 'Placeholder user (Enterprise edition only add-on)'
title_no_ee: 'Yer tutucu kullanıcı (yalnızca Enterprise sürümü eklentisi)'
description: 'Projeye erişimi yoktur ve e-posta gönderilmez.'
description_no_ee: 'Has no access to the project and no emails are sent out. <br>Check out the <a href="%{eeHref}" target="_blank">Enterprise edition</a>'
description_no_ee: 'Projeye erişimi yoktur ve e-posta gönderilmez. <br><a href="%{eeHref}" target="_blank">Enterprise sürümünü</a> inceleyin'
principal:
label:
name_or_email: 'İsim veya e-posta adresi'
@ -1217,7 +1217,7 @@ tr:
next_button: 'Sonraki'
message:
label: 'Davet Mesajı'
description: 'We will send an email to the user, to which you can add a personal message here. An explanation for the invitation could be useful, or prehaps a bit of information regarding the project to help them get started.'
description: 'Kullanıcıya, buradan kişisel bir mesaj ekleyebileceğiniz bir e-posta göndereceğiz. Davet için bir açıklama yararlı olabilir veya belki de başlamalarına yardımcı olacak projeyle ilgili bir parça bilgi olabilir.'
next_button: 'Sonraki'
summary:
next_button: 'Davet gönder'
@ -1237,9 +1237,9 @@ tr:
all: 'Tüm projeler'
selected: 'Sadece seçilen'
search_placeholder: 'Proje ara...'
include_subprojects: 'Include all sub-projects'
include_subprojects: 'Tüm alt projeleri dahil et'
tooltip:
include_all_selected: 'Project already included since Include all sub-projects is enabled.'
include_all_selected: 'Tüm alt projeleri dahil et etkinleştirildiğinden, proje zaten dahil edilmiştir.'
current_project: 'Bu, içinde bulunduğunuz mevcut projedir.'
does_not_match_search: 'Proje arama kriterleriyle eşleşmiyor.'
no_results: 'Arama kriterleriniz ile eşleşen proje yok'

@ -2941,6 +2941,9 @@ ko:
days:
working: "%{day}은(는) 이제 근무일입니다."
non_working: "%{day}은(는) 이제 휴무일입니다."
dates:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
nothing_to_preview: "미리 볼 내용 없음"
api_v3:
attributes:

@ -2934,6 +2934,9 @@ lol:
days:
working: "crwdns834174:0%{day}crwdne834174:0"
non_working: "crwdns834176:0%{day}crwdne834176:0"
dates:
working: "crwdns844503:0%{date}crwdne844503:0"
non_working: "crwdns844505:0%{date}crwdne844505:0"
nothing_to_preview: "crwdns499773:0crwdne499773:0"
api_v3:
attributes:

@ -3002,6 +3002,9 @@ lt:
days:
working: "%{day} is now working"
non_working: "%{day} is now non-working"
dates:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
nothing_to_preview: "Nėra ką rodyti"
api_v3:
attributes:

@ -2982,6 +2982,9 @@ lv:
days:
working: "%{day} is now working"
non_working: "%{day} is now non-working"
dates:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
nothing_to_preview: "Nothing to preview"
api_v3:
attributes:

@ -2966,6 +2966,9 @@ ne:
days:
working: "%{day} is now working"
non_working: "%{day} is now non-working"
dates:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
nothing_to_preview: "Nothing to preview"
api_v3:
attributes:

@ -2961,6 +2961,9 @@ nl:
days:
working: "%{day} werkt nu"
non_working: "%{day} is nu niet actief"
dates:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
nothing_to_preview: "Niets om te bekijken"
api_v3:
attributes:

@ -2966,6 +2966,9 @@
days:
working: "%{day} is now working"
non_working: "%{day} is now non-working"
dates:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
nothing_to_preview: "Ingenting å forhåndsvise"
api_v3:
attributes:

@ -3002,6 +3002,9 @@ pl:
days:
working: "%{day} jest teraz dniem roboczym"
non_working: "%{day} jest teraz dniem nieroboczym"
dates:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
nothing_to_preview: "Nie ma nic do podglądu"
api_v3:
attributes:

@ -2962,6 +2962,9 @@ pt:
days:
working: "%{day} agora é um dia útil"
non_working: "%{day} agora é um dia não-útil"
dates:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
nothing_to_preview: "Nada para visualizar"
api_v3:
attributes:

@ -2986,6 +2986,9 @@ ro:
days:
working: "%{day} funcționează acum"
non_working: "%{day} este acum nefuncțională"
dates:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
nothing_to_preview: "Nimic de previzualizat"
api_v3:
attributes:

@ -3003,6 +3003,9 @@ ru:
days:
working: "%{day} сейчас работает"
non_working: "%{day} теперь не работает"
dates:
working: "%{date} сейчас работает"
non_working: "%{date} теперь не работает"
nothing_to_preview: "Нет ничего для предосмотра"
api_v3:
attributes:

@ -2966,6 +2966,9 @@ rw:
days:
working: "%{day} is now working"
non_working: "%{day} is now non-working"
dates:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
nothing_to_preview: "Nothing to preview"
api_v3:
attributes:

@ -2966,6 +2966,9 @@ si:
days:
working: "%{day} is now working"
non_working: "%{day} is now non-working"
dates:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
nothing_to_preview: "පරදසමට කවකත"
api_v3:
attributes:

@ -3007,6 +3007,9 @@ sk:
days:
working: "%{day} is now working"
non_working: "%{day} is now non-working"
dates:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
nothing_to_preview: "Nič na zobrazenie náhľadu"
api_v3:
attributes:

@ -3004,6 +3004,9 @@ sl:
days:
working: "%{day} is now working"
non_working: "%{day} is now non-working"
dates:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
nothing_to_preview: "Ničesar za predogled"
api_v3:
attributes:

@ -483,9 +483,9 @@ sv:
explanation: 'Statusbeskrivning'
codes:
not_started: 'Not started'
on_track: 'På banan'
on_track: 'På rätt spår'
at_risk: 'I riskzonen'
off_track: 'Utanför banan'
off_track: 'Urspårat'
finished: 'Finished'
discontinued: 'Discontinued'
query:
@ -2962,6 +2962,9 @@ sv:
days:
working: "%{day} is now working"
non_working: "%{day} is now non-working"
dates:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
nothing_to_preview: "Ingenting att förhandsgranska"
api_v3:
attributes:

@ -2945,6 +2945,9 @@ th:
days:
working: "%{day} is now working"
non_working: "%{day} is now non-working"
dates:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
nothing_to_preview: "ไมอะไรใหแสดงเปนตวอยาง"
api_v3:
attributes:

@ -70,7 +70,7 @@ tr:
text: "Are you sure you want to remove the current Enterprise edition token used?"
title: "Delete token"
replace_token: "Geçerli destek anahtarını değiştirin"
order: "Order Enterprise on-premises edition"
order: "Enterprise on-premises edition sipariş edin"
paste: "Paste your Enterprise edition support token"
required_for_feature: "This add-on is only available with an active Enterprise edition support token."
enterprise_link: "Daha fazla bilgi için burayı tıklatın."
@ -84,7 +84,7 @@ tr:
upgrade_info: "Etkinleştirmek ve ekibinizde kullanmaya başlamak için lütfen ücretli bir plana yükseltin."
journal_aggregation:
explanation:
text: "Individual actions of a user (e.g. updating a work package twice) are aggregated into a single action if their age difference is less than the specified timespan. They will be displayed as a single action within the application. This will also delay notifications by the same amount of time reducing the number of emails being sent and will also affect %{webhook_link} delay."
text: "Bir kullanıcının bireysel eylemleri (örneğin, bir iş paketini iki kez güncelleme), yaş farkı belirtilen zaman aralığından azsa tek bir eylemde toplanır. Uygulama içinde tek bir eylem olarak görüntülenecektir. Bu aynı zamanda gönderilen e-posta sayısını azaltarak bildirimleri aynı süre kadar geciktirecek ve ayrıca %{webhook_link} gecikmesini etkileyecektir."
link: "webhook"
announcements:
show_until: Son görüntülenme tarihi
@ -220,10 +220,10 @@ tr:
#Contains custom strings for options when copying a project that cannot be found elsewhere.
members: 'Proje üyeleri'
overviews: 'Projeye Genel Bakış'
queries: 'Work packages: saved views'
wiki_page_attachments: 'Wiki pages: attachments'
work_package_attachments: 'Work packages: attachments'
work_package_categories: 'Work packages: categories'
queries: 'İş paketleri: kaydedilen görünümler'
wiki_page_attachments: 'Wiki sayfaları: ekler'
work_package_attachments: 'İş paketleri: ekler'
work_package_categories: 'İş paketleri: kategoriler'
work_package_file_links: 'Çalışma paketleri: dosya bağlantıları'
delete:
scheduled: "Silme planlandı ve arka planda gerçekleştirilir. Sonuçtan haberdar edileceksiniz."
@ -280,7 +280,7 @@ tr:
no_results_title_text: Bu kullanıcı şuan için bir proje üyesi değil.
placeholder_users:
right_to_manage_members_missing: >
You are not allowed to delete the placeholder user. You do not have the right to manage members for all projects that the placeholder user is a member of.
Yer tutucu kullanıcıyı silme izniniz yok. Yer tutucu kullanıcının üyesi olduğu tüm projeler için üyeleri yönetme hakkınız yoktur.
delete_tooltip: "Yer tutucu kullanıcısını silin."
deletion_info:
heading: "%{name} yer tutucu kullanıcısını sil."
@ -638,7 +638,7 @@ tr:
auth_source:
attributes:
tls_certificate_string:
invalid_certificate: "The provided SSL certificate is invalid: %{additional_message}"
invalid_certificate: "Sağlanan SSL sertifikası geçersiz: %{additional_message}"
format: "%{message}"
attachment:
attributes:
@ -1271,11 +1271,11 @@ tr:
ee:
upsale:
form_configuration:
description: "Customize the form configuration with these additional add-ons:"
description: "Bu ek eklentilerle form yapılandırmasını özelleştirin:"
add_groups: "Yeni öznitelik grubu ekleyin"
rename_groups: "Öznitelik grubunun adını değiştirin"
project_filters:
description_html: "Filtering and sorting on custom fields is an Enterprise edition add-on."
description_html: "Özel alanlarda filtreleme ve sıralama, bir Enterprise sürümü eklentisidir."
enumeration_activities: "Zaman izleme faaliyetleri"
enumeration_work_package_priorities: "İş paketi öncelikleri"
enumeration_reported_project_statuses: "Bildirilen proje durumları"
@ -1797,7 +1797,7 @@ tr:
label_product_version: "Ürün sürümü"
label_professional_support: "Profesyonel destek"
label_profile: "Profil"
label_project_activity: "Project activity"
label_project_activity: "Proje etkinliği"
label_project_attribute_plural: "Proje öznitelikleri"
label_project_count: "Toplam proje sayısı"
label_project_copy_notifications: "Proje kopyalaması esnasında bilgilendirme e-postaları gönder"
@ -2046,9 +2046,9 @@ tr:
other: 'There are %{count} more work packages with notifications.'
reason:
watched: 'İzlendi'
assigned: 'Assigned'
assigned: 'Atanmış'
responsible: 'Sorumlu'
mentioned: 'Mentioned'
mentioned: 'Bahsedilen'
subscribed: 'tüm'
prefix: 'Received because of the notification setting: %{reason}'
date_alert_start_date: 'Date alert'
@ -2221,7 +2221,7 @@ tr:
permission_add_work_packages: "İş paketi eklemek"
permission_add_messages: "İleti göndermek"
permission_add_project: "Proje oluşturmak"
permission_archive_project: "Archive project"
permission_archive_project: "Projeyi arşivle"
permission_manage_user: "Kullanıcılar oluştur ve düzenle"
permission_manage_placeholder_user: "Yer tutucu kullanıcıları oluşturun, düzenleyin ve silin"
permission_add_subprojects: "Alt proje oluşturmak"
@ -2607,7 +2607,7 @@ tr:
text_access_token_hint: "Erişim belirteçleri, OpenProject içindeki kaynaklara harici uygulamalar erişimi vermenizi sağlar."
text_analyze: "Daha fazla analiz: %{subject}"
text_are_you_sure: "Emin misiniz?"
text_are_you_sure_continue: "Are you sure you want to continue?"
text_are_you_sure_continue: "Devam etmek istediğinizden emin misiniz?"
text_are_you_sure_with_children: "Sil iş paketi ve tüm alt çalışma paketlerini?"
text_assign_to_project: "Projeye ata"
text_form_configuration: >
@ -2965,11 +2965,14 @@ tr:
days:
working: "%{day} is now working"
non_working: "%{day} is now non-working"
dates:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
nothing_to_preview: "Önizlenecek bir şey yok"
api_v3:
attributes:
lock_version: "Sürümü Kilitle"
property: 'Property'
property: 'Özellik'
errors:
code_400: "Geçersiz istek: %{message}"
code_401: "Bu kaynağa erişim sağlayabilmeniz için yetkilendirilmiş olmalısınız"

@ -2999,6 +2999,9 @@ uk:
days:
working: "%{day} зараз робочий"
non_working: "%{day} зараз неробочий"
dates:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
nothing_to_preview: "Нічого для перегляду"
api_v3:
attributes:

@ -2946,6 +2946,9 @@ vi:
days:
working: "%{day} is now working"
non_working: "%{day} is now non-working"
dates:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
nothing_to_preview: "Nothing to preview"
api_v3:
attributes:

@ -2944,6 +2944,9 @@ zh-TW:
days:
working: "%{day} is now working"
non_working: "%{day} is now non-working"
dates:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
nothing_to_preview: "沒有內容可預覽"
api_v3:
attributes:

@ -3160,6 +3160,9 @@ en:
days:
working: "%{day} is now working"
non_working: "%{day} is now non-working"
dates:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
nothing_to_preview: "Nothing to preview"
api_v3:

@ -0,0 +1,34 @@
# Schema: StorageFileUploadLinkModel
---
type: object
required:
- _type
- _links
properties:
_type:
type: string
enum:
- UploadLink
_links:
type: object
required:
- self
- destination
properties:
self:
allOf:
- $ref: './link.yml'
- description: |-
The resource link of the upload link resource.
As the upload link is a temporal object, and cannot be retrieved again, the
self link usually is `urn:openproject-org:api:v3:storages:upload_link:no_link_provided`.
**Resource**: UploadLink
destination:
allOf:
- $ref: './link.yml'
- description: |-
The direct upload link.
**Resource**: N/A

@ -0,0 +1,20 @@
# Schema: StorageFileUploadPreparationModel
---
type: object
required:
- projectId
- fileName
- parent
properties:
projectId:
type: integer
description: The project identifier, from where a user starts uploading a file.
minimum: 1
fileName:
type: string
description: The file name.
parent:
type: string
description: |-
The directory to which the file is to be uploaded. For root directories, the value `/` must
be provided.

@ -1,2 +0,0 @@
# Schema: Time_entry_create_form
--- {}

@ -1,2 +0,0 @@
# Schema: Time_entry_update_form
--- {}

@ -1,2 +0,0 @@
# Schema: Unlock_user
--- {}

@ -1,2 +0,0 @@
# Schema: Update_group
--- {}

@ -1,2 +0,0 @@
# Schema: Update_User
--- {}

@ -363,6 +363,8 @@ paths:
"$ref": "./paths/storage.yml"
"/api/v3/storages/{id}/files":
"$ref": "./paths/storage_files.yml"
"/api/v3/storages/{id}/files/prepare_upload":
"$ref": "./paths/storage_files_prepare_upload.yml"
"/api/v3/storages/{id}/oauth_client_credentials":
"$ref": "./paths/storage_oauth_client_credentials.yml"
"/api/v3/time_entries":
@ -750,6 +752,10 @@ components:
"$ref": "./components/schemas/storage_file_model.yml"
StorageFileLocationModel:
"$ref": "./components/schemas/storage_file_location_model.yml"
StorageFileUploadPreparationModel:
"$ref": "./components/schemas/storage_file_upload_preparation_model.yml"
StorageFileUploadLinkModel:
"$ref": "./components/schemas/storage_file_upload_link_model.yml"
StorageReadModel:
"$ref": "./components/schemas/storage_read_model.yml"
StorageWriteModel:
@ -758,24 +764,14 @@ components:
"$ref": "./components/schemas/time_entry_model.yml"
Time_Entry_ActivityModel:
"$ref": "./components/schemas/time_entry_activity_model.yml"
Time_entry_create_form:
"$ref": "./components/schemas/time_entry_create_form.yml"
Time_entry_update_form:
"$ref": "./components/schemas/time_entry_update_form.yml"
TypeModel:
"$ref": "./components/schemas/type_model.yml"
TypesModel:
"$ref": "./components/schemas/types_model.yml"
Types_by_ProjectModel:
"$ref": "./components/schemas/types_by_project_model.yml"
Unlock_user:
"$ref": "./components/schemas/unlock_user.yml"
Unstar_QueryModel:
"$ref": "./components/schemas/unstar_query_model.yml"
Update_User:
"$ref": "./components/schemas/update_user.yml"
Update_group:
"$ref": "./components/schemas/update_group.yml"
UserCollectionModel:
"$ref": "./components/schemas/user_collection_model.yml"
UserCreateModel:

@ -116,12 +116,10 @@ delete:
application/hal+json:
schema:
$ref: '../components/schemas/error_response.yml'
examples:
response:
value:
_type: Error
errorIdentifier: urn:openproject-org:api:v3:errors:MissingPermission
message: You are not authorized to access this resource.
example:
_type: Error
errorIdentifier: urn:openproject-org:api:v3:errors:MissingPermission
message: You are not authorized to access this resource.
description: |-
Returned if the client does not have sufficient permissions.

@ -0,0 +1,71 @@
# /api/v3/storages/{id}/files/prepare_upload
---
post:
summary: Preparation of a direct upload of a file to the given storage.
operationId: prepare_storage_file_upload
tags:
- File links
description: |-
Executes a request that prepares a link for a direct upload to the storage.
The background here is, that the client needs to make a direct request to the storage instance for file uploading,
but should not get access to the credentials, which are stored in the backend. The response contains a link object,
that enables the client to execute a file upload without the real credentials.
parameters:
- name: id
description: Storage id
in: path
required: true
schema:
type: integer
example: 1337
requestBody:
content:
application/json:
schema:
$ref: '../components/schemas/storage_file_upload_preparation_model.yml'
responses:
'201':
description: OK
content:
application/hal+json:
schema:
$ref: '../components/schemas/storage_file_upload_link_model.yml'
'400':
description: Returned if the given parent parameter value does not refer to a directory.
content:
application/hal+json:
schema:
$ref: '../components/schemas/error_response.yml'
example:
_type: Error
errorIdentifier: urn:openproject-org:api:v3:errors:InvalidQuery
message: The given parent is not a directory.
'403':
content:
application/hal+json:
schema:
$ref: '../components/schemas/error_response.yml'
example:
_type: Error
errorIdentifier: urn:openproject-org:api:v3:errors:MissingPermission
message: You are not authorized to access this resource.
description: |-
Returned if the client does not have sufficient permissions.
**Required permission:** manage file links
'404':
content:
application/hal+json:
schema:
$ref: '../components/schemas/error_response.yml'
example:
_type: Error
errorIdentifier: urn:openproject-org:api:v3:errors:NotFound
message: The requested resource could not be found.
description: |-
Returned in either of those cases:
- if the storage does not exist or the client does not have sufficient permissions to see it
**Required permission:** view file links
- if the document root file identification does not exist on the storage

@ -8,8 +8,8 @@ keywords: use-cases
# OpenProject Use Cases
| Use Case | Description |
|----------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| [Portfolio Management](portfolio-management) | This guide provides detailed step-by-step instruction on how to set up an overview of your project portfolio and create custom reports using the Project Overview, Wiki and the Rich text (WYSIWYG) editor in OpenProject. |
| Use Case | Description |
| -------------------------------------------- | ------------------------------------------------------------ |
| [Resource Management](resource-management) | OpenProject does not have the automated functionality to provide detailed resource management or employee work capacity calculations. This guide with detailed step-by-step instructions introduces a workaround that can provide an avenue to accomplish this manually and visually beyond the functionality the Team Planner Module provides. |
| [Portfolio Management](portfolio-management) | This guide provides detailed step-by-step instruction on how to set up an overview of your project portfolio and create custom reports using the Project Overview, Wiki and the Rich text (WYSIWYG) editor in OpenProject. |

@ -6,32 +6,73 @@ description: Step-by-step instruction about portfolio management and custom repo
keywords: use-case, portfolio management
---
# Use Case: Portfolio Management and Custom Reporting Options
# Use Case: Portfolio management and custom reporting options
Step 1: To view all projects, first select the *project chooser drop-down*, the chose *View all projects*
If you have a lot of projects running at the same time it can be helpful and even necessary to have a meta level overview of your projects, keep track of the project status and due dates. With OpenProject you can do just that.
![Chose project](chose-project.jpg)
![OpenProject projects portfolio overview](openproject_projects_overview.png)
Step 2: You can sort and filter this view using custom fields, such as *Initiative* or *Status.* If you have not added useful custom fields, please see [here](../../system-admin-guide/custom-fields/).
## Creating projects overview
Step 3: Press the **floppy disk icon** to save and name your view once you are happy with the information that is displayed. You can also add this view as a favorite to the black bar on the left.
Step 1: To view all projects, first select the **Select a project** dropdown menu, then click on the **Projects list** button.
## Creating Custom Reports
![open project list](openproject_select_projects_list.png)
You can create advanced project reports by using the same techniques and the print function (**CTRL+P**), then saving as PDF, for example. The print function in OpenProject is optimized for reporting purposes. Only information displayed in the main screen area is included. None of the designs or side or top menus are in it.
Step 2: You will get a list of all the projects that exist in your organization. You can filter the list by various project attributes, such as **project owner** or **creation date**. You can also use project custom fields as filters (please keep in mind that this is an enterprise add-on). If you have not added any custom fields yet, please see [here](../../system-admin-guide/custom-fields/) how to do it.
For more advanced requirements, using the Wiki is another powerful tool. For more information about how to use the Wiki function, please consult: [Wiki](../../user-guide/wiki/)
![OpenProject filter projects view](openproject_filter_projects.png)
The Wiki function allows you to build complete custom reports using embedded work package tables, macros and even embedded calculations.
You can then sort the project list by clicking on a column heading, for example by project status.
Here is an example of how a wiki could look:
![Openproject sort project list by status](sort_by_status.png)
![Creating custom reports](custom-reports.jpg)
You can add a visual component to the overview by clicking on the **Open as Gantt view** button.
![OpenProject projects Gantt overview](open_as_gantt_view.png)
![OpenProject projects in Gantt view](gantt_view.png)
**Step 3:** You can also configure this view using the button with the three dots at the upper right corner and select **Configure**.
![OpenProject configure projects overview](openrpoject_configure_projects_overview.png)
You will then be led to the **System settings** of the global Administration. If you scroll down the page, you can select which columns are to be displayed in the project list in the section **Settings for project overview list** (you will need to scroll down the page). Please save your changes via the blue **Save** button, at the bottom of the page.
![OpenProject settings for project overview list](openproject_settings_for_project_overview_list.png)
If you click on **Edit query** you can adjust the project overview when using the Gantt chart option.
## Creating custom reports
### Exporting reports
For creating custom project reports you can use the export function in the work packages view.
![Openproject reports export](openproject_export.png)
You can export the work packages in one of the following formats.
![Openproject export options](export_options.png)
To export or print a Gantt chart use the print function (**CTRL+P**) and then save it as PDF. Only information displayed in the main screen area is included. None of the designs or side or top menus are in it. Please see here [how to print a Gantt chart in OpenProject](../../user-guide/gantt-chart/#how-to-print-a-gantt-chart).
### Project status reporting
You can [display and configure the individual project status](../../user-guide/projects/project-status/) on the project overview page.
For more advanced project reporting requirements, using the Wiki module is another powerful tool. The Wiki allows you to build complete custom reports using embedded work package tables, macros and even embedded calculations.
Here is an example of how a project report wiki could look:
![Creating custom reports](Wiki.png)
And how the dynamic data, such as calculations, filters, macros and reference language work behind the scenes:
![Dynamic data](dynamic-data.jpg)
![Dynamic data](openproject_wiki_editing.png)
For more information about the syntax and how the attributes work please look [here](../../user-guide/wysiwyg/).
For more information about the syntax and how the attributes work [here](../../user-guide/wysiwyg/).
If you want to work with multiple Wiki-based reports, you can create a parent Wiki page as a table of contents, for example, on which all the other reports are listed.
If you like to work with multiple Wiki-based reports, you can create an umbrella Wiki page as a table of content, for example, on which all the other reports are listed. See more info on Wiki and the use of Macros [here](../../user-guide/wiki/).
See more info on Wiki and the use of Macros [here](../../user-guide/wiki/).

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 262 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 146 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

@ -6,9 +6,11 @@ description: Step-by-step instruction about resource management
keywords: use-case, resource management
---
# Use Case: Resource Management
# Use Case: Resource management
**Note:** OpenProject does not have the automated functionality to provide detailed resource management or employee work capacity calculations. However, there is a workaround that you can use to configure a visual estimate of task attribution and plan accordingly.
**Note:** OpenProject does not have the automated functionality to provide detailed resource management or employee work capacity calculations. However, there is a workaround that you can use to configure a visual estimate of task distribution and plan accordingly.
## Work packages view
These are the steps you can follow to adjust a work package overview to suit your goals.
@ -20,32 +22,38 @@ Alternatively, you can also chose the **Global work package overview** by select
![OpenProject global work packages overview](openproject_global_wp_view.png)
Step 2: Either use existing fields, for example **Estimated time** and **Spent time**, or [create custom fields](../../system-admin-guide/custom-fields/) (i.e. **Est. Scope (h)** and **Time spent (h)**) to adjust the work packages overview.
Step 2: You can add existing fields, such as **Estimated time**, **Spent time** and **Remaining hours** to your work packages list. Also, you can [create additional custom fields](../../system-admin-guide/custom-fields/), e.g. **Scope (h)**, to get an overview of the team capacity.
Step 3: You can either insert the standard or existing fields to the view, or insert the custom fields if created in Step 2.
Step 3: You can add these fields via the **Insert columns** option via the drop-down menu.
Step 4: You can add any filters necessary and and sort or group the work packages by assignee.
Step 4: You can add any filters necessary and sort or group the work packages by assignee.
![OpenProject sort work packages by assignee](openproject_sort_by_assignee.png)
Step 5: Save your adjusted view by clicking on the **Save** icon on the left (you can name this view before saving or re-name it later). ![Save adjusted openrpoject workpage view](openproject_save_wp_adjusted_view.png)
This view will be saved and shown under your private work package filters.
This view will be saved and shown under your private work package filters (you can make it public and share with other team members).
![OpenProjec work package private filter](work_package_private_filter.png)
You could also add the Gantt view to add an additional dimension to your overview.
## Adding sums to the work packages view
![OpenProject work packages Gantt view](openproject_wp_gantt_view.png)
You can also use the sum function. Select **[⋮]** -> ***Configure view*** -> ***Display settings*** -> and check the ***Display Sums*** box:
This will provide a rough overview of the various tasks assigned to a specific person or team. Adding the Gantt view provides a supplementary overview of when these tasks are scheduled. It is a visual way of looking at approximately how many tasks are assigned to an individual. This view gives you an estimate about the timeline, allowing for adjustments in assignments and timing to be made to balance your resources.
![OpenProject work package configure view](openproject_configure_view.png)
These functions can help focus in on showing relevant results only. Using filters and the (+) zoom function will help to focus the Gantt view to only the tasks that are scheduled for example for the next 30 days.
![OpenProject display sums](openproject_display_sums.png)
You can also use the sum function. Select **[⋮]** -> ***Configure view*** -> ***Display settings*** -> and check ***Display Sums*** box:
You will see the estimated, spent and remaining hours summed up by user, as well as the overall sum.
![OpenProject work package configure view](openproject_configure_view.png)
![OpenProject work packages sums](openproject_work_packages_sum.png)
![OpenProject display sums](openproject_display_sums.png)
## Gannt chart view
You could also add the Gantt view to add an additional dimension to your overview.
![OpenProject work packages Gantt view](openproject_wp_gantt_view.png)
This will provide a rough overview of the various tasks assigned to a specific person or team. Adding the Gantt view provides a supplementary overview of when these tasks are scheduled. It is a visual way of looking at approximately how many tasks are assigned to an individual. This view gives you an estimate about the timeline, allowing for adjustments in assignments and timing to be made to balance your resources.
**Limitations:** While this workaround provides a visual estimate of who works on what and when, it does not replace a dedicated capacity management tool.
To get a more in-depth overview about who does which tasks and when, you can also switch to the [team planner view](../../user-guide/team-planner/).

Binary file not shown.

Before

Width:  |  Height:  |  Size: 132 KiB

After

Width:  |  Height:  |  Size: 131 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 137 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 389 KiB

After

Width:  |  Height:  |  Size: 241 KiB

@ -46456,9 +46456,9 @@
}
},
"node_modules/ua-parser-js": {
"version": "0.7.32",
"resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.32.tgz",
"integrity": "sha512-f9BESNVhzlhEFf2CHMSj40NWOjYPl1YKYbrvIr/hFTDEmLq7SRbWvm7FcdcpCYT95zrOhC7gZSxjdnnTpBcwVw==",
"version": "0.7.33",
"resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.33.tgz",
"integrity": "sha512-s8ax/CeZdK9R/56Sui0WM6y9OFREJarMRHqLB2EwkovemBxNQ+Bqu8GAsUnVcXKgphb++ghr/B2BZx4mahujPw==",
"dev": true,
"funding": [
{
@ -83851,9 +83851,9 @@
"dev": true
},
"ua-parser-js": {
"version": "0.7.32",
"resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.32.tgz",
"integrity": "sha512-f9BESNVhzlhEFf2CHMSj40NWOjYPl1YKYbrvIr/hFTDEmLq7SRbWvm7FcdcpCYT95zrOhC7gZSxjdnnTpBcwVw==",
"version": "0.7.33",
"resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.33.tgz",
"integrity": "sha512-s8ax/CeZdK9R/56Sui0WM6y9OFREJarMRHqLB2EwkovemBxNQ+Bqu8GAsUnVcXKgphb++ghr/B2BZx4mahujPw==",
"dev": true
},
"uglify-js": {

@ -26,16 +26,17 @@
// See COPYRIGHT and LICENSE files for more details.
//++
import { getType } from 'mime';
import { Injectable } from '@angular/core';
import { HttpEvent, HttpResponse } from '@angular/common/http';
import { from, Observable, of } from 'rxjs';
import { share, switchMap } from 'rxjs/operators';
import { HalResource } from 'core-app/features/hal/resources/hal-resource';
import { getType } from 'mime';
import { EXTERNAL_REQUEST_HEADER } from 'core-app/features/hal/http/openproject-header-interceptor';
import {
OpenProjectFileUploadService, UploadBlob, UploadFile, UploadInProgress,
} from './op-file-upload.service';
import { EXTERNAL_REQUEST_HEADER } from "core-app/features/hal/http/openproject-header-interceptor";
interface PrepareUploadResult {
url:string;
@ -53,25 +54,22 @@ interface PrepareUploadResult {
export class OpenProjectDirectFileUploadService extends OpenProjectFileUploadService {
/**
* Upload a single file, get an UploadResult observable
* @param {string} url
* @param {UploadFile} file
* @param {string} method
*/
public uploadSingle(url:string, file:UploadFile|UploadBlob, method = 'post', responseType:'text'|'json' = 'text') {
public uploadSingle(url:string, file:UploadFile|UploadBlob, method = 'post') {
const observable = from(this.getDirectUploadFormFrom(url, file))
.pipe(
switchMap(this.uploadToExternal(file, method, responseType)),
switchMap(this.uploadToExternal(file, method)),
share(),
);
return [file, observable] as UploadInProgress;
}
private uploadToExternal(file:UploadFile|UploadBlob, method:string, responseType:string):(result:PrepareUploadResult) => Observable<HttpEvent<unknown>> {
private uploadToExternal(file:UploadFile|UploadBlob, method:string):(result:PrepareUploadResult) => Observable<HttpEvent<unknown>> {
return (result) => {
result.form.append('file', file, file.customName || file.name);
return this.http.request<HalResource>(
return this.http.request(
method,
result.url,
{
@ -83,7 +81,7 @@ export class OpenProjectDirectFileUploadService extends OpenProjectFileUploadSer
headers: {
[EXTERNAL_REQUEST_HEADER]: 'true',
},
responseType: responseType as 'json',
responseType: 'text',
// Subscribe to progress events. subscribe() will fire multiple times!
reportProgress: true,
},

@ -28,7 +28,10 @@
import { Injectable } from '@angular/core';
import {
HttpClient, HttpEvent, HttpEventType, HttpResponse,
HttpClient,
HttpEvent,
HttpEventType,
HttpResponse,
} from '@angular/common/http';
import { Observable } from 'rxjs';
import { filter, map, share } from 'rxjs/operators';
@ -61,22 +64,22 @@ export interface MappedUploadResult {
@Injectable()
export class OpenProjectFileUploadService {
constructor(protected http:HttpClient,
protected halResource:HalResourceService) {
}
constructor(
protected readonly http:HttpClient,
protected readonly halResource:HalResourceService,
) { }
/**
* Upload multiple files and return a promise for each uploading file and a single promise for all processed uploads
* with their accessible URLs returned.
* @param {string} url
* @param {UploadFile[]} files
* @param {string} method
* @returns {Promise<{response:HalResource; uploadUrl:any}[]>}
*/
public uploadAndMapResponse(url:string, files:UploadFile[], method = 'post') {
public uploadAndMapResponse(url:string, files:UploadFile[]):MappedUploadResult {
const { uploads, finished } = this.upload(url, files);
const mapped = finished
.then((result:HalResource[]) => result.map((el:HalResource) => ({ response: el, uploadUrl: el.staticDownloadLocation.href }))) as Promise<{ response:HalResource, uploadUrl:string }[]>;
.then((result:HalResource[]) => result.map((element:HalResource) => ({
response: element,
uploadUrl: (element.staticDownloadLocation as unknown&{ href:string }).href,
}))) as Promise<{ response:HalResource, uploadUrl:string }[]>;
return { uploads, finished: mapped } as MappedUploadResult;
}
@ -95,11 +98,13 @@ export class OpenProjectFileUploadService {
/**
* Upload a single file, get an UploadResult observable
* @param {string} url
* @param {UploadFile} file
* @param {string} method
*/
public uploadSingle(url:string, file:UploadFile|UploadBlob, method = 'post', responseType:'text'|'json' = 'json') {
public uploadSingle(
url:string,
file:UploadFile|UploadBlob,
method = 'post',
responseType:'json'|'text' = 'json',
):UploadInProgress {
const formData = new FormData();
const metadata = {
description: file.description,
@ -115,9 +120,7 @@ export class OpenProjectFileUploadService {
// Add the file
formData.append('file', file, metadata.fileName);
const observable = this
.http
.request<HalResource>(
const observable = this.http.request(
method,
url,
{
@ -125,14 +128,11 @@ export class OpenProjectFileUploadService {
// Observe the response, not the body
observe: 'events',
withCredentials: true,
responseType: responseType as any,
responseType,
// Subscribe to progress events. subscribe() will fire multiple times!
reportProgress: true,
},
)
.pipe(
share(),
);
).pipe(share());
return [file, observable] as UploadInProgress;
}

@ -28,7 +28,6 @@
import { Injectable } from '@angular/core';
import {
HttpClient,
HttpHeaders,
} from '@angular/common/http';
import { applyTransaction } from '@datorama/akita';
@ -52,7 +51,6 @@ import {
import { OpenProjectDirectFileUploadService } from 'core-app/core/file-upload/op-direct-file-upload.service';
import { I18nService } from 'core-app/core/i18n/i18n.service';
import { HalResource } from 'core-app/features/hal/resources/hal-resource';
import { ApiV3Service } from 'core-app/core/apiv3/api-v3.service';
import { HalLink } from 'core-app/features/hal/hal-link/hal-link';
import isNewResource, { HAL_NEW_RESOURCE_ID } from 'core-app/features/hal/helpers/is-new-resource';
import { ConfigurationService } from 'core-app/core/config/configuration.service';

@ -2,6 +2,7 @@ import { Injectable } from '@angular/core';
import {
finalize,
map,
take,
tap,
} from 'rxjs/operators';
import { Observable } from 'rxjs';
@ -33,14 +34,16 @@ export class DayResourceService extends ResourceCollectionService<IDay> {
.path;
}
isNonWorkingDay$(input:Date):Observable<boolean> {
isNonWorkingDay$(input:Date):Promise<boolean> {
const date = moment(input).format('YYYY-MM-DD');
return this
.requireNonWorkingYear$(input)
.pipe(
map((days) => days.findIndex((day:IDay) => day.date === date) !== -1),
);
take(1),
)
.toPromise();
}
requireNonWorkingYear$(date:Date|string):Observable<IDay[]> {

@ -38,14 +38,13 @@ import {
tap,
} from 'rxjs/operators';
import { IFileLink } from 'core-app/core/state/file-links/file-link.model';
import { IFileLink, IFileLinkOriginData } from 'core-app/core/state/file-links/file-link.model';
import { IHALCollection } from 'core-app/core/apiv3/types/hal-collection.type';
import { ToastService } from 'core-app/shared/components/toaster/toast.service';
import { FileLinksStore } from 'core-app/core/state/file-links/file-links.store';
import { insertCollectionIntoState, removeEntityFromCollectionAndState } from 'core-app/core/state/collection-store';
import { CollectionStore, ResourceCollectionService } from 'core-app/core/state/resource-collection.service';
import { IHalResourceLink } from 'core-app/core/state/hal-resource';
import { IStorageFile } from 'core-app/core/state/storage-files/storage-file.model';
import { InjectField } from 'core-app/shared/helpers/angular/inject-field.decorator';
import idFromLink from 'core-app/features/hal/helpers/id-from-link';
@ -102,19 +101,10 @@ export class FileLinksResourceService extends ResourceCollectionService<IFileLin
collectionKey:string,
addFileLinksHref:string,
storage:IHalResourceLink,
filesToLink:IStorageFile[],
filesToLink:IFileLinkOriginData[],
):Observable<IHALCollection<IFileLink>> {
const elements = filesToLink.map((file) => ({
originData: {
id: file.id,
name: file.name,
mimeType: file.mimeType,
size: file.size,
createdAt: file.createdAt,
lastModifiedAt: file.lastModifiedAt,
createdByName: file.createdByName,
lastModifiedByName: file.lastModifiedByName,
},
originData: { ...file },
_links: { storage },
}));

@ -6,17 +6,11 @@ import {
markNotificationsAsRead,
notificationsMarkedRead,
} from 'core-app/core/state/in-app-notifications/in-app-notifications.actions';
import {
EffectCallback,
EffectHandler,
} from 'core-app/core/state/effects/effect-handler.decorator';
import { EffectCallback, EffectHandler } from 'core-app/core/state/effects/effect-handler.decorator';
import { ActionsService } from 'core-app/core/state/actions/actions.service';
import { InAppNotificationsStore } from './in-app-notifications.store';
import { INotification } from './in-app-notification.model';
import {
CollectionStore,
ResourceCollectionService,
} from 'core-app/core/state/resource-collection.service';
import { CollectionStore, ResourceCollectionService } from 'core-app/core/state/resource-collection.service';
import { InjectField } from 'core-app/shared/helpers/angular/inject-field.decorator';
@EffectHandler

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

Loading…
Cancel
Save