From add8a95fcd9d55758cdcf71cd6fa2de36871a2fa Mon Sep 17 00:00:00 2001 From: Behrokh Satarnejad Date: Mon, 2 Sep 2024 13:28:29 +0200 Subject: [PATCH 01/16] change bg-color of non-working days in gantt --- .../global_styles/content/work_packages/timelines/_grid.sass | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/frontend/src/global_styles/content/work_packages/timelines/_grid.sass b/frontend/src/global_styles/content/work_packages/timelines/_grid.sass index 260321ff1a1a..cd639fc59c0d 100644 --- a/frontend/src/global_styles/content/work_packages/timelines/_grid.sass +++ b/frontend/src/global_styles/content/work_packages/timelines/_grid.sass @@ -4,10 +4,9 @@ top: 0 padding-top: 5px height: 100% - border-right: 1px solid #dddddd5e - + border-right: 1px solid var(--borderColor-neutral-muted) &_highlight border-right: 1px solid var(--borderColor-default) &--non-working-day - background-color: #f5f5f5 + background-color: var(--bgColor-disabled) From bf14004bc392dbfd7625e7b8e1aaad71bebccb57 Mon Sep 17 00:00:00 2001 From: Behrokh Satarnejad Date: Mon, 2 Sep 2024 13:47:12 +0200 Subject: [PATCH 02/16] change border color for gant chart elements --- .../global_styles/content/work_packages/timelines/_grid.sass | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/global_styles/content/work_packages/timelines/_grid.sass b/frontend/src/global_styles/content/work_packages/timelines/_grid.sass index cd639fc59c0d..ab1cccb5c350 100644 --- a/frontend/src/global_styles/content/work_packages/timelines/_grid.sass +++ b/frontend/src/global_styles/content/work_packages/timelines/_grid.sass @@ -4,9 +4,9 @@ top: 0 padding-top: 5px height: 100% - border-right: 1px solid var(--borderColor-neutral-muted) + border-right: 1px solid var(--borderColor-default) &_highlight - border-right: 1px solid var(--borderColor-default) + border-right: 1px solid var(--borderColor-emphasis) &--non-working-day background-color: var(--bgColor-disabled) From 0560c1b343e7128adea90391dbe69c898e6b8027 Mon Sep 17 00:00:00 2001 From: Dombi Attila <83396+dombesz@users.noreply.github.com> Date: Wed, 28 Aug 2024 13:52:51 +0300 Subject: [PATCH 03/16] [#57503] Time based filters like "Created on" don't trigger a result update while typing https://community.openproject.org/work_packages/57503 --- .../dynamic/filter/filters-form.controller.ts | 66 +++++++------------ 1 file changed, 22 insertions(+), 44 deletions(-) diff --git a/frontend/src/stimulus/controllers/dynamic/filter/filters-form.controller.ts b/frontend/src/stimulus/controllers/dynamic/filter/filters-form.controller.ts index 9bcf84db9ca7..bfb77a1b4515 100644 --- a/frontend/src/stimulus/controllers/dynamic/filter/filters-form.controller.ts +++ b/frontend/src/stimulus/controllers/dynamic/filter/filters-form.controller.ts @@ -74,6 +74,8 @@ export default class FiltersFormController extends Controller { declare readonly singleDayTargets:HTMLInputElement[]; declare readonly simpleValueTargets:HTMLInputElement[]; + autoReloadTargets:HTMLElement[]; + static values = { displayFilters: { type: Boolean, default: false }, outputFormat: { type: String, default: 'params' }, @@ -89,6 +91,14 @@ export default class FiltersFormController extends Controller { initialize() { // Initialize runs anytime an element with a controller connected to the DOM for the first time this.sendForm = debounce(this.sendForm.bind(this), 300); + this.autoReloadTargets = [ + ...this.simpleValueTargets, + ...this.operatorTargets, + ...this.filterValueContainerTargets, + ...this.filterValueSelectTargets, + ...this.daysTargets, + ...this.singleDayTargets, + ]; } connect() { @@ -101,28 +111,12 @@ export default class FiltersFormController extends Controller { // Auto-register change event listeners for all fields // to keep DOM cleaner. if (this.performTurboRequestsValue) { - this.simpleValueTargets.forEach((simpleValue) => { - simpleValue.addEventListener('input', this.sendForm.bind(this)); - }); - - this.operatorTargets.forEach((operator) => { - operator.addEventListener('change', this.sendForm.bind(this)); - }); - - this.filterValueSelectTargets.forEach((select) => { - select.addEventListener('change', this.sendForm.bind(this)); - }); - - this.filterValueContainerTargets.forEach((container) => { - container.addEventListener('change', this.sendForm.bind(this)); - }); - - this.singleDayTargets.forEach((singleDay) => { - singleDay.addEventListener('change', this.sendForm.bind(this)); - }); - - this.daysTargets.forEach((days) => { - days.addEventListener('change', this.sendForm.bind(this)); + this.autoReloadTargets.forEach((target) => { + if (target instanceof HTMLInputElement) { + target.addEventListener('input', this.sendForm.bind(this)); + } else { + target.addEventListener('change', this.sendForm.bind(this)); + } }); } } @@ -134,28 +128,12 @@ export default class FiltersFormController extends Controller { // Auto-deregister change event listeners for all fields // to keep DOM cleaner. if (this.performTurboRequestsValue) { - this.simpleValueTargets.forEach((simpleValue) => { - simpleValue.removeEventListener('change', this.sendForm.bind(this)); - }); - - this.operatorTargets.forEach((operator) => { - operator.removeEventListener('change', this.sendForm.bind(this)); - }); - - this.filterValueSelectTargets.forEach((select) => { - select.removeEventListener('change', this.sendForm.bind(this)); - }); - - this.filterValueContainerTargets.forEach((container) => { - container.removeEventListener('change', this.sendForm.bind(this)); - }); - - this.singleDayTargets.forEach((singleDay) => { - singleDay.removeEventListener('change', this.sendForm.bind(this)); - }); - - this.daysTargets.forEach((days) => { - days.removeEventListener('change', this.sendForm.bind(this)); + this.autoReloadTargets.forEach((target) => { + if (target instanceof HTMLInputElement) { + target.removeEventListener('input', this.sendForm.bind(this)); + } else { + target.removeEventListener('change', this.sendForm.bind(this)); + } }); } } From f2be800d7da624ab87e36bd647f1d9d1c8754156 Mon Sep 17 00:00:00 2001 From: Dombi Attila <83396+dombesz@users.noreply.github.com> Date: Sun, 1 Sep 2024 18:42:52 +0300 Subject: [PATCH 04/16] Refactor target finding logic --- .../dynamic/filter/filters-form.controller.ts | 77 ++++++++++++------- 1 file changed, 50 insertions(+), 27 deletions(-) diff --git a/frontend/src/stimulus/controllers/dynamic/filter/filters-form.controller.ts b/frontend/src/stimulus/controllers/dynamic/filter/filters-form.controller.ts index bfb77a1b4515..880ffe72a279 100644 --- a/frontend/src/stimulus/controllers/dynamic/filter/filters-form.controller.ts +++ b/frontend/src/stimulus/controllers/dynamic/filter/filters-form.controller.ts @@ -160,9 +160,9 @@ export default class FiltersFormController extends Controller { } toggleMultiSelect({ params: { filterName } }:{ params:{ filterName:string } }) { - const valueContainer = this.filterValueContainerTargets.find((filterValueContainer) => filterValueContainer.getAttribute('data-filter-name') === filterName); - const singleSelect = this.filterValueSelectTargets.find((selectField) => !selectField.multiple && selectField.getAttribute('data-filter-name') === filterName); - const multiSelect = this.filterValueSelectTargets.find((selectField) => selectField.multiple && selectField.getAttribute('data-filter-name') === filterName); + const valueContainer = this.findTargetByName(filterName, this.filterValueContainerTargets); + const singleSelect = this.findTargetByName(filterName, this.filterValueSelectTargets, (selectField) => !selectField.multiple); + const multiSelect = this.findTargetByName(filterName, this.filterValueSelectTargets, (selectField) => selectField.multiple); if (valueContainer && singleSelect && multiSelect) { if (valueContainer.classList.contains('multi-value')) { const valueToSelect = this.getValueToSelect(multiSelect); @@ -186,13 +186,13 @@ export default class FiltersFormController extends Controller { } addFilter(event:Event) { - const selectedFilterName = (event.target as HTMLSelectElement).value; - const selectedFilter = this.filterTargets.find((filter) => filter.getAttribute('data-filter-name') === selectedFilterName); + const filterName = (event.target as HTMLSelectElement).value; + const selectedFilter = this.findTargetByName(filterName, this.filterTargets); if (selectedFilter) { selectedFilter.classList.remove('hidden'); } - this.disableSelection(); - this.reselectPlaceholderOption(); + this.addFilterSelectTarget.selectedOptions[0].disabled = true; + this.addFilterSelectTarget.selectedIndex = 0; this.setSpacerVisibility(); if (this.performTurboRequestsValue) { @@ -200,16 +200,8 @@ export default class FiltersFormController extends Controller { } } - private disableSelection() { - this.addFilterSelectTarget.selectedOptions[0].setAttribute('disabled', 'disabled'); - } - - private reselectPlaceholderOption() { - this.addFilterSelectTarget.options[0].setAttribute('selected', 'selected'); - } - removeFilter({ params: { filterName } }:{ params:{ filterName:string } }) { - const filterToRemove = this.filterTargets.find((filter) => filter.getAttribute('data-filter-name') === filterName); + const filterToRemove = this.findTargetByName(filterName, this.filterTargets); filterToRemove?.classList.add('hidden'); const selectOptions = Array.from(this.addFilterSelectTarget.options); @@ -256,7 +248,7 @@ export default class FiltersFormController extends Controller { setValueVisibility({ target, params: { filterName } }:{ target:HTMLSelectElement, params:{ filterName:string } }) { const selectedOperator = target.value; - const valueContainer = this.filterValueContainerTargets.find((filterValueContainer) => filterValueContainer.getAttribute('data-filter-name') === filterName); + const valueContainer = this.findTargetByName(filterName, this.filterValueContainerTargets); if (valueContainer) { if (this.noValueOperators.includes(selectedOperator)) { valueContainer.classList.add('hidden'); @@ -360,10 +352,10 @@ export default class FiltersFormController extends Controller { const filters:InternalFilterValue[] = []; advancedFilters.forEach((filter) => { - const filterName = filter.getAttribute('data-filter-name'); + const filterName = filter.getAttribute('data-filter-name') as string; const filterType = filter.getAttribute('data-filter-type'); - const parsedOperator = this.operatorTargets.find((operator) => operator.getAttribute('data-filter-name') === filterName)?.value; - const valueContainer = this.filterValueContainerTargets.find((filterValueContainer) => filterValueContainer.getAttribute('data-filter-name') === filterName); + const parsedOperator = this.findTargetByName(filterName, this.operatorTargets)?.value; + const valueContainer = this.findTargetByName(filterName, this.filterValueContainerTargets); if (valueContainer && filterName && filterType && parsedOperator) { const parsedValue = this.parseFilterValue(valueContainer, filterName, filterType, parsedOperator) as string[]|null; @@ -404,13 +396,12 @@ export default class FiltersFormController extends Controller { private parseFilterValue(valueContainer:HTMLElement, filterName:string, filterType:string, operator:string) { const checkbox = valueContainer.querySelector('input[type="checkbox"]') as HTMLInputElement; - const isAutocomplete = valueContainer.dataset.filterAutocomplete === 'true'; if (checkbox) { return [checkbox.checked ? 't' : 'f']; } - if (isAutocomplete) { + if (valueContainer.dataset.filterAutocomplete === 'true') { return (valueContainer.querySelector('input[name="value"]') as HTMLInputElement)?.value.split(','); } @@ -426,7 +417,7 @@ export default class FiltersFormController extends Controller { return this.parseDateFilterValue(valueContainer, filterName); } - const value = this.simpleValueTargets.find((simpleValueInput) => simpleValueInput.getAttribute('data-filter-name') === filterName)?.value; + const value = this.findTargetByName(filterName, this.simpleValueTargets)?.value; if (value && value.length > 0) { return [value]; @@ -456,16 +447,16 @@ export default class FiltersFormController extends Controller { let value; if (valueContainer.classList.contains('days')) { - const dateValue = this.daysTargets.find((daysField) => daysField.getAttribute('data-filter-name') === filterName)?.value; + const dateValue = this.findTargetByName(filterName, this.daysTargets)?.value; value = _.without([dateValue], ''); } else if (valueContainer.classList.contains('on-date')) { - const dateValue = this.singleDayTargets.find((dateInput) => dateInput.id === `on-date-value-${filterName}`)?.value; + const dateValue = this.findTargetById(`on-date-value-${filterName}`, this.singleDayTargets)?.value; value = _.without([dateValue], ''); } else if (valueContainer.classList.contains('between-dates')) { - const fromValue = this.singleDayTargets.find((dateInput) => dateInput.id === `between-dates-from-value-${filterName}`)?.value; - const toValue = this.singleDayTargets.find((dateInput) => dateInput.id === `between-dates-to-value-${filterName}`)?.value; + const fromValue = this.findTargetById(`between-dates-from-value-${filterName}`, this.singleDayTargets)?.value; + const toValue = this.findTargetById(`between-dates-to-value-${filterName}`, this.singleDayTargets)?.value; value = [fromValue, toValue]; } @@ -474,4 +465,36 @@ export default class FiltersFormController extends Controller { } return null; } + + private findTargetByName( + filterName:string, + targets:T[], + targetFilter?:(target:T) => boolean, + ):T | undefined { + return this.findTargetBy( + filterName, + (target:T) => target.getAttribute('data-filter-name'), + targets, + targetFilter, + ); + } + + private findTargetById( + filterName:string, + targets:T[], + targetFilter?:(target:T) => boolean, + ):T | undefined { + return this.findTargetBy(filterName, (target:T) => target.id, targets, targetFilter); + } + + private findTargetBy( + attributeValue:string, + attributeGetter:(target:T) => string | null, + targets:T[], + targetFilter?:(target:T) => boolean, + ):T | undefined { + return targets.find((target) => { + return attributeGetter(target) === attributeValue && (!targetFilter || targetFilter(target)); + }); + } } From 4f4a229b36267900637a77b998ba1e63417d7a6b Mon Sep 17 00:00:00 2001 From: Dombi Attila <83396+dombesz@users.noreply.github.com> Date: Mon, 2 Sep 2024 18:13:40 +0300 Subject: [PATCH 05/16] Add specs --- spec/features/projects/projects_index_spec.rb | 35 +++++++++++++ spec/support/pages/projects/index.rb | 51 ++++++++++++------- 2 files changed, 69 insertions(+), 17 deletions(-) diff --git a/spec/features/projects/projects_index_spec.rb b/spec/features/projects/projects_index_spec.rb index ff395e1a6c93..76426bfee7ee 100644 --- a/spec/features/projects/projects_index_spec.rb +++ b/spec/features/projects/projects_index_spec.rb @@ -507,6 +507,16 @@ def load_and_open_filters(user) projects_page.remove_filter("name_and_identifier") projects_page.expect_projects_listed(project, development_project, public_project) + # Filter on model attribute 'name' triggered by keyboard input event instead of change + projects_page.filter_by_name_and_identifier("Plain", send_keys: true) + wait_for_reload + + projects_page.expect_projects_listed(project) + projects_page.expect_projects_not_listed(development_project, public_project) + + projects_page.remove_filter("name_and_identifier") + projects_page.expect_projects_listed(project, development_project, public_project) + # Filter on model attribute 'identifier' projects_page.filter_by_name_and_identifier("plain-project") wait_for_reload @@ -789,6 +799,18 @@ def load_and_open_filters(user) expect(page).to have_text(project_created_on_today.name) expect(page).to have_no_text(project_created_on_fixed_date.name) + # created on 'less than days ago' triggered by an input event + projects_page.remove_filter("created_at") + projects_page.set_filter("created_at", + "Created on", + "less than days ago", + ["1"], + send_keys: true) + wait_for_reload + + expect(page).to have_text(project_created_on_today.name) + expect(page).to have_no_text(project_created_on_fixed_date.name) + # created on 'more than days ago' projects_page.remove_filter("created_at") @@ -801,6 +823,19 @@ def load_and_open_filters(user) expect(page).to have_text(project_created_on_fixed_date.name) expect(page).to have_no_text(project_created_on_today.name) + # created on 'more than days ago' + projects_page.remove_filter("created_at") + + projects_page.set_filter("created_at", + "Created on", + "more than days ago", + ["1"], + send_keys: true) + wait_for_reload + + expect(page).to have_text(project_created_on_fixed_date.name) + expect(page).to have_no_text(project_created_on_today.name) + # created on 'between' projects_page.remove_filter("created_at") diff --git a/spec/support/pages/projects/index.rb b/spec/support/pages/projects/index.rb index 9f0933c88d73..c5c81901eeea 100644 --- a/spec/support/pages/projects/index.rb +++ b/spec/support/pages/projects/index.rb @@ -207,26 +207,26 @@ def filter_by_membership(value) wait_for_reload end - def filter_by_name_and_identifier(value) - set_name_and_identifier_filter([value]) + def filter_by_name_and_identifier(value, send_keys: false) + set_name_and_identifier_filter([value], send_keys:) wait_for_reload end - def set_filter(name, human_name, human_operator = nil, values = []) + def set_filter(name, human_name, human_operator = nil, values = [], send_keys: false) if name == "name_and_identifier" - set_simple_filter(name, values) + set_simple_filter(name, values, send_keys:) else - set_advanced_filter(name, human_name, human_operator, values) + set_advanced_filter(name, human_name, human_operator, values, send_keys:) end end - def set_simple_filter(_name, values) + def set_simple_filter(_name, values, send_keys: false) return unless values.any? - set_name_and_identifier_filter(values) # This is the only one simple filter at the moment. + set_name_and_identifier_filter(values, send_keys:) # This is the only one simple filter at the moment. end - def set_advanced_filter(name, human_name, human_operator = nil, values = []) + def set_advanced_filter(name, human_name, human_operator = nil, values = [], send_keys: false) select human_name, from: "add_filter_select" selected_filter = page.find("li[data-filter-name='#{name}']") select(human_operator, from: "operator") unless boolean_filter?(name) @@ -238,7 +238,7 @@ def set_advanced_filter(name, human_name, human_operator = nil, values = []) set_toggle_filter(values) elsif name == "created_at" select(human_operator, from: "operator") - set_created_at_filter(human_operator, values) + set_created_at_filter(human_operator, values, send_keys:) elsif /cf_\d+/.match?(name) select(human_operator, from: "operator") set_custom_field_filter(selected_filter, human_operator, values) @@ -269,21 +269,34 @@ def set_toggle_filter(values) end end - def set_name_and_identifier_filter(values) - fill_in "name_and_identifier", with: values.first + def set_name_and_identifier_filter(values, send_keys: false) + if send_keys + find_field("name_and_identifier").send_keys values.first + else + fill_in "name_and_identifier", with: values.first + end end - def set_created_at_filter(human_operator, values) + def set_created_at_filter(human_operator, values, send_keys: false) case human_operator when "on", "less than days ago", "more than days ago", "days ago" - fill_in "value", with: values.first + if send_keys + find_field("value").send_keys values.first + else + fill_in "value", with: values.first + end when "between" - fill_in "from_value", with: values.first - fill_in "to_value", with: values.second + if send_keys + find_field("from_value").send_keysvalues.first + find_field("to_value").send_keys values.second + else + fill_in "from_value", with: values.first + fill_in "to_value", with: values.second + end end end - def set_custom_field_filter(selected_filter, human_operator, values) + def set_custom_field_filter(selected_filter, human_operator, values, send_keys: false) if selected_filter[:"data-filter-type"] == "list_optional" if values.size == 1 value_select = find('.single-select select[name="value"]') @@ -291,7 +304,11 @@ def set_custom_field_filter(selected_filter, human_operator, values) end elsif selected_filter[:"data-filter-type"] == "date" if human_operator == "on" - fill_in "value", with: values.first + if send_keys + find_field("value").send_keys values.first + else + fill_in "value", with: values.first + end end end end From d1bffeba22fa0a045e0908ebc7c15ea5933e73c9 Mon Sep 17 00:00:00 2001 From: ulferts Date: Mon, 2 Sep 2024 14:46:17 +0200 Subject: [PATCH 06/16] update teaser text --- config/locales/js-en.yml | 12 ++++++------ .../homescreen/blocks/new-features.component.ts | 4 ++-- .../images/{14_4_features.png => 14_5_features.png} | Bin 3 files changed, 8 insertions(+), 8 deletions(-) rename frontend/src/assets/images/{14_4_features.png => 14_5_features.png} (100%) diff --git a/config/locales/js-en.yml b/config/locales/js-en.yml index aeb412261ebc..51e332ecbc7e 100644 --- a/config/locales/js-en.yml +++ b/config/locales/js-en.yml @@ -405,16 +405,16 @@ en: learn_about: "Learn more about the new features" # Include the version to invalidate outdated translations in other locales. # Otherwise, e.g. chinese might still have the translations for 10.0 in the 12.0 release. - "14_4": + "14_5": standard: new_features_html: > The release contains various new features and improvements, such as:
    -
  • Dark mode option in personal settings
  • -
  • Separate permissions for viewing and editing on project attributes
  • -
  • Improved status-based progress reporting
  • -
  • Connection validation for Nextcloud storages
  • -
  • More filter options for project lists
  • +
  • Keep and restore local versions of WYSIWYG content changes.
  • +
  • Enable a storage for multiple projects at once.
  • +
  • Export work packages in an updated modal with additional settings.
  • +
  • Display custom field columns/filters in project lists also in the Community Edition.
  • +
  • Support CloudFlare Turnstile as Captcha.
ical_sharing_modal: diff --git a/frontend/src/app/features/homescreen/blocks/new-features.component.ts b/frontend/src/app/features/homescreen/blocks/new-features.component.ts index 2079a0ed843d..62ae851dbcf5 100644 --- a/frontend/src/app/features/homescreen/blocks/new-features.component.ts +++ b/frontend/src/app/features/homescreen/blocks/new-features.component.ts @@ -33,9 +33,9 @@ import { I18nService } from 'core-app/core/i18n/i18n.service'; import { imagePath } from 'core-app/shared/helpers/images/path-helper'; // The key used in the I18n files to distinguish between versions. -const OpVersionI18n = '14_4'; +const OpVersionI18n = '14_5'; -const OpReleaseURL = 'https://www.openproject.org/docs/release-notes/14-4-0/'; +const OpReleaseURL = 'https://www.openproject.org/docs/release-notes/14-5-0/'; /** Update the teaser image to the next version */ const featureTeaserImage = `${OpVersionI18n}_features.png`; diff --git a/frontend/src/assets/images/14_4_features.png b/frontend/src/assets/images/14_5_features.png similarity index 100% rename from frontend/src/assets/images/14_4_features.png rename to frontend/src/assets/images/14_5_features.png From 9d58b3873356523764e1e131e0255e921ac1b8fe Mon Sep 17 00:00:00 2001 From: ulferts Date: Wed, 4 Sep 2024 09:26:24 +0200 Subject: [PATCH 07/16] update teaser image --- frontend/src/assets/images/14_5_features.png | Bin 20998 -> 37117 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/frontend/src/assets/images/14_5_features.png b/frontend/src/assets/images/14_5_features.png index c8b671176c169cf2c02eb11345238dc1829decd3..f8defaf793c67d9317345d5d3fa9242d72931cea 100644 GIT binary patch literal 37117 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 literal 20998 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 From dfeed5eb0716e784c27e5115de230593c4d9a7c3 Mon Sep 17 00:00:00 2001 From: Henriette Darge Date: Tue, 3 Sep 2024 14:08:25 +0200 Subject: [PATCH 08/16] Add arrows for the UnderlineNav of the split screen to navigate without a scrollbar. We actively hide the scrollbar to avoid the scrollbar overlapping the active element --- .../details/tab_component.html.erb | 39 ++++++++++++- .../work_packages/details/tab_component.sass | 3 + config/locales/en.yml | 2 + .../src/global_styles/primer/_overrides.sass | 9 +-- .../work-packages/details/tabs.controller.ts | 56 +++++++++++++++++++ 5 files changed, 99 insertions(+), 10 deletions(-) create mode 100644 frontend/src/stimulus/controllers/dynamic/work-packages/details/tabs.controller.ts diff --git a/app/components/work_packages/details/tab_component.html.erb b/app/components/work_packages/details/tab_component.html.erb index 6b99f5f2b57c..f684953bf5cd 100644 --- a/app/components/work_packages/details/tab_component.html.erb +++ b/app/components/work_packages/details/tab_component.html.erb @@ -1,12 +1,35 @@ <%= - flex_layout(classes: "op-work-package-details-tab-component") do |flex| + flex_layout(classes: "op-work-package-details-tab-component", data: { + "application-target": "dynamic", + controller: "work-packages--details--tabs" + }) do |flex| + flex.with_column(classes: "op-work-package-details-tab-component--action") do + render(Primer::Beta::IconButton.new(icon: :"chevron-left", + tag: :a, + scheme: :invisible, + data: { + action: "click->work-packages--details--tabs#scrollLeft" + }, + aria: { label: I18n.t(:label_scroll_left) })) + end + + flex.with_column(flex: 1, classes: "op-work-package-details-tab-component--tabs", test_selector: "wp-details-tab-component--tabs") do - render(Primer::Alpha::UnderlineNav.new(align: :left, label: "Tabs", classes: "op-primer-adjustment--UnderlineNav_spaciousLeft")) do |component| + render(Primer::Alpha::UnderlineNav.new(align: :left, + label: "Tabs", + data: { + "work-packages--details--tabs-target": "underlineNav", + })) do |component| menu_items.each do |node| component.with_tab(selected: @tab == node.name, href: helpers.url_for_with_params(**node.url), test_selector: "wp-details-tab-component--tab-#{node.name}", - data: { turbo: true, turbo_stream: true, turbo_action: "replace" } + data: { + turbo: true, + turbo_stream: true, + turbo_action: "replace", + "work-packages--details--tabs-target": @tab == node.name ? "activeElement" : "" + } ) do |c| c.with_text { t("js.work_packages.tabs.#{node.name}") } count = node.badge(work_package:).to_i @@ -16,6 +39,16 @@ end end + flex.with_column(classes: "op-work-package-details-tab-component--action") do + render(Primer::Beta::IconButton.new(icon: :"chevron-right", + tag: :a, + scheme: :invisible, + data: { + action: "click->work-packages--details--tabs#scrollRight" + }, + aria: { label: I18n.t(:label_scroll_right) })) + end + flex.with_column(classes: "op-work-package-details-tab-component--action") do render(Primer::Beta::IconButton.new(icon: :"screen-full", tag: :a, diff --git a/app/components/work_packages/details/tab_component.sass b/app/components/work_packages/details/tab_component.sass index 23c2a467bf4c..4a6fdeb48444 100644 --- a/app/components/work_packages/details/tab_component.sass +++ b/app/components/work_packages/details/tab_component.sass @@ -14,3 +14,6 @@ &:last-of-type padding-right: 10px + + &:first-of-type + padding-left: 5px diff --git a/config/locales/en.yml b/config/locales/en.yml index 93b889d88728..6aa13ce5dd9e 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -2484,6 +2484,8 @@ en: label_role_plural: "Roles" label_role_search: "Assign role to new members" label_scm: "SCM" + label_scroll_left: "Scroll left" + label_scroll_right: "Scroll right" label_search: "Search" label_search_by_name: "Search by name" label_send_information: "Send new credentials to the user" diff --git a/frontend/src/global_styles/primer/_overrides.sass b/frontend/src/global_styles/primer/_overrides.sass index e74b5c0e2690..db99d3eeaa4e 100644 --- a/frontend/src/global_styles/primer/_overrides.sass +++ b/frontend/src/global_styles/primer/_overrides.sass @@ -46,15 +46,10 @@ action-menu margin-left: 0 .UnderlineNav - @include styled-scroll-bar + @include no-visible-scroll-bar + scroll-behavior: smooth margin-bottom: 12px - &-body - margin-left: 12px - - &.op-primer-adjustment--UnderlineNav_spaciousLeft - padding-left: 8px - /* Remove margin-left: 2rem from Breadcrumbs */ #breadcrumb, page-header, diff --git a/frontend/src/stimulus/controllers/dynamic/work-packages/details/tabs.controller.ts b/frontend/src/stimulus/controllers/dynamic/work-packages/details/tabs.controller.ts new file mode 100644 index 000000000000..243e588b61a1 --- /dev/null +++ b/frontend/src/stimulus/controllers/dynamic/work-packages/details/tabs.controller.ts @@ -0,0 +1,56 @@ +/* + * -- copyright + * OpenProject is an open source project management software. + * Copyright (C) the OpenProject GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 3. + * + * OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: + * Copyright (C) 2006-2013 Jean-Philippe Lang + * Copyright (C) 2010-2013 the ChiliProject Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * See COPYRIGHT and LICENSE files for more details. + * ++ + */ + +import { Controller } from '@hotwired/stimulus'; + +export default class TabsController extends Controller { + static targets = [ + 'underlineNav', + 'activeElement', + ]; + + declare readonly underlineNavTarget:HTMLElement; + + declare readonly activeElementTarget:HTMLElement; + + connect() { + if (this.activeElementTarget.parentElement) { + this.activeElementTarget.parentElement.scrollIntoView(); + } + } + + scrollLeft() { + this.underlineNavTarget.scrollBy(-100, 0); + } + + scrollRight() { + this.underlineNavTarget.scrollBy(100, 0); + } +} From 95c04030183701e143f0c6321c8769582ebc0c11 Mon Sep 17 00:00:00 2001 From: as-op Date: Wed, 4 Sep 2024 10:45:04 +0200 Subject: [PATCH 09/16] feat(csv-export): description column optional --- .../csv/export_settings_component.html.erb | 25 ++++++++--- .../xls/export_settings_component.html.erb | 28 +++++++----- app/models/work_package/exports/csv.rb | 8 ++++ spec/features/work_packages/export_spec.rb | 19 +++++++- .../exporter/csv_integration_spec.rb | 44 ++++++++++++++----- 5 files changed, 94 insertions(+), 30 deletions(-) diff --git a/app/components/work_packages/exports/csv/export_settings_component.html.erb b/app/components/work_packages/exports/csv/export_settings_component.html.erb index 4cc6a176a260..dddd90a2649b 100644 --- a/app/components/work_packages/exports/csv/export_settings_component.html.erb +++ b/app/components/work_packages/exports/csv/export_settings_component.html.erb @@ -1,5 +1,20 @@ -<%= render WorkPackages::Exports::ColumnSelectionComponent.new( - query, - "columns-select-export-csv", - I18n.t("export.dialog.columns.input_caption_table") -) %> +<%= flex_layout do |container| %> + <%= container.with_row do |_columns| %> + <%= render WorkPackages::Exports::ColumnSelectionComponent.new( + query, + "columns-select-export-csv", + I18n.t("export.dialog.columns.input_caption_table") + ) %> + <% end %> + <%= container.with_row do |_csv_include_description| %> + <%= render OpenProject::Common::DividerComponent.new %> + <%= render(Primer::Alpha::CheckBox.new( + id: "show_descriptions_csv", + name: "show_descriptions", + value: "true", + unchecked_value: "false", + label: I18n.t("export.dialog.xls.include_descriptions.label"), + caption: I18n.t("export.dialog.xls.include_descriptions.caption"), + visually_hide_label: false)) %> + <% end %> +<% end %> diff --git a/app/components/work_packages/exports/xls/export_settings_component.html.erb b/app/components/work_packages/exports/xls/export_settings_component.html.erb index 0465d0db5488..7909c0191895 100644 --- a/app/components/work_packages/exports/xls/export_settings_component.html.erb +++ b/app/components/work_packages/exports/xls/export_settings_component.html.erb @@ -8,20 +8,24 @@ <% end %> <%= container.with_row do |_xls_include_relations| %> <%= render OpenProject::Common::DividerComponent.new(mt: 2) %> - <%= render(Primer::Alpha::CheckBox.new(name: "show_relations", - value: "true", - unchecked_value: "false", - label: I18n.t("export.dialog.xls.include_relations.label"), - caption: I18n.t("export.dialog.xls.include_relations.caption"), - visually_hide_label: false)) %> + <%= render(Primer::Alpha::CheckBox.new( + id: "show_relations_xls", + name: "show_relations", + value: "true", + unchecked_value: "false", + label: I18n.t("export.dialog.xls.include_relations.label"), + caption: I18n.t("export.dialog.xls.include_relations.caption"), + visually_hide_label: false)) %> <% end %> <%= container.with_row do |_xls_include_description| %> <%= render OpenProject::Common::DividerComponent.new %> - <%= render(Primer::Alpha::CheckBox.new(name: "show_descriptions", - value: "true", - unchecked_value: "false", - label: I18n.t("export.dialog.xls.include_descriptions.label"), - caption: I18n.t("export.dialog.xls.include_descriptions.caption"), - visually_hide_label: false)) %> + <%= render(Primer::Alpha::CheckBox.new( + id: "show_descriptions_xls", + name: "show_descriptions", + value: "true", + unchecked_value: "false", + label: I18n.t("export.dialog.xls.include_descriptions.label"), + caption: I18n.t("export.dialog.xls.include_descriptions.caption"), + visually_hide_label: false)) %> <% end %> <% end %> diff --git a/app/models/work_package/exports/csv.rb b/app/models/work_package/exports/csv.rb index 052dd3f82925..a16a5309f1e8 100644 --- a/app/models/work_package/exports/csv.rb +++ b/app/models/work_package/exports/csv.rb @@ -39,11 +39,19 @@ def title end def csv_headers + return super unless with_descriptions + super + [WorkPackage.human_attribute_name(:description)] end + def with_descriptions + ActiveModel::Type::Boolean.new.cast(options[:show_descriptions]) + end + # fetch all row values def csv_row(work_package) + return super unless with_descriptions + super.tap do |row| if row.any? row << if work_package.description diff --git a/spec/features/work_packages/export_spec.rb b/spec/features/work_packages/export_spec.rb index 8076a9cf3782..8c16a1bd3b4d 100644 --- a/spec/features/work_packages/export_spec.rb +++ b/spec/features/work_packages/export_spec.rb @@ -163,10 +163,25 @@ def export! before do open_export_dialog! + sleep 1 end - it "exports a csv" do - export! + context "with descriptions" do + let(:expected_params) { default_expected_params.merge({ show_descriptions: "true" }) } + + it "exports a csv" do + check I18n.t("export.dialog.xls.include_descriptions.label") + export! + end + end + + context "without descriptions" do + let(:expected_params) { default_expected_params.merge({ show_descriptions: "false" }) } + + it "exports a csv" do + uncheck I18n.t("export.dialog.xls.include_descriptions.label") + export! + end end end diff --git a/spec/models/work_package/exporter/csv_integration_spec.rb b/spec/models/work_package/exporter/csv_integration_spec.rb index da298f40d240..d09709859759 100644 --- a/spec/models/work_package/exporter/csv_integration_spec.rb +++ b/spec/models/work_package/exporter/csv_integration_spec.rb @@ -34,6 +34,7 @@ end let(:project) { create(:project) } + let(:options) { { show_descriptions: true } } let(:type_a) { create(:type, name: "Type A") } let(:type_b) { create(:type, name: "Type B") } let(:wp1) { create(:work_package, project:, done_ratio: 25, subject: "WP1", type: type_a, id: 1) } @@ -45,7 +46,7 @@ member_with_permissions: { project => %i(view_work_packages) }) end let(:instance) do - described_class.new(query) + described_class.new(query, options) end let(:work_packages) do [wp1, wp2, wp3, wp4] @@ -74,19 +75,40 @@ ) end - it "performs a successful export" do - work_package.reload + context "when description is included" do + it "performs a successful export" do + work_package.reload - data = CSV.parse instance.export!.content + data = CSV.parse instance.export!.content - expect(data.size).to eq(2) - expect(data.last).to include(work_package.type.name) - expect(data.last).to include(work_package.subject) - expect(data.last).to include(work_package.description) - expect(data.last).to include(user.name) - expect(data.last).to include(work_package.updated_at.localtime.strftime("%m/%d/%Y %I:%M %p")) - expect(data.last).to include("· Σ 15h") + expect(data.size).to eq(2) + expect(data.last).to include(work_package.type.name) + expect(data.last).to include(work_package.subject) + expect(data.last).to include(work_package.description) + expect(data.last).to include(user.name) + expect(data.last).to include(work_package.updated_at.localtime.strftime("%m/%d/%Y %I:%M %p")) + expect(data.last).to include("· Σ 15h") + end + end + + context "when description is not included" do + let(:options) { { show_descriptions: false } } + + it "performs a successful export" do + work_package.reload + + data = CSV.parse instance.export!.content + + expect(data.size).to eq(2) + expect(data.last).to include(work_package.type.name) + expect(data.last).to include(work_package.subject) + expect(data.last).to_not include(work_package.description) + expect(data.last).to include(user.name) + expect(data.last).to include(work_package.updated_at.localtime.strftime("%m/%d/%Y %I:%M %p")) + expect(data.last).to include("· Σ 15h") + end end + end context "when the query is grouped" do From 65d54aae2329d7541f3482ee45916380ced59284 Mon Sep 17 00:00:00 2001 From: as-op Date: Wed, 4 Sep 2024 12:18:47 +0200 Subject: [PATCH 10/16] obey rubocop --- spec/models/work_package/exporter/csv_integration_spec.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/spec/models/work_package/exporter/csv_integration_spec.rb b/spec/models/work_package/exporter/csv_integration_spec.rb index d09709859759..f2c0ef5e4163 100644 --- a/spec/models/work_package/exporter/csv_integration_spec.rb +++ b/spec/models/work_package/exporter/csv_integration_spec.rb @@ -102,13 +102,12 @@ expect(data.size).to eq(2) expect(data.last).to include(work_package.type.name) expect(data.last).to include(work_package.subject) - expect(data.last).to_not include(work_package.description) + expect(data.last).not_to include(work_package.description) expect(data.last).to include(user.name) expect(data.last).to include(work_package.updated_at.localtime.strftime("%m/%d/%Y %I:%M %p")) expect(data.last).to include("· Σ 15h") end end - end context "when the query is grouped" do From 32bafc04858d1697a3fd4078835c6975d2051a00 Mon Sep 17 00:00:00 2001 From: Behrokh Satarnejad Date: Wed, 4 Sep 2024 12:37:57 +0200 Subject: [PATCH 11/16] add a size for action menu --- .../my/two_factor_devices/index.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/two_factor_authentication/app/views/two_factor_authentication/my/two_factor_devices/index.html.erb b/modules/two_factor_authentication/app/views/two_factor_authentication/my/two_factor_devices/index.html.erb index 2c3e110bf853..0a4b97af0376 100644 --- a/modules/two_factor_authentication/app/views/two_factor_authentication/my/two_factor_devices/index.html.erb +++ b/modules/two_factor_authentication/app/views/two_factor_authentication/my/two_factor_devices/index.html.erb @@ -10,7 +10,7 @@ <%= render(Primer::OpenProject::SubHeader.new) do |subheader| subheader.with_action_component do - render(Primer::Alpha::ActionMenu.new(anchor_align: :end)) do |menu| + render(Primer::Alpha::ActionMenu.new(anchor_align: :end, size: :small)) do |menu| menu.with_show_button(scheme: :primary, test_selector: "two_factor_authentication_devices_button", aria: { label: t('two_factor_authentication.label_device') }) do |button| From 8fe4a222148f6708c70e44ac5a834163174507f2 Mon Sep 17 00:00:00 2001 From: as-op Date: Wed, 4 Sep 2024 12:52:04 +0200 Subject: [PATCH 12/16] fix(job-status-modal): after user clicked the redirect, closing the dialog no longer navigates back (from the navigated redirect) --- .../dynamic/job-status-polling.controller.ts | 12 ++++++++++-- .../job_status/dialog/body_component.html.erb | 1 + modules/job_status/spec/features/job_status_spec.rb | 8 ++++++++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/frontend/src/stimulus/controllers/dynamic/job-status-polling.controller.ts b/frontend/src/stimulus/controllers/dynamic/job-status-polling.controller.ts index ce06ad9bcaea..25b7539301c6 100644 --- a/frontend/src/stimulus/controllers/dynamic/job-status-polling.controller.ts +++ b/frontend/src/stimulus/controllers/dynamic/job-status-polling.controller.ts @@ -10,6 +10,7 @@ export default class JobStatusPollingController extends Controller declare readonly frameTarget:FrameElement; interval:ReturnType; + userInteraction:boolean = false; connect() { this.interval = setInterval(() => this.frameTarget.reload(), 2000); @@ -17,7 +18,7 @@ export default class JobStatusPollingController extends Controller disconnect() { this.stopPolling(); - if (this.backOnCloseValue) { + if (this.backOnCloseValue && !this.userInteraction) { window.history.back(); } } @@ -39,7 +40,14 @@ export default class JobStatusPollingController extends Controller setTimeout(() => element.click(), 50); } + redirectClick(_:Event) { + this.userInteraction = true; + } + redirectTargetConnected(element:HTMLLinkElement) { - setTimeout(() => { window.location.href = element.href; }, 2000); + setTimeout(() => { + this.userInteraction = true; + window.location.href = element.href; + }, 2000); } } diff --git a/modules/job_status/app/components/job_status/dialog/body_component.html.erb b/modules/job_status/app/components/job_status/dialog/body_component.html.erb index 9fd33a19a808..05faf32ce7ce 100644 --- a/modules/job_status/app/components/job_status/dialog/body_component.html.erb +++ b/modules/job_status/app/components/job_status/dialog/body_component.html.erb @@ -19,6 +19,7 @@ flex.with_row { render(Primer::Beta::Link.new( href: redirect_url, data: { + action: 'job-status-polling#redirectClick', "job-status-polling-target": job_errors.present? ? nil : "redirect" } )) { I18n.t('job_status_dialog.redirect_link') } } diff --git a/modules/job_status/spec/features/job_status_spec.rb b/modules/job_status/spec/features/job_status_spec.rb index f4e7ef984424..da7461a180a9 100644 --- a/modules/job_status/spec/features/job_status_spec.rb +++ b/modules/job_status/spec/features/job_status_spec.rb @@ -88,5 +88,13 @@ expect(page).to have_content "Some error" expect(page).to have_css("a[href='#{home_url}']", text: "Please click here to continue") end + + it "does not navigate back after user clicked the redirect" do + visit "/projects" + visit "/job_statuses/#{status.job_id}" + click_on I18n.t('job_status_dialog.redirect_link') + + expect(page).to have_current_path(home_path, wait: 10) + end end end From 0fec37dd3be6dfd8777862ee8657a3c7bbf5b501 Mon Sep 17 00:00:00 2001 From: as-op Date: Wed, 4 Sep 2024 13:02:03 +0200 Subject: [PATCH 13/16] obey eslint --- modules/job_status/spec/features/job_status_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/job_status/spec/features/job_status_spec.rb b/modules/job_status/spec/features/job_status_spec.rb index da7461a180a9..1b1eeec07c4f 100644 --- a/modules/job_status/spec/features/job_status_spec.rb +++ b/modules/job_status/spec/features/job_status_spec.rb @@ -92,7 +92,7 @@ it "does not navigate back after user clicked the redirect" do visit "/projects" visit "/job_statuses/#{status.job_id}" - click_on I18n.t('job_status_dialog.redirect_link') + click_on I18n.t("job_status_dialog.redirect_link") expect(page).to have_current_path(home_path, wait: 10) end From aadd5b22f8463e0629bd7233deed1c58146a6781 Mon Sep 17 00:00:00 2001 From: Markus Kahl Date: Wed, 4 Sep 2024 15:18:47 +0100 Subject: [PATCH 14/16] fix github rate limit issue using authentication allows for a higher rate limit (5000 per hour instead of 60) reducing number of requests to mitigate the issue further --- .../workers/cron/check_deploy_status_job.rb | 36 +++++- .../cron/check_deploy_status_job_spec.rb | 122 +++++++++++++++++- 2 files changed, 156 insertions(+), 2 deletions(-) diff --git a/modules/github_integration/app/workers/cron/check_deploy_status_job.rb b/modules/github_integration/app/workers/cron/check_deploy_status_job.rb index 18637859530d..6a27e3e5bd65 100644 --- a/modules/github_integration/app/workers/cron/check_deploy_status_job.rb +++ b/modules/github_integration/app/workers/cron/check_deploy_status_job.rb @@ -28,6 +28,8 @@ module Cron class CheckDeployStatusJob < ApplicationJob + class DeployCheckAccessTokenExpired < StandardError; end + include OpenProject::GithubIntegration::NotificationHandler::Helper priority_number :low @@ -55,7 +57,19 @@ def deploy_targets def pull_requests GithubPullRequest .closed + .where(repository: "opf/openproject") + .where(merged: true) .where.not(merge_commit_sha: nil) + .where("merged_at > ?", look_back_cutoff_date) + end + + ## + # These PRs have been merged but seemingly not been deployed within a month. + # It might be that they were merged into a different branch (not dev or release) via rebase. + # + # What ever it may be, at this point we're going to give up and not check on those anymore. + def look_back_cutoff_date + Time.zone.today - 1.month end def check_deploy_status(deploy_target, pull_request, core_sha) @@ -112,6 +126,13 @@ def comment_user user_id ? User.find(user_id) : User.system end + ## + # With an access token configured, requests are authenticated which increases the rate limit + # from 60 per hour to 5000 per hour. + def github_access_token + plugin_settings[:github_access_token].presence + end + def plugin_settings Hash(Setting.plugin_openproject_github_integration).with_indifferent_access end @@ -183,6 +204,9 @@ def handle_request_error(res, error_prefix) OpenProject.logger.error "#{error_prefix}: #{res.error}" elsif res.status == 404 OpenProject.logger.error "#{error_prefix}: not found" + elsif res.status == 401 + # raise so we notice this in AppSignal and can fix it + raise DeployCheckAccessTokenExpired, "response: #{res.body}" elsif res.status != 200 OpenProject.logger.error "#{error_prefix}: #{res.body}" else @@ -193,7 +217,17 @@ def handle_request_error(res, error_prefix) end def compare_commits_request(sha_a, sha_b) - OpenProject.httpx.get(compare_commits_url(sha_a, sha_b)) + authenticated_request(OpenProject.httpx).get(compare_commits_url(sha_a, sha_b)) + end + + def authenticated_request(httpx) + return httpx if github_access_token.blank? + + httpx.with( + headers: { + "Authorization" => "Bearer #{github_access_token}" + } + ) end def compare_commits_url(sha_a, sha_b) diff --git a/modules/github_integration/spec/workers/cron/check_deploy_status_job_spec.rb b/modules/github_integration/spec/workers/cron/check_deploy_status_job_spec.rb index 792319506673..754952e99a1b 100644 --- a/modules/github_integration/spec/workers/cron/check_deploy_status_job_spec.rb +++ b/modules/github_integration/spec/workers/cron/check_deploy_status_job_spec.rb @@ -37,10 +37,130 @@ let(:work_package) { create(:work_package) } let(:deploy_target) { create(:deploy_target, api_key:) } - let(:pull_request) { create(:github_pull_request, work_packages: [work_package], state: :closed, merge_commit_sha:) } + let(:pull_request) do + create :github_pull_request, pull_request_attributes.merge(pull_request_attribute_override) + end + + let(:pull_request_attributes) do + { + work_packages: [work_package], + state: :closed, + repository: "opf/openproject", + merge_commit_sha:, + merged: true, + merged_at: Date.yesterday + } + end + + let(:pull_request_attribute_override) { {} } let(:job) { described_class.new } + describe "#pull_requests" do + before do + pull_request + end + + context "with matching PRs" do + it "includes them" do + expect(job.pull_requests).to include pull_request + end + end + + context "with not merged PRs" do + let(:pull_request_attribute_override) { { merged: false } } + + it "does not include them" do + expect(job.pull_requests).not_to include pull_request + end + end + + context "with PRs from other repositories" do + let(:pull_request_attribute_override) { { repository: "opf/website" } } + + it "does not include them" do + expect(job.pull_requests).not_to include pull_request + end + end + + context "with PRs past the use-by date" do + let(:pull_request_attribute_override) { { merged_at: Date.today - 2.months } } + + it "does not include them" do + expect(job.pull_requests).not_to include pull_request + end + end + end + + describe "#commit_contains?", :webmock do + let(:result) { job.commit_contains? core_sha, merge_commit_sha } + let(:response) { {} } + + let(:request_url) { "https://api.github.com/repos/opf/openproject/compare/#{core_sha}...#{merge_commit_sha}" } + let(:request_headers) do + { + "Accept" => "*/*", + "Accept-Encoding" => "gzip, deflate", + "User-Agent" => "httpx.rb/1.3.1" + } + end + + before do + stub_request(:get, request_url) + .with(headers: request_headers) + .to_return(status: 200, body: response.to_json, headers: {}) + end + + context "with a response not indicating the commits are related" do + it "is false" do + expect(result).to eq false + end + end + + context "with a response indicating the commits are related" do + let(:response) do + { + status: "behind", + ahead_by: 0, + behind_by: 42 + } + end + + it "is true" do + expect(result).to eq true + end + end + + context( + "with a github access token configured", + with_settings: { + plugin_openproject_github_integration: { + github_access_token: "pat_42" + } + } + ) do + it "sends an authenticated request" do + result + + expect(WebMock) + .to have_requested(:get, request_url) + .with(headers: { "Authorization" => "Bearer pat_42" }) + end + end + + context "with an invalid access token" do + before do + stub_request(:get, request_url) + .with(headers: request_headers) + .to_return(status: 401, body: response.to_json, headers: { message: "invalid token" }) + end + + it "raises an error" do + expect { result }.to raise_error(Cron::CheckDeployStatusJob::DeployCheckAccessTokenExpired) + end + end + end + context "with no prior checks and the same deployed sha" do before do deploy_target From 4bb6eac35950adebbc08a34c6d2be8679eb3be5b Mon Sep 17 00:00:00 2001 From: OpenProject Actions CI Date: Thu, 5 Sep 2024 03:09:36 +0000 Subject: [PATCH 15/16] update locales from crowdin [ci skip] --- config/locales/crowdin/fr.yml | 12 ++-- config/locales/crowdin/js-af.yml | 4 +- config/locales/crowdin/js-ar.yml | 4 +- config/locales/crowdin/js-az.yml | 4 +- config/locales/crowdin/js-be.yml | 4 +- config/locales/crowdin/js-bg.yml | 4 +- config/locales/crowdin/js-ca.yml | 4 +- config/locales/crowdin/js-ckb-IR.yml | 4 +- config/locales/crowdin/js-cs.yml | 4 +- config/locales/crowdin/js-da.yml | 4 +- config/locales/crowdin/js-de.yml | 4 +- config/locales/crowdin/js-el.yml | 4 +- config/locales/crowdin/js-eo.yml | 4 +- config/locales/crowdin/js-es.yml | 4 +- config/locales/crowdin/js-et.yml | 4 +- config/locales/crowdin/js-eu.yml | 4 +- config/locales/crowdin/js-fa.yml | 4 +- config/locales/crowdin/js-fi.yml | 4 +- config/locales/crowdin/js-fil.yml | 4 +- config/locales/crowdin/js-fr.yml | 4 +- config/locales/crowdin/js-he.yml | 4 +- config/locales/crowdin/js-hi.yml | 4 +- config/locales/crowdin/js-hr.yml | 4 +- config/locales/crowdin/js-hu.yml | 4 +- config/locales/crowdin/js-id.yml | 4 +- config/locales/crowdin/js-it.yml | 4 +- config/locales/crowdin/js-ja.yml | 4 +- config/locales/crowdin/js-ka.yml | 4 +- config/locales/crowdin/js-kk.yml | 4 +- config/locales/crowdin/js-ko.yml | 4 +- config/locales/crowdin/js-lt.yml | 4 +- config/locales/crowdin/js-lv.yml | 4 +- config/locales/crowdin/js-mn.yml | 4 +- config/locales/crowdin/js-ms.yml | 4 +- config/locales/crowdin/js-ne.yml | 4 +- config/locales/crowdin/js-nl.yml | 4 +- config/locales/crowdin/js-no.yml | 4 +- config/locales/crowdin/js-pl.yml | 4 +- config/locales/crowdin/js-pt-BR.yml | 4 +- config/locales/crowdin/js-pt-PT.yml | 4 +- config/locales/crowdin/js-ro.yml | 4 +- config/locales/crowdin/js-ru.yml | 6 +- config/locales/crowdin/js-rw.yml | 4 +- config/locales/crowdin/js-si.yml | 4 +- config/locales/crowdin/js-sk.yml | 4 +- config/locales/crowdin/js-sl.yml | 4 +- config/locales/crowdin/js-sr.yml | 4 +- config/locales/crowdin/js-sv.yml | 4 +- config/locales/crowdin/js-th.yml | 4 +- config/locales/crowdin/js-tr.yml | 4 +- config/locales/crowdin/js-uk.yml | 4 +- config/locales/crowdin/js-uz.yml | 4 +- config/locales/crowdin/js-vi.yml | 4 +- config/locales/crowdin/js-zh-CN.yml | 6 +- config/locales/crowdin/js-zh-TW.yml | 16 +++--- config/locales/crowdin/zh-TW.yml | 56 +++++++++---------- .../config/locales/crowdin/hu.yml | 2 +- .../grids/config/locales/crowdin/js-hu.yml | 4 +- modules/meeting/config/locales/crowdin/hu.yml | 34 +++++------ .../meeting/config/locales/crowdin/zh-TW.yml | 2 +- .../storages/config/locales/crowdin/ru.yml | 2 +- .../storages/config/locales/crowdin/zh-CN.yml | 2 +- .../storages/config/locales/crowdin/zh-TW.yml | 2 +- 63 files changed, 174 insertions(+), 174 deletions(-) diff --git a/config/locales/crowdin/fr.yml b/config/locales/crowdin/fr.yml index 0e2e8b02e6a5..a824b0345a3c 100644 --- a/config/locales/crowdin/fr.yml +++ b/config/locales/crowdin/fr.yml @@ -1661,18 +1661,18 @@ fr: xls: label: "XLS" columns: - input_label_report: "Add columns to attribute table" - input_caption_report: "By default all attributes added as columns in the work package list are selected. Long text fields are not available in the attribute table, but can be displayed below it." - input_caption_table: "By default all attributes added as columns in the work package list are selected. Long text fields are not available in table based exports." + input_label_report: "Ajouter des colonnes à la table d'attributs" + input_caption_report: "Par défaut, tous les attributs ajoutés en tant que colonnes dans la liste des lots de travaux sont sélectionnés. Les champs de type texte long ne sont pas disponibles dans la table des attributs, mais peuvent être affichés en dessous." + input_caption_table: "Par défaut, tous les attributs ajoutés en tant que colonnes dans la liste des lots de travaux sont sélectionnés. Les champs de type texte long ne sont pas disponibles dans les exports basés sur la table." pdf: export_type: - label: "PDF export type" + label: "Type d'export PDF" options: table: label: "Table" - caption: "Export the work packages list in a table with the desired columns." + caption: "Exporter la liste des lots de travaux dans une table avec les colonnes souhaitées." report: - label: "Report" + label: "Rapport" caption: "Export the work package on a detailed report of all work packages in the list." gantt: label: "Gantt chart" diff --git a/config/locales/crowdin/js-af.yml b/config/locales/crowdin/js-af.yml index b0558273e01b..f50600c150d2 100644 --- a/config/locales/crowdin/js-af.yml +++ b/config/locales/crowdin/js-af.yml @@ -358,10 +358,10 @@ af: learn_about: "Learn more about the new features" #Include the version to invalidate outdated translations in other locales. #Otherwise, e.g. chinese might still have the translations for 10.0 in the 12.0 release. - "14_4": + "14_5": standard: new_features_html: > - The release contains various new features and improvements, such as:

  • Dark mode option in personal settings
  • Separate permissions for viewing and editing on project attributes
  • Improved status-based progress reporting
  • Connection validation for Nextcloud storages
  • More filter options for project lists
+ The release contains various new features and improvements, such as:
  • Keep and restore local versions of WYSIWYG content changes.
  • Enable a storage for multiple projects at once.
  • Export work packages in an updated modal with additional settings.
  • Display custom field columns/filters in project lists also in the Community Edition.
  • Support CloudFlare Turnstile as Captcha.
ical_sharing_modal: title: "Subscribe to calendar" inital_setup_error_message: "An error occured while fetching data." diff --git a/config/locales/crowdin/js-ar.yml b/config/locales/crowdin/js-ar.yml index cae75bd68323..4bef3259e9d1 100644 --- a/config/locales/crowdin/js-ar.yml +++ b/config/locales/crowdin/js-ar.yml @@ -358,10 +358,10 @@ ar: learn_about: "Learn more about the new features" #Include the version to invalidate outdated translations in other locales. #Otherwise, e.g. chinese might still have the translations for 10.0 in the 12.0 release. - "14_4": + "14_5": standard: new_features_html: > - The release contains various new features and improvements, such as:
  • Dark mode option in personal settings
  • Separate permissions for viewing and editing on project attributes
  • Improved status-based progress reporting
  • Connection validation for Nextcloud storages
  • More filter options for project lists
+ The release contains various new features and improvements, such as:
  • Keep and restore local versions of WYSIWYG content changes.
  • Enable a storage for multiple projects at once.
  • Export work packages in an updated modal with additional settings.
  • Display custom field columns/filters in project lists also in the Community Edition.
  • Support CloudFlare Turnstile as Captcha.
ical_sharing_modal: title: "Subscribe to calendar" inital_setup_error_message: "An error occured while fetching data." diff --git a/config/locales/crowdin/js-az.yml b/config/locales/crowdin/js-az.yml index 1f2507b3d90e..14e45b25d7ab 100644 --- a/config/locales/crowdin/js-az.yml +++ b/config/locales/crowdin/js-az.yml @@ -358,10 +358,10 @@ az: learn_about: "Learn more about the new features" #Include the version to invalidate outdated translations in other locales. #Otherwise, e.g. chinese might still have the translations for 10.0 in the 12.0 release. - "14_4": + "14_5": standard: new_features_html: > - The release contains various new features and improvements, such as:
  • Dark mode option in personal settings
  • Separate permissions for viewing and editing on project attributes
  • Improved status-based progress reporting
  • Connection validation for Nextcloud storages
  • More filter options for project lists
+ The release contains various new features and improvements, such as:
  • Keep and restore local versions of WYSIWYG content changes.
  • Enable a storage for multiple projects at once.
  • Export work packages in an updated modal with additional settings.
  • Display custom field columns/filters in project lists also in the Community Edition.
  • Support CloudFlare Turnstile as Captcha.
ical_sharing_modal: title: "Subscribe to calendar" inital_setup_error_message: "An error occured while fetching data." diff --git a/config/locales/crowdin/js-be.yml b/config/locales/crowdin/js-be.yml index 7e9c7cf71cb0..560e177c52e3 100644 --- a/config/locales/crowdin/js-be.yml +++ b/config/locales/crowdin/js-be.yml @@ -358,10 +358,10 @@ be: learn_about: "Learn more about the new features" #Include the version to invalidate outdated translations in other locales. #Otherwise, e.g. chinese might still have the translations for 10.0 in the 12.0 release. - "14_4": + "14_5": standard: new_features_html: > - The release contains various new features and improvements, such as:
  • Dark mode option in personal settings
  • Separate permissions for viewing and editing on project attributes
  • Improved status-based progress reporting
  • Connection validation for Nextcloud storages
  • More filter options for project lists
+ The release contains various new features and improvements, such as:
  • Keep and restore local versions of WYSIWYG content changes.
  • Enable a storage for multiple projects at once.
  • Export work packages in an updated modal with additional settings.
  • Display custom field columns/filters in project lists also in the Community Edition.
  • Support CloudFlare Turnstile as Captcha.
ical_sharing_modal: title: "Subscribe to calendar" inital_setup_error_message: "An error occured while fetching data." diff --git a/config/locales/crowdin/js-bg.yml b/config/locales/crowdin/js-bg.yml index 01c6704024be..229963c47c64 100644 --- a/config/locales/crowdin/js-bg.yml +++ b/config/locales/crowdin/js-bg.yml @@ -358,10 +358,10 @@ bg: learn_about: "Learn more about the new features" #Include the version to invalidate outdated translations in other locales. #Otherwise, e.g. chinese might still have the translations for 10.0 in the 12.0 release. - "14_4": + "14_5": standard: new_features_html: > - The release contains various new features and improvements, such as:
  • Dark mode option in personal settings
  • Separate permissions for viewing and editing on project attributes
  • Improved status-based progress reporting
  • Connection validation for Nextcloud storages
  • More filter options for project lists
+ The release contains various new features and improvements, such as:
  • Keep and restore local versions of WYSIWYG content changes.
  • Enable a storage for multiple projects at once.
  • Export work packages in an updated modal with additional settings.
  • Display custom field columns/filters in project lists also in the Community Edition.
  • Support CloudFlare Turnstile as Captcha.
ical_sharing_modal: title: "Subscribe to calendar" inital_setup_error_message: "An error occured while fetching data." diff --git a/config/locales/crowdin/js-ca.yml b/config/locales/crowdin/js-ca.yml index a0dad5de4e68..49e7a3134e69 100644 --- a/config/locales/crowdin/js-ca.yml +++ b/config/locales/crowdin/js-ca.yml @@ -358,10 +358,10 @@ ca: learn_about: "Més informació sobre les noves funcions" #Include the version to invalidate outdated translations in other locales. #Otherwise, e.g. chinese might still have the translations for 10.0 in the 12.0 release. - "14_4": + "14_5": standard: new_features_html: > - The release contains various new features and improvements, such as:
  • Dark mode option in personal settings
  • Separate permissions for viewing and editing on project attributes
  • Improved status-based progress reporting
  • Connection validation for Nextcloud storages
  • More filter options for project lists
+ The release contains various new features and improvements, such as:
  • Keep and restore local versions of WYSIWYG content changes.
  • Enable a storage for multiple projects at once.
  • Export work packages in an updated modal with additional settings.
  • Display custom field columns/filters in project lists also in the Community Edition.
  • Support CloudFlare Turnstile as Captcha.
ical_sharing_modal: title: "Subscribe to calendar" inital_setup_error_message: "S'ha produït un error en carregar les dades." diff --git a/config/locales/crowdin/js-ckb-IR.yml b/config/locales/crowdin/js-ckb-IR.yml index 3aa08e25105a..54dafd8c8425 100644 --- a/config/locales/crowdin/js-ckb-IR.yml +++ b/config/locales/crowdin/js-ckb-IR.yml @@ -358,10 +358,10 @@ ckb-IR: learn_about: "Learn more about the new features" #Include the version to invalidate outdated translations in other locales. #Otherwise, e.g. chinese might still have the translations for 10.0 in the 12.0 release. - "14_4": + "14_5": standard: new_features_html: > - The release contains various new features and improvements, such as:
  • Dark mode option in personal settings
  • Separate permissions for viewing and editing on project attributes
  • Improved status-based progress reporting
  • Connection validation for Nextcloud storages
  • More filter options for project lists
+ The release contains various new features and improvements, such as:
  • Keep and restore local versions of WYSIWYG content changes.
  • Enable a storage for multiple projects at once.
  • Export work packages in an updated modal with additional settings.
  • Display custom field columns/filters in project lists also in the Community Edition.
  • Support CloudFlare Turnstile as Captcha.
ical_sharing_modal: title: "Subscribe to calendar" inital_setup_error_message: "An error occured while fetching data." diff --git a/config/locales/crowdin/js-cs.yml b/config/locales/crowdin/js-cs.yml index 3434e06ccb00..4f5cfc020a55 100644 --- a/config/locales/crowdin/js-cs.yml +++ b/config/locales/crowdin/js-cs.yml @@ -357,10 +357,10 @@ cs: learn_about: "Další informace o nových funkcích" #Include the version to invalidate outdated translations in other locales. #Otherwise, e.g. chinese might still have the translations for 10.0 in the 12.0 release. - "14_4": + "14_5": standard: new_features_html: > - The release contains various new features and improvements, such as:
  • Dark mode option in personal settings
  • Separate permissions for viewing and editing on project attributes
  • Improved status-based progress reporting
  • Connection validation for Nextcloud storages
  • More filter options for project lists
+ The release contains various new features and improvements, such as:
  • Keep and restore local versions of WYSIWYG content changes.
  • Enable a storage for multiple projects at once.
  • Export work packages in an updated modal with additional settings.
  • Display custom field columns/filters in project lists also in the Community Edition.
  • Support CloudFlare Turnstile as Captcha.
ical_sharing_modal: title: "Přihlásit kalendář k odběru" inital_setup_error_message: "Při načítání dat došlo k chybě." diff --git a/config/locales/crowdin/js-da.yml b/config/locales/crowdin/js-da.yml index a415c62c90bc..59c46f3d4ddd 100644 --- a/config/locales/crowdin/js-da.yml +++ b/config/locales/crowdin/js-da.yml @@ -357,10 +357,10 @@ da: learn_about: "Learn more about the new features" #Include the version to invalidate outdated translations in other locales. #Otherwise, e.g. chinese might still have the translations for 10.0 in the 12.0 release. - "14_4": + "14_5": standard: new_features_html: > - The release contains various new features and improvements, such as:
  • Dark mode option in personal settings
  • Separate permissions for viewing and editing on project attributes
  • Improved status-based progress reporting
  • Connection validation for Nextcloud storages
  • More filter options for project lists
+ The release contains various new features and improvements, such as:
  • Keep and restore local versions of WYSIWYG content changes.
  • Enable a storage for multiple projects at once.
  • Export work packages in an updated modal with additional settings.
  • Display custom field columns/filters in project lists also in the Community Edition.
  • Support CloudFlare Turnstile as Captcha.
ical_sharing_modal: title: "Subscribe to calendar" inital_setup_error_message: "An error occured while fetching data." diff --git a/config/locales/crowdin/js-de.yml b/config/locales/crowdin/js-de.yml index e37c3e62cfd0..39bf1568920a 100644 --- a/config/locales/crowdin/js-de.yml +++ b/config/locales/crowdin/js-de.yml @@ -357,10 +357,10 @@ de: learn_about: "Erfahren Sie mehr über die neuen Funktionen" #Include the version to invalidate outdated translations in other locales. #Otherwise, e.g. chinese might still have the translations for 10.0 in the 12.0 release. - "14_4": + "14_5": standard: new_features_html: > - Diese Version enthält verschiedene neue Funktionen und Verbesserungen:
  • Dark Mode wählbar in den persönlichen Einstellungen
  • Getrennte Berechtigungen für die Anzeige und Bearbeitung von Projektattributen
  • Verbesserungen für Fortschrittsberichte auf Basis des Status
  • Verbindungsüberprüfung für Nextcloud-Speicher
  • Mehr Filteroptionen für Projektlisten
+ The release contains various new features and improvements, such as:
  • Keep and restore local versions of WYSIWYG content changes.
  • Enable a storage for multiple projects at once.
  • Export work packages in an updated modal with additional settings.
  • Display custom field columns/filters in project lists also in the Community Edition.
  • Support CloudFlare Turnstile as Captcha.
ical_sharing_modal: title: "Kalender abonnieren" inital_setup_error_message: "Beim Abrufen der Daten ist ein Fehler aufgetreten." diff --git a/config/locales/crowdin/js-el.yml b/config/locales/crowdin/js-el.yml index d45ba9c38367..f7e9a36dc177 100644 --- a/config/locales/crowdin/js-el.yml +++ b/config/locales/crowdin/js-el.yml @@ -357,10 +357,10 @@ el: learn_about: "Μάθετε περισσότερα για τις νέες λειτουργίες" #Include the version to invalidate outdated translations in other locales. #Otherwise, e.g. chinese might still have the translations for 10.0 in the 12.0 release. - "14_4": + "14_5": standard: new_features_html: > - The release contains various new features and improvements, such as:
  • Dark mode option in personal settings
  • Separate permissions for viewing and editing on project attributes
  • Improved status-based progress reporting
  • Connection validation for Nextcloud storages
  • More filter options for project lists
+ The release contains various new features and improvements, such as:
  • Keep and restore local versions of WYSIWYG content changes.
  • Enable a storage for multiple projects at once.
  • Export work packages in an updated modal with additional settings.
  • Display custom field columns/filters in project lists also in the Community Edition.
  • Support CloudFlare Turnstile as Captcha.
ical_sharing_modal: title: "Subscribe to calendar" inital_setup_error_message: "An error occured while fetching data." diff --git a/config/locales/crowdin/js-eo.yml b/config/locales/crowdin/js-eo.yml index 0f82db3db1ca..9b8da316d90f 100644 --- a/config/locales/crowdin/js-eo.yml +++ b/config/locales/crowdin/js-eo.yml @@ -358,10 +358,10 @@ eo: learn_about: "Lerni pli pri la novaj plibonigoj" #Include the version to invalidate outdated translations in other locales. #Otherwise, e.g. chinese might still have the translations for 10.0 in the 12.0 release. - "14_4": + "14_5": standard: new_features_html: > - The release contains various new features and improvements, such as:
  • Dark mode option in personal settings
  • Separate permissions for viewing and editing on project attributes
  • Improved status-based progress reporting
  • Connection validation for Nextcloud storages
  • More filter options for project lists
+ The release contains various new features and improvements, such as:
  • Keep and restore local versions of WYSIWYG content changes.
  • Enable a storage for multiple projects at once.
  • Export work packages in an updated modal with additional settings.
  • Display custom field columns/filters in project lists also in the Community Edition.
  • Support CloudFlare Turnstile as Captcha.
ical_sharing_modal: title: "Subscribe to calendar" inital_setup_error_message: "An error occured while fetching data." diff --git a/config/locales/crowdin/js-es.yml b/config/locales/crowdin/js-es.yml index 9d316e5e292f..68b305a32fb9 100644 --- a/config/locales/crowdin/js-es.yml +++ b/config/locales/crowdin/js-es.yml @@ -358,10 +358,10 @@ es: learn_about: "Más información sobre las nuevas funciones" #Include the version to invalidate outdated translations in other locales. #Otherwise, e.g. chinese might still have the translations for 10.0 in the 12.0 release. - "14_4": + "14_5": standard: new_features_html: > - The release contains various new features and improvements, such as:
  • Dark mode option in personal settings
  • Separate permissions for viewing and editing on project attributes
  • Improved status-based progress reporting
  • Connection validation for Nextcloud storages
  • More filter options for project lists
+ The release contains various new features and improvements, such as:
  • Keep and restore local versions of WYSIWYG content changes.
  • Enable a storage for multiple projects at once.
  • Export work packages in an updated modal with additional settings.
  • Display custom field columns/filters in project lists also in the Community Edition.
  • Support CloudFlare Turnstile as Captcha.
ical_sharing_modal: title: "Suscribirse al calendario" inital_setup_error_message: "Se ha producido un error al obtener los datos." diff --git a/config/locales/crowdin/js-et.yml b/config/locales/crowdin/js-et.yml index d4be03244419..51b950d193f9 100644 --- a/config/locales/crowdin/js-et.yml +++ b/config/locales/crowdin/js-et.yml @@ -358,10 +358,10 @@ et: learn_about: "Learn more about the new features" #Include the version to invalidate outdated translations in other locales. #Otherwise, e.g. chinese might still have the translations for 10.0 in the 12.0 release. - "14_4": + "14_5": standard: new_features_html: > - The release contains various new features and improvements, such as:
  • Dark mode option in personal settings
  • Separate permissions for viewing and editing on project attributes
  • Improved status-based progress reporting
  • Connection validation for Nextcloud storages
  • More filter options for project lists
+ The release contains various new features and improvements, such as:
  • Keep and restore local versions of WYSIWYG content changes.
  • Enable a storage for multiple projects at once.
  • Export work packages in an updated modal with additional settings.
  • Display custom field columns/filters in project lists also in the Community Edition.
  • Support CloudFlare Turnstile as Captcha.
ical_sharing_modal: title: "Subscribe to calendar" inital_setup_error_message: "An error occured while fetching data." diff --git a/config/locales/crowdin/js-eu.yml b/config/locales/crowdin/js-eu.yml index ba9ffff6d86e..4f9bbdd048e1 100644 --- a/config/locales/crowdin/js-eu.yml +++ b/config/locales/crowdin/js-eu.yml @@ -358,10 +358,10 @@ eu: learn_about: "Learn more about the new features" #Include the version to invalidate outdated translations in other locales. #Otherwise, e.g. chinese might still have the translations for 10.0 in the 12.0 release. - "14_4": + "14_5": standard: new_features_html: > - The release contains various new features and improvements, such as:
  • Dark mode option in personal settings
  • Separate permissions for viewing and editing on project attributes
  • Improved status-based progress reporting
  • Connection validation for Nextcloud storages
  • More filter options for project lists
+ The release contains various new features and improvements, such as:
  • Keep and restore local versions of WYSIWYG content changes.
  • Enable a storage for multiple projects at once.
  • Export work packages in an updated modal with additional settings.
  • Display custom field columns/filters in project lists also in the Community Edition.
  • Support CloudFlare Turnstile as Captcha.
ical_sharing_modal: title: "Subscribe to calendar" inital_setup_error_message: "An error occured while fetching data." diff --git a/config/locales/crowdin/js-fa.yml b/config/locales/crowdin/js-fa.yml index 0e6bb27f792d..5405500caabf 100644 --- a/config/locales/crowdin/js-fa.yml +++ b/config/locales/crowdin/js-fa.yml @@ -358,10 +358,10 @@ fa: learn_about: "Learn more about the new features" #Include the version to invalidate outdated translations in other locales. #Otherwise, e.g. chinese might still have the translations for 10.0 in the 12.0 release. - "14_4": + "14_5": standard: new_features_html: > - The release contains various new features and improvements, such as:
  • Dark mode option in personal settings
  • Separate permissions for viewing and editing on project attributes
  • Improved status-based progress reporting
  • Connection validation for Nextcloud storages
  • More filter options for project lists
+ The release contains various new features and improvements, such as:
  • Keep and restore local versions of WYSIWYG content changes.
  • Enable a storage for multiple projects at once.
  • Export work packages in an updated modal with additional settings.
  • Display custom field columns/filters in project lists also in the Community Edition.
  • Support CloudFlare Turnstile as Captcha.
ical_sharing_modal: title: "Subscribe to calendar" inital_setup_error_message: "An error occured while fetching data." diff --git a/config/locales/crowdin/js-fi.yml b/config/locales/crowdin/js-fi.yml index 909937d58226..23056e7adadd 100644 --- a/config/locales/crowdin/js-fi.yml +++ b/config/locales/crowdin/js-fi.yml @@ -358,10 +358,10 @@ fi: learn_about: "Lisätietoja uusista ominaisuuksista" #Include the version to invalidate outdated translations in other locales. #Otherwise, e.g. chinese might still have the translations for 10.0 in the 12.0 release. - "14_4": + "14_5": standard: new_features_html: > - The release contains various new features and improvements, such as:
  • Dark mode option in personal settings
  • Separate permissions for viewing and editing on project attributes
  • Improved status-based progress reporting
  • Connection validation for Nextcloud storages
  • More filter options for project lists
+ The release contains various new features and improvements, such as:
  • Keep and restore local versions of WYSIWYG content changes.
  • Enable a storage for multiple projects at once.
  • Export work packages in an updated modal with additional settings.
  • Display custom field columns/filters in project lists also in the Community Edition.
  • Support CloudFlare Turnstile as Captcha.
ical_sharing_modal: title: "Subscribe to calendar" inital_setup_error_message: "An error occured while fetching data." diff --git a/config/locales/crowdin/js-fil.yml b/config/locales/crowdin/js-fil.yml index 6cfad7d0f0be..c47020c09ed0 100644 --- a/config/locales/crowdin/js-fil.yml +++ b/config/locales/crowdin/js-fil.yml @@ -358,10 +358,10 @@ fil: learn_about: "Learn more about the new features" #Include the version to invalidate outdated translations in other locales. #Otherwise, e.g. chinese might still have the translations for 10.0 in the 12.0 release. - "14_4": + "14_5": standard: new_features_html: > - The release contains various new features and improvements, such as:
  • Dark mode option in personal settings
  • Separate permissions for viewing and editing on project attributes
  • Improved status-based progress reporting
  • Connection validation for Nextcloud storages
  • More filter options for project lists
+ The release contains various new features and improvements, such as:
  • Keep and restore local versions of WYSIWYG content changes.
  • Enable a storage for multiple projects at once.
  • Export work packages in an updated modal with additional settings.
  • Display custom field columns/filters in project lists also in the Community Edition.
  • Support CloudFlare Turnstile as Captcha.
ical_sharing_modal: title: "Subscribe to calendar" inital_setup_error_message: "An error occured while fetching data." diff --git a/config/locales/crowdin/js-fr.yml b/config/locales/crowdin/js-fr.yml index 0f31195e92dd..f7cdd39de466 100644 --- a/config/locales/crowdin/js-fr.yml +++ b/config/locales/crowdin/js-fr.yml @@ -358,10 +358,10 @@ fr: learn_about: "En savoir plus sur les nouvelles fonctionnalités" #Include the version to invalidate outdated translations in other locales. #Otherwise, e.g. chinese might still have the translations for 10.0 in the 12.0 release. - "14_4": + "14_5": standard: new_features_html: > - La version contient diverses nouvelles fonctionnalités et améliorations, telles que :
  • Option de mode sombre dans les paramètres personnels
  • Séparation des permissions pour la visualisation et l'édition des attributs du projet
  • Amélioration de l'état de progression basé sur le statut
  • Validation de la connexion pour les stockages Nextcloud
  • Plus d'options de filtre pour les listes de projets
+ The release contains various new features and improvements, such as:
  • Keep and restore local versions of WYSIWYG content changes.
  • Enable a storage for multiple projects at once.
  • Export work packages in an updated modal with additional settings.
  • Display custom field columns/filters in project lists also in the Community Edition.
  • Support CloudFlare Turnstile as Captcha.
ical_sharing_modal: title: "S'abonner au calendrier" inital_setup_error_message: "Une erreur est survenue lors de la récupération des données." diff --git a/config/locales/crowdin/js-he.yml b/config/locales/crowdin/js-he.yml index 3c1b454361ab..d6d3b782b314 100644 --- a/config/locales/crowdin/js-he.yml +++ b/config/locales/crowdin/js-he.yml @@ -358,10 +358,10 @@ he: learn_about: "Learn more about the new features" #Include the version to invalidate outdated translations in other locales. #Otherwise, e.g. chinese might still have the translations for 10.0 in the 12.0 release. - "14_4": + "14_5": standard: new_features_html: > - The release contains various new features and improvements, such as:
  • Dark mode option in personal settings
  • Separate permissions for viewing and editing on project attributes
  • Improved status-based progress reporting
  • Connection validation for Nextcloud storages
  • More filter options for project lists
+ The release contains various new features and improvements, such as:
  • Keep and restore local versions of WYSIWYG content changes.
  • Enable a storage for multiple projects at once.
  • Export work packages in an updated modal with additional settings.
  • Display custom field columns/filters in project lists also in the Community Edition.
  • Support CloudFlare Turnstile as Captcha.
ical_sharing_modal: title: "Subscribe to calendar" inital_setup_error_message: "An error occured while fetching data." diff --git a/config/locales/crowdin/js-hi.yml b/config/locales/crowdin/js-hi.yml index 792635d48309..ba460dff221a 100644 --- a/config/locales/crowdin/js-hi.yml +++ b/config/locales/crowdin/js-hi.yml @@ -358,10 +358,10 @@ hi: learn_about: "Learn more about the new features" #Include the version to invalidate outdated translations in other locales. #Otherwise, e.g. chinese might still have the translations for 10.0 in the 12.0 release. - "14_4": + "14_5": standard: new_features_html: > - The release contains various new features and improvements, such as:
  • Dark mode option in personal settings
  • Separate permissions for viewing and editing on project attributes
  • Improved status-based progress reporting
  • Connection validation for Nextcloud storages
  • More filter options for project lists
+ The release contains various new features and improvements, such as:
  • Keep and restore local versions of WYSIWYG content changes.
  • Enable a storage for multiple projects at once.
  • Export work packages in an updated modal with additional settings.
  • Display custom field columns/filters in project lists also in the Community Edition.
  • Support CloudFlare Turnstile as Captcha.
ical_sharing_modal: title: "Subscribe to calendar" inital_setup_error_message: "An error occured while fetching data." diff --git a/config/locales/crowdin/js-hr.yml b/config/locales/crowdin/js-hr.yml index ae68f726e071..3ea56362a85c 100644 --- a/config/locales/crowdin/js-hr.yml +++ b/config/locales/crowdin/js-hr.yml @@ -358,10 +358,10 @@ hr: learn_about: "Saznaj više o novim značajkama" #Include the version to invalidate outdated translations in other locales. #Otherwise, e.g. chinese might still have the translations for 10.0 in the 12.0 release. - "14_4": + "14_5": standard: new_features_html: > - The release contains various new features and improvements, such as:
  • Dark mode option in personal settings
  • Separate permissions for viewing and editing on project attributes
  • Improved status-based progress reporting
  • Connection validation for Nextcloud storages
  • More filter options for project lists
+ The release contains various new features and improvements, such as:
  • Keep and restore local versions of WYSIWYG content changes.
  • Enable a storage for multiple projects at once.
  • Export work packages in an updated modal with additional settings.
  • Display custom field columns/filters in project lists also in the Community Edition.
  • Support CloudFlare Turnstile as Captcha.
ical_sharing_modal: title: "Subscribe to calendar" inital_setup_error_message: "An error occured while fetching data." diff --git a/config/locales/crowdin/js-hu.yml b/config/locales/crowdin/js-hu.yml index 11b314eb26be..b9c9b5007c24 100644 --- a/config/locales/crowdin/js-hu.yml +++ b/config/locales/crowdin/js-hu.yml @@ -358,10 +358,10 @@ hu: learn_about: "Tudjon meg többet az új funkciókról" #Include the version to invalidate outdated translations in other locales. #Otherwise, e.g. chinese might still have the translations for 10.0 in the 12.0 release. - "14_4": + "14_5": standard: new_features_html: > - The release contains various new features and improvements, such as:
  • Dark mode option in personal settings
  • Separate permissions for viewing and editing on project attributes
  • Improved status-based progress reporting
  • Connection validation for Nextcloud storages
  • More filter options for project lists
+ The release contains various new features and improvements, such as:
  • Keep and restore local versions of WYSIWYG content changes.
  • Enable a storage for multiple projects at once.
  • Export work packages in an updated modal with additional settings.
  • Display custom field columns/filters in project lists also in the Community Edition.
  • Support CloudFlare Turnstile as Captcha.
ical_sharing_modal: title: "Subscribe to calendar" inital_setup_error_message: "An error occured while fetching data." diff --git a/config/locales/crowdin/js-id.yml b/config/locales/crowdin/js-id.yml index cc7f76e73ed6..28389794aaed 100644 --- a/config/locales/crowdin/js-id.yml +++ b/config/locales/crowdin/js-id.yml @@ -358,10 +358,10 @@ id: learn_about: "Learn more about the new features" #Include the version to invalidate outdated translations in other locales. #Otherwise, e.g. chinese might still have the translations for 10.0 in the 12.0 release. - "14_4": + "14_5": standard: new_features_html: > - The release contains various new features and improvements, such as:
  • Dark mode option in personal settings
  • Separate permissions for viewing and editing on project attributes
  • Improved status-based progress reporting
  • Connection validation for Nextcloud storages
  • More filter options for project lists
+ The release contains various new features and improvements, such as:
  • Keep and restore local versions of WYSIWYG content changes.
  • Enable a storage for multiple projects at once.
  • Export work packages in an updated modal with additional settings.
  • Display custom field columns/filters in project lists also in the Community Edition.
  • Support CloudFlare Turnstile as Captcha.
ical_sharing_modal: title: "Subscribe to calendar" inital_setup_error_message: "An error occured while fetching data." diff --git a/config/locales/crowdin/js-it.yml b/config/locales/crowdin/js-it.yml index e253e6adc554..854c4ca9b78c 100644 --- a/config/locales/crowdin/js-it.yml +++ b/config/locales/crowdin/js-it.yml @@ -358,10 +358,10 @@ it: learn_about: "Scopri di più sulle nuove funzionalità" #Include the version to invalidate outdated translations in other locales. #Otherwise, e.g. chinese might still have the translations for 10.0 in the 12.0 release. - "14_4": + "14_5": standard: new_features_html: > - Questa versione contiene varie nuove funzionalità e miglioramenti, come:
  • Opzione modalità scura nelle impostazioni personali
  • Autorizzazioni separate per la visualizzazione e la modifica degli attributi di progetto
  • Report sullo stato di avanzamento migliorato
  • Convalida della connessione per gli archivi Nextcloud
  • Più opzioni di filtro per gli elenchi di progetti
+ The release contains various new features and improvements, such as:
  • Keep and restore local versions of WYSIWYG content changes.
  • Enable a storage for multiple projects at once.
  • Export work packages in an updated modal with additional settings.
  • Display custom field columns/filters in project lists also in the Community Edition.
  • Support CloudFlare Turnstile as Captcha.
ical_sharing_modal: title: "Iscriviti al calendario" inital_setup_error_message: "Si è verificato un errore recuperando i dati." diff --git a/config/locales/crowdin/js-ja.yml b/config/locales/crowdin/js-ja.yml index dc9197a39faa..6d326895c17a 100644 --- a/config/locales/crowdin/js-ja.yml +++ b/config/locales/crowdin/js-ja.yml @@ -359,10 +359,10 @@ ja: learn_about: "新機能の詳細はこちら" #Include the version to invalidate outdated translations in other locales. #Otherwise, e.g. chinese might still have the translations for 10.0 in the 12.0 release. - "14_4": + "14_5": standard: new_features_html: > - The release contains various new features and improvements, such as:
  • Dark mode option in personal settings
  • Separate permissions for viewing and editing on project attributes
  • Improved status-based progress reporting
  • Connection validation for Nextcloud storages
  • More filter options for project lists
+ The release contains various new features and improvements, such as:
  • Keep and restore local versions of WYSIWYG content changes.
  • Enable a storage for multiple projects at once.
  • Export work packages in an updated modal with additional settings.
  • Display custom field columns/filters in project lists also in the Community Edition.
  • Support CloudFlare Turnstile as Captcha.
ical_sharing_modal: title: "Subscribe to calendar" inital_setup_error_message: "An error occured while fetching data." diff --git a/config/locales/crowdin/js-ka.yml b/config/locales/crowdin/js-ka.yml index ea8d9cbca838..82de37bed037 100644 --- a/config/locales/crowdin/js-ka.yml +++ b/config/locales/crowdin/js-ka.yml @@ -358,10 +358,10 @@ ka: learn_about: "Learn more about the new features" #Include the version to invalidate outdated translations in other locales. #Otherwise, e.g. chinese might still have the translations for 10.0 in the 12.0 release. - "14_4": + "14_5": standard: new_features_html: > - The release contains various new features and improvements, such as:
  • Dark mode option in personal settings
  • Separate permissions for viewing and editing on project attributes
  • Improved status-based progress reporting
  • Connection validation for Nextcloud storages
  • More filter options for project lists
+ The release contains various new features and improvements, such as:
  • Keep and restore local versions of WYSIWYG content changes.
  • Enable a storage for multiple projects at once.
  • Export work packages in an updated modal with additional settings.
  • Display custom field columns/filters in project lists also in the Community Edition.
  • Support CloudFlare Turnstile as Captcha.
ical_sharing_modal: title: "Subscribe to calendar" inital_setup_error_message: "An error occured while fetching data." diff --git a/config/locales/crowdin/js-kk.yml b/config/locales/crowdin/js-kk.yml index 4e846d1e4603..54ef56f955d2 100644 --- a/config/locales/crowdin/js-kk.yml +++ b/config/locales/crowdin/js-kk.yml @@ -358,10 +358,10 @@ kk: learn_about: "Learn more about the new features" #Include the version to invalidate outdated translations in other locales. #Otherwise, e.g. chinese might still have the translations for 10.0 in the 12.0 release. - "14_4": + "14_5": standard: new_features_html: > - The release contains various new features and improvements, such as:
  • Dark mode option in personal settings
  • Separate permissions for viewing and editing on project attributes
  • Improved status-based progress reporting
  • Connection validation for Nextcloud storages
  • More filter options for project lists
+ The release contains various new features and improvements, such as:
  • Keep and restore local versions of WYSIWYG content changes.
  • Enable a storage for multiple projects at once.
  • Export work packages in an updated modal with additional settings.
  • Display custom field columns/filters in project lists also in the Community Edition.
  • Support CloudFlare Turnstile as Captcha.
ical_sharing_modal: title: "Subscribe to calendar" inital_setup_error_message: "An error occured while fetching data." diff --git a/config/locales/crowdin/js-ko.yml b/config/locales/crowdin/js-ko.yml index 7dda4c7b45bf..0d350cbf7c69 100644 --- a/config/locales/crowdin/js-ko.yml +++ b/config/locales/crowdin/js-ko.yml @@ -358,10 +358,10 @@ ko: learn_about: "새로운 기능에 대해 자세히 알아보기" #Include the version to invalidate outdated translations in other locales. #Otherwise, e.g. chinese might still have the translations for 10.0 in the 12.0 release. - "14_4": + "14_5": standard: new_features_html: > - The release contains various new features and improvements, such as:
  • Dark mode option in personal settings
  • Separate permissions for viewing and editing on project attributes
  • Improved status-based progress reporting
  • Connection validation for Nextcloud storages
  • More filter options for project lists
+ The release contains various new features and improvements, such as:
  • Keep and restore local versions of WYSIWYG content changes.
  • Enable a storage for multiple projects at once.
  • Export work packages in an updated modal with additional settings.
  • Display custom field columns/filters in project lists also in the Community Edition.
  • Support CloudFlare Turnstile as Captcha.
ical_sharing_modal: title: "캘린더 구독" inital_setup_error_message: "데이터를 가져오는 중에 오류가 발생했습니다." diff --git a/config/locales/crowdin/js-lt.yml b/config/locales/crowdin/js-lt.yml index 79caaff89f8e..1a437c88b35d 100644 --- a/config/locales/crowdin/js-lt.yml +++ b/config/locales/crowdin/js-lt.yml @@ -358,10 +358,10 @@ lt: learn_about: "Sužinokite daugiau apie naujas galimybes" #Include the version to invalidate outdated translations in other locales. #Otherwise, e.g. chinese might still have the translations for 10.0 in the 12.0 release. - "14_4": + "14_5": standard: new_features_html: > - The release contains various new features and improvements, such as:
  • Dark mode option in personal settings
  • Separate permissions for viewing and editing on project attributes
  • Improved status-based progress reporting
  • Connection validation for Nextcloud storages
  • More filter options for project lists
+ The release contains various new features and improvements, such as:
  • Keep and restore local versions of WYSIWYG content changes.
  • Enable a storage for multiple projects at once.
  • Export work packages in an updated modal with additional settings.
  • Display custom field columns/filters in project lists also in the Community Edition.
  • Support CloudFlare Turnstile as Captcha.
ical_sharing_modal: title: "Prenumeruoti kalendorių" inital_setup_error_message: "Gaunant duomenis įvyko klaida." diff --git a/config/locales/crowdin/js-lv.yml b/config/locales/crowdin/js-lv.yml index 2bf37855ecc0..42f05157e3e4 100644 --- a/config/locales/crowdin/js-lv.yml +++ b/config/locales/crowdin/js-lv.yml @@ -358,10 +358,10 @@ lv: learn_about: "Learn more about the new features" #Include the version to invalidate outdated translations in other locales. #Otherwise, e.g. chinese might still have the translations for 10.0 in the 12.0 release. - "14_4": + "14_5": standard: new_features_html: > - The release contains various new features and improvements, such as:
  • Dark mode option in personal settings
  • Separate permissions for viewing and editing on project attributes
  • Improved status-based progress reporting
  • Connection validation for Nextcloud storages
  • More filter options for project lists
+ The release contains various new features and improvements, such as:
  • Keep and restore local versions of WYSIWYG content changes.
  • Enable a storage for multiple projects at once.
  • Export work packages in an updated modal with additional settings.
  • Display custom field columns/filters in project lists also in the Community Edition.
  • Support CloudFlare Turnstile as Captcha.
ical_sharing_modal: title: "Subscribe to calendar" inital_setup_error_message: "An error occured while fetching data." diff --git a/config/locales/crowdin/js-mn.yml b/config/locales/crowdin/js-mn.yml index c5b8bb4e39f0..74dbcfe7a2b0 100644 --- a/config/locales/crowdin/js-mn.yml +++ b/config/locales/crowdin/js-mn.yml @@ -358,10 +358,10 @@ mn: learn_about: "Learn more about the new features" #Include the version to invalidate outdated translations in other locales. #Otherwise, e.g. chinese might still have the translations for 10.0 in the 12.0 release. - "14_4": + "14_5": standard: new_features_html: > - The release contains various new features and improvements, such as:
  • Dark mode option in personal settings
  • Separate permissions for viewing and editing on project attributes
  • Improved status-based progress reporting
  • Connection validation for Nextcloud storages
  • More filter options for project lists
+ The release contains various new features and improvements, such as:
  • Keep and restore local versions of WYSIWYG content changes.
  • Enable a storage for multiple projects at once.
  • Export work packages in an updated modal with additional settings.
  • Display custom field columns/filters in project lists also in the Community Edition.
  • Support CloudFlare Turnstile as Captcha.
ical_sharing_modal: title: "Subscribe to calendar" inital_setup_error_message: "An error occured while fetching data." diff --git a/config/locales/crowdin/js-ms.yml b/config/locales/crowdin/js-ms.yml index 4d87ce832aab..dc62c89c9e6f 100644 --- a/config/locales/crowdin/js-ms.yml +++ b/config/locales/crowdin/js-ms.yml @@ -358,10 +358,10 @@ ms: learn_about: "Ketahui lebih lanjut mengenai fitur-fitur baharu." #Include the version to invalidate outdated translations in other locales. #Otherwise, e.g. chinese might still have the translations for 10.0 in the 12.0 release. - "14_4": + "14_5": standard: new_features_html: > - The release contains various new features and improvements, such as:
  • Dark mode option in personal settings
  • Separate permissions for viewing and editing on project attributes
  • Improved status-based progress reporting
  • Connection validation for Nextcloud storages
  • More filter options for project lists
+ The release contains various new features and improvements, such as:
  • Keep and restore local versions of WYSIWYG content changes.
  • Enable a storage for multiple projects at once.
  • Export work packages in an updated modal with additional settings.
  • Display custom field columns/filters in project lists also in the Community Edition.
  • Support CloudFlare Turnstile as Captcha.
ical_sharing_modal: title: "Langgan kalendar" inital_setup_error_message: "Ralat berlaku ketika sedang mengambil data." diff --git a/config/locales/crowdin/js-ne.yml b/config/locales/crowdin/js-ne.yml index 5251cec69199..518687e23c1c 100644 --- a/config/locales/crowdin/js-ne.yml +++ b/config/locales/crowdin/js-ne.yml @@ -358,10 +358,10 @@ ne: learn_about: "Learn more about the new features" #Include the version to invalidate outdated translations in other locales. #Otherwise, e.g. chinese might still have the translations for 10.0 in the 12.0 release. - "14_4": + "14_5": standard: new_features_html: > - The release contains various new features and improvements, such as:
  • Dark mode option in personal settings
  • Separate permissions for viewing and editing on project attributes
  • Improved status-based progress reporting
  • Connection validation for Nextcloud storages
  • More filter options for project lists
+ The release contains various new features and improvements, such as:
  • Keep and restore local versions of WYSIWYG content changes.
  • Enable a storage for multiple projects at once.
  • Export work packages in an updated modal with additional settings.
  • Display custom field columns/filters in project lists also in the Community Edition.
  • Support CloudFlare Turnstile as Captcha.
ical_sharing_modal: title: "Subscribe to calendar" inital_setup_error_message: "An error occured while fetching data." diff --git a/config/locales/crowdin/js-nl.yml b/config/locales/crowdin/js-nl.yml index 9eb3e7ba46d3..b9b0d4bc275f 100644 --- a/config/locales/crowdin/js-nl.yml +++ b/config/locales/crowdin/js-nl.yml @@ -358,10 +358,10 @@ nl: learn_about: "Meer informatie over de nieuwe functies" #Include the version to invalidate outdated translations in other locales. #Otherwise, e.g. chinese might still have the translations for 10.0 in the 12.0 release. - "14_4": + "14_5": standard: new_features_html: > - The release contains various new features and improvements, such as:
  • Dark mode option in personal settings
  • Separate permissions for viewing and editing on project attributes
  • Improved status-based progress reporting
  • Connection validation for Nextcloud storages
  • More filter options for project lists
+ The release contains various new features and improvements, such as:
  • Keep and restore local versions of WYSIWYG content changes.
  • Enable a storage for multiple projects at once.
  • Export work packages in an updated modal with additional settings.
  • Display custom field columns/filters in project lists also in the Community Edition.
  • Support CloudFlare Turnstile as Captcha.
ical_sharing_modal: title: "Abonneren op agenda" inital_setup_error_message: "Er is een fout opgetreden tijdens het ophalen van gegevens." diff --git a/config/locales/crowdin/js-no.yml b/config/locales/crowdin/js-no.yml index e0cec25928f3..f9f2459c928a 100644 --- a/config/locales/crowdin/js-no.yml +++ b/config/locales/crowdin/js-no.yml @@ -358,10 +358,10 @@ learn_about: "Lær mer om de nye funksjonene" #Include the version to invalidate outdated translations in other locales. #Otherwise, e.g. chinese might still have the translations for 10.0 in the 12.0 release. - "14_4": + "14_5": standard: new_features_html: > - The release contains various new features and improvements, such as:
  • Dark mode option in personal settings
  • Separate permissions for viewing and editing on project attributes
  • Improved status-based progress reporting
  • Connection validation for Nextcloud storages
  • More filter options for project lists
+ The release contains various new features and improvements, such as:
  • Keep and restore local versions of WYSIWYG content changes.
  • Enable a storage for multiple projects at once.
  • Export work packages in an updated modal with additional settings.
  • Display custom field columns/filters in project lists also in the Community Edition.
  • Support CloudFlare Turnstile as Captcha.
ical_sharing_modal: title: "Abonner på kalender" inital_setup_error_message: "En feil oppstod under henting av data." diff --git a/config/locales/crowdin/js-pl.yml b/config/locales/crowdin/js-pl.yml index 804005656c99..9bb63ebb0e83 100644 --- a/config/locales/crowdin/js-pl.yml +++ b/config/locales/crowdin/js-pl.yml @@ -358,10 +358,10 @@ pl: learn_about: "Dowiedz się więcej o nowych funkcjach" #Include the version to invalidate outdated translations in other locales. #Otherwise, e.g. chinese might still have the translations for 10.0 in the 12.0 release. - "14_4": + "14_5": standard: new_features_html: > - The release contains various new features and improvements, such as:
  • Dark mode option in personal settings
  • Separate permissions for viewing and editing on project attributes
  • Improved status-based progress reporting
  • Connection validation for Nextcloud storages
  • More filter options for project lists
+ The release contains various new features and improvements, such as:
  • Keep and restore local versions of WYSIWYG content changes.
  • Enable a storage for multiple projects at once.
  • Export work packages in an updated modal with additional settings.
  • Display custom field columns/filters in project lists also in the Community Edition.
  • Support CloudFlare Turnstile as Captcha.
ical_sharing_modal: title: "Subskrybuj kalendarz" inital_setup_error_message: "Podczas pobierania danych wystąpił błąd." diff --git a/config/locales/crowdin/js-pt-BR.yml b/config/locales/crowdin/js-pt-BR.yml index 4b12d4b3e73c..a201ae958e7b 100644 --- a/config/locales/crowdin/js-pt-BR.yml +++ b/config/locales/crowdin/js-pt-BR.yml @@ -357,10 +357,10 @@ pt-BR: learn_about: "Saiba mais sobre os novos recursos" #Include the version to invalidate outdated translations in other locales. #Otherwise, e.g. chinese might still have the translations for 10.0 in the 12.0 release. - "14_4": + "14_5": standard: new_features_html: > - A versão contém vários novos recursos e aprimoramentos, como:
  • Opção de modo escuro nas configurações pessoais
  • Permissões separadas para visualização e edição dos atributos do projeto
  • Relatórios de progresso baseados em status aprimorados
  • Validação de conexão para armazenamentos Nextcloud
  • Mais opções de filtro para listas de projetos
+ The release contains various new features and improvements, such as:
  • Keep and restore local versions of WYSIWYG content changes.
  • Enable a storage for multiple projects at once.
  • Export work packages in an updated modal with additional settings.
  • Display custom field columns/filters in project lists also in the Community Edition.
  • Support CloudFlare Turnstile as Captcha.
ical_sharing_modal: title: "Assinar calendário" inital_setup_error_message: "Ocorreu um erro ao buscar dados." diff --git a/config/locales/crowdin/js-pt-PT.yml b/config/locales/crowdin/js-pt-PT.yml index 49ef53bc70e2..3381af8e4b0d 100644 --- a/config/locales/crowdin/js-pt-PT.yml +++ b/config/locales/crowdin/js-pt-PT.yml @@ -358,10 +358,10 @@ pt-PT: learn_about: "Saiba mais sobre os novos recursos" #Include the version to invalidate outdated translations in other locales. #Otherwise, e.g. chinese might still have the translations for 10.0 in the 12.0 release. - "14_4": + "14_5": standard: new_features_html: > - The release contains various new features and improvements, such as:
  • Dark mode option in personal settings
  • Separate permissions for viewing and editing on project attributes
  • Improved status-based progress reporting
  • Connection validation for Nextcloud storages
  • More filter options for project lists
+ The release contains various new features and improvements, such as:
  • Keep and restore local versions of WYSIWYG content changes.
  • Enable a storage for multiple projects at once.
  • Export work packages in an updated modal with additional settings.
  • Display custom field columns/filters in project lists also in the Community Edition.
  • Support CloudFlare Turnstile as Captcha.
ical_sharing_modal: title: "Subscrever o calendário" inital_setup_error_message: "Ocorreu um erro ao recuperar os dados." diff --git a/config/locales/crowdin/js-ro.yml b/config/locales/crowdin/js-ro.yml index deef01bbe294..507cb4421572 100644 --- a/config/locales/crowdin/js-ro.yml +++ b/config/locales/crowdin/js-ro.yml @@ -357,10 +357,10 @@ ro: learn_about: "Aflați mai multe despre noile caracteristici" #Include the version to invalidate outdated translations in other locales. #Otherwise, e.g. chinese might still have the translations for 10.0 in the 12.0 release. - "14_4": + "14_5": standard: new_features_html: > - The release contains various new features and improvements, such as:
  • Dark mode option in personal settings
  • Separate permissions for viewing and editing on project attributes
  • Improved status-based progress reporting
  • Connection validation for Nextcloud storages
  • More filter options for project lists
+ The release contains various new features and improvements, such as:
  • Keep and restore local versions of WYSIWYG content changes.
  • Enable a storage for multiple projects at once.
  • Export work packages in an updated modal with additional settings.
  • Display custom field columns/filters in project lists also in the Community Edition.
  • Support CloudFlare Turnstile as Captcha.
ical_sharing_modal: title: "Subscribe to calendar" inital_setup_error_message: "An error occured while fetching data." diff --git a/config/locales/crowdin/js-ru.yml b/config/locales/crowdin/js-ru.yml index bfa8b2d25ebd..e82f15fe3715 100644 --- a/config/locales/crowdin/js-ru.yml +++ b/config/locales/crowdin/js-ru.yml @@ -74,7 +74,7 @@ ru: button_copy: "Копировать" button_copy_to_clipboard: "Копировать в буфер обмена" button_copy_link_to_clipboard: "Копировать ссылку в буфер обмена" - button_copy_to_other_project: "Duplicate in another project" + button_copy_to_other_project: "Дублировать в другой проект" button_custom-fields: "Настраиваемые поля" button_delete: "Удалить" button_delete_watcher: "Удалить наблюдателя" @@ -357,10 +357,10 @@ ru: learn_about: "Подробнее о новых функциях" #Include the version to invalidate outdated translations in other locales. #Otherwise, e.g. chinese might still have the translations for 10.0 in the 12.0 release. - "14_4": + "14_5": standard: new_features_html: > - Выпуск содержит различные новые функции и улучшения, такие как:
  • Опция темного режима в персональных настройках
  • Раздельные разрешения на просмотр и редактирование атрибутов проекта
  • Улучшенные отчеты о проделанной работе на основе статуса
  • Проверка соединений для хранилищ Nextcloud
  • Больше опций фильтрации для списков проектов
+ The release contains various new features and improvements, such as:
  • Keep and restore local versions of WYSIWYG content changes.
  • Enable a storage for multiple projects at once.
  • Export work packages in an updated modal with additional settings.
  • Display custom field columns/filters in project lists also in the Community Edition.
  • Support CloudFlare Turnstile as Captcha.
ical_sharing_modal: title: "Подписаться на календарь" inital_setup_error_message: "Произошла ошибка при получении данных." diff --git a/config/locales/crowdin/js-rw.yml b/config/locales/crowdin/js-rw.yml index 99269bca75a3..720748414931 100644 --- a/config/locales/crowdin/js-rw.yml +++ b/config/locales/crowdin/js-rw.yml @@ -358,10 +358,10 @@ rw: learn_about: "Learn more about the new features" #Include the version to invalidate outdated translations in other locales. #Otherwise, e.g. chinese might still have the translations for 10.0 in the 12.0 release. - "14_4": + "14_5": standard: new_features_html: > - The release contains various new features and improvements, such as:
  • Dark mode option in personal settings
  • Separate permissions for viewing and editing on project attributes
  • Improved status-based progress reporting
  • Connection validation for Nextcloud storages
  • More filter options for project lists
+ The release contains various new features and improvements, such as:
  • Keep and restore local versions of WYSIWYG content changes.
  • Enable a storage for multiple projects at once.
  • Export work packages in an updated modal with additional settings.
  • Display custom field columns/filters in project lists also in the Community Edition.
  • Support CloudFlare Turnstile as Captcha.
ical_sharing_modal: title: "Subscribe to calendar" inital_setup_error_message: "An error occured while fetching data." diff --git a/config/locales/crowdin/js-si.yml b/config/locales/crowdin/js-si.yml index 04db558bbe95..d3adfe9195c8 100644 --- a/config/locales/crowdin/js-si.yml +++ b/config/locales/crowdin/js-si.yml @@ -358,10 +358,10 @@ si: learn_about: "නව විශේෂාංග ගැන වැඩි විස්තර දැනගන්න" #Include the version to invalidate outdated translations in other locales. #Otherwise, e.g. chinese might still have the translations for 10.0 in the 12.0 release. - "14_4": + "14_5": standard: new_features_html: > - The release contains various new features and improvements, such as:
  • Dark mode option in personal settings
  • Separate permissions for viewing and editing on project attributes
  • Improved status-based progress reporting
  • Connection validation for Nextcloud storages
  • More filter options for project lists
+ The release contains various new features and improvements, such as:
  • Keep and restore local versions of WYSIWYG content changes.
  • Enable a storage for multiple projects at once.
  • Export work packages in an updated modal with additional settings.
  • Display custom field columns/filters in project lists also in the Community Edition.
  • Support CloudFlare Turnstile as Captcha.
ical_sharing_modal: title: "Subscribe to calendar" inital_setup_error_message: "An error occured while fetching data." diff --git a/config/locales/crowdin/js-sk.yml b/config/locales/crowdin/js-sk.yml index 7a6d39e28090..7d644a83c772 100644 --- a/config/locales/crowdin/js-sk.yml +++ b/config/locales/crowdin/js-sk.yml @@ -358,10 +358,10 @@ sk: learn_about: "Learn more about the new features" #Include the version to invalidate outdated translations in other locales. #Otherwise, e.g. chinese might still have the translations for 10.0 in the 12.0 release. - "14_4": + "14_5": standard: new_features_html: > - The release contains various new features and improvements, such as:
  • Dark mode option in personal settings
  • Separate permissions for viewing and editing on project attributes
  • Improved status-based progress reporting
  • Connection validation for Nextcloud storages
  • More filter options for project lists
+ The release contains various new features and improvements, such as:
  • Keep and restore local versions of WYSIWYG content changes.
  • Enable a storage for multiple projects at once.
  • Export work packages in an updated modal with additional settings.
  • Display custom field columns/filters in project lists also in the Community Edition.
  • Support CloudFlare Turnstile as Captcha.
ical_sharing_modal: title: "Subscribe to calendar" inital_setup_error_message: "An error occured while fetching data." diff --git a/config/locales/crowdin/js-sl.yml b/config/locales/crowdin/js-sl.yml index d76642c9125f..db27deae7642 100644 --- a/config/locales/crowdin/js-sl.yml +++ b/config/locales/crowdin/js-sl.yml @@ -357,10 +357,10 @@ sl: learn_about: "Preberite več o novostih" #Include the version to invalidate outdated translations in other locales. #Otherwise, e.g. chinese might still have the translations for 10.0 in the 12.0 release. - "14_4": + "14_5": standard: new_features_html: > - The release contains various new features and improvements, such as:
  • Dark mode option in personal settings
  • Separate permissions for viewing and editing on project attributes
  • Improved status-based progress reporting
  • Connection validation for Nextcloud storages
  • More filter options for project lists
+ The release contains various new features and improvements, such as:
  • Keep and restore local versions of WYSIWYG content changes.
  • Enable a storage for multiple projects at once.
  • Export work packages in an updated modal with additional settings.
  • Display custom field columns/filters in project lists also in the Community Edition.
  • Support CloudFlare Turnstile as Captcha.
ical_sharing_modal: title: "Subscribe to calendar" inital_setup_error_message: "An error occured while fetching data." diff --git a/config/locales/crowdin/js-sr.yml b/config/locales/crowdin/js-sr.yml index 4f358124f14c..636ea4d9e734 100644 --- a/config/locales/crowdin/js-sr.yml +++ b/config/locales/crowdin/js-sr.yml @@ -358,10 +358,10 @@ sr: learn_about: "Learn more about the new features" #Include the version to invalidate outdated translations in other locales. #Otherwise, e.g. chinese might still have the translations for 10.0 in the 12.0 release. - "14_4": + "14_5": standard: new_features_html: > - The release contains various new features and improvements, such as:
  • Dark mode option in personal settings
  • Separate permissions for viewing and editing on project attributes
  • Improved status-based progress reporting
  • Connection validation for Nextcloud storages
  • More filter options for project lists
+ The release contains various new features and improvements, such as:
  • Keep and restore local versions of WYSIWYG content changes.
  • Enable a storage for multiple projects at once.
  • Export work packages in an updated modal with additional settings.
  • Display custom field columns/filters in project lists also in the Community Edition.
  • Support CloudFlare Turnstile as Captcha.
ical_sharing_modal: title: "Subscribe to calendar" inital_setup_error_message: "An error occured while fetching data." diff --git a/config/locales/crowdin/js-sv.yml b/config/locales/crowdin/js-sv.yml index d51716b49d90..78fa0df05543 100644 --- a/config/locales/crowdin/js-sv.yml +++ b/config/locales/crowdin/js-sv.yml @@ -357,10 +357,10 @@ sv: learn_about: "Learn more about the new features" #Include the version to invalidate outdated translations in other locales. #Otherwise, e.g. chinese might still have the translations for 10.0 in the 12.0 release. - "14_4": + "14_5": standard: new_features_html: > - The release contains various new features and improvements, such as:
  • Dark mode option in personal settings
  • Separate permissions for viewing and editing on project attributes
  • Improved status-based progress reporting
  • Connection validation for Nextcloud storages
  • More filter options for project lists
+ The release contains various new features and improvements, such as:
  • Keep and restore local versions of WYSIWYG content changes.
  • Enable a storage for multiple projects at once.
  • Export work packages in an updated modal with additional settings.
  • Display custom field columns/filters in project lists also in the Community Edition.
  • Support CloudFlare Turnstile as Captcha.
ical_sharing_modal: title: "Subscribe to calendar" inital_setup_error_message: "An error occured while fetching data." diff --git a/config/locales/crowdin/js-th.yml b/config/locales/crowdin/js-th.yml index bf1616fbb378..69aa33e796bf 100644 --- a/config/locales/crowdin/js-th.yml +++ b/config/locales/crowdin/js-th.yml @@ -358,10 +358,10 @@ th: learn_about: "Learn more about the new features" #Include the version to invalidate outdated translations in other locales. #Otherwise, e.g. chinese might still have the translations for 10.0 in the 12.0 release. - "14_4": + "14_5": standard: new_features_html: > - The release contains various new features and improvements, such as:
  • Dark mode option in personal settings
  • Separate permissions for viewing and editing on project attributes
  • Improved status-based progress reporting
  • Connection validation for Nextcloud storages
  • More filter options for project lists
+ The release contains various new features and improvements, such as:
  • Keep and restore local versions of WYSIWYG content changes.
  • Enable a storage for multiple projects at once.
  • Export work packages in an updated modal with additional settings.
  • Display custom field columns/filters in project lists also in the Community Edition.
  • Support CloudFlare Turnstile as Captcha.
ical_sharing_modal: title: "Subscribe to calendar" inital_setup_error_message: "An error occured while fetching data." diff --git a/config/locales/crowdin/js-tr.yml b/config/locales/crowdin/js-tr.yml index d0a4b4f7e3f4..22c038274531 100644 --- a/config/locales/crowdin/js-tr.yml +++ b/config/locales/crowdin/js-tr.yml @@ -357,10 +357,10 @@ tr: learn_about: "Yeni özellikler hakkında daha fazla bilgi edinin" #Include the version to invalidate outdated translations in other locales. #Otherwise, e.g. chinese might still have the translations for 10.0 in the 12.0 release. - "14_4": + "14_5": standard: new_features_html: > - The release contains various new features and improvements, such as:
  • Dark mode option in personal settings
  • Separate permissions for viewing and editing on project attributes
  • Improved status-based progress reporting
  • Connection validation for Nextcloud storages
  • More filter options for project lists
+ The release contains various new features and improvements, such as:
  • Keep and restore local versions of WYSIWYG content changes.
  • Enable a storage for multiple projects at once.
  • Export work packages in an updated modal with additional settings.
  • Display custom field columns/filters in project lists also in the Community Edition.
  • Support CloudFlare Turnstile as Captcha.
ical_sharing_modal: title: "Subscribe to calendar" inital_setup_error_message: "An error occured while fetching data." diff --git a/config/locales/crowdin/js-uk.yml b/config/locales/crowdin/js-uk.yml index db00e521952c..7f9a320293ee 100644 --- a/config/locales/crowdin/js-uk.yml +++ b/config/locales/crowdin/js-uk.yml @@ -358,10 +358,10 @@ uk: learn_about: "Дізнатися більше про нові функції" #Include the version to invalidate outdated translations in other locales. #Otherwise, e.g. chinese might still have the translations for 10.0 in the 12.0 release. - "14_4": + "14_5": standard: new_features_html: > - The release contains various new features and improvements, such as:
  • Dark mode option in personal settings
  • Separate permissions for viewing and editing on project attributes
  • Improved status-based progress reporting
  • Connection validation for Nextcloud storages
  • More filter options for project lists
+ The release contains various new features and improvements, such as:
  • Keep and restore local versions of WYSIWYG content changes.
  • Enable a storage for multiple projects at once.
  • Export work packages in an updated modal with additional settings.
  • Display custom field columns/filters in project lists also in the Community Edition.
  • Support CloudFlare Turnstile as Captcha.
ical_sharing_modal: title: "Підписатися на календар" inital_setup_error_message: "Під час отримання даних сталася помилка." diff --git a/config/locales/crowdin/js-uz.yml b/config/locales/crowdin/js-uz.yml index 255f24f9706e..addb9b6a7c41 100644 --- a/config/locales/crowdin/js-uz.yml +++ b/config/locales/crowdin/js-uz.yml @@ -358,10 +358,10 @@ uz: learn_about: "Learn more about the new features" #Include the version to invalidate outdated translations in other locales. #Otherwise, e.g. chinese might still have the translations for 10.0 in the 12.0 release. - "14_4": + "14_5": standard: new_features_html: > - The release contains various new features and improvements, such as:
  • Dark mode option in personal settings
  • Separate permissions for viewing and editing on project attributes
  • Improved status-based progress reporting
  • Connection validation for Nextcloud storages
  • More filter options for project lists
+ The release contains various new features and improvements, such as:
  • Keep and restore local versions of WYSIWYG content changes.
  • Enable a storage for multiple projects at once.
  • Export work packages in an updated modal with additional settings.
  • Display custom field columns/filters in project lists also in the Community Edition.
  • Support CloudFlare Turnstile as Captcha.
ical_sharing_modal: title: "Subscribe to calendar" inital_setup_error_message: "An error occured while fetching data." diff --git a/config/locales/crowdin/js-vi.yml b/config/locales/crowdin/js-vi.yml index 04654dba5435..6c50aa83b82f 100644 --- a/config/locales/crowdin/js-vi.yml +++ b/config/locales/crowdin/js-vi.yml @@ -358,10 +358,10 @@ vi: learn_about: "Tìm hiểu thêm về các tính năng mới" #Include the version to invalidate outdated translations in other locales. #Otherwise, e.g. chinese might still have the translations for 10.0 in the 12.0 release. - "14_4": + "14_5": standard: new_features_html: > - Bản phát hành bao gồm nhiều tính năng và cải tiến mới, chẳng hạn như:
  • Tùy chọn chế độ tối trong cài đặt cá nhân
  • Quyền riêng biệt để xem và chỉnh sửa trên các thuộc tính của dự án
  • Cải thiện báo cáo tiến độ dựa trên trạng thái
  • Xác thực kết nối cho kho lưu trữ Nextcloud
  • Nhiều tùy chọn bộ lọc hơn cho danh sách dự án
+ The release contains various new features and improvements, such as:
  • Keep and restore local versions of WYSIWYG content changes.
  • Enable a storage for multiple projects at once.
  • Export work packages in an updated modal with additional settings.
  • Display custom field columns/filters in project lists also in the Community Edition.
  • Support CloudFlare Turnstile as Captcha.
ical_sharing_modal: title: "Đăng ký lịch" inital_setup_error_message: "Đã xảy ra lỗi khi lấy dữ liệu." diff --git a/config/locales/crowdin/js-zh-CN.yml b/config/locales/crowdin/js-zh-CN.yml index 8594af5bb2fb..89ad37c26421 100644 --- a/config/locales/crowdin/js-zh-CN.yml +++ b/config/locales/crowdin/js-zh-CN.yml @@ -74,7 +74,7 @@ zh-CN: button_copy: "复制" button_copy_to_clipboard: "复制到剪贴板" button_copy_link_to_clipboard: "将链接复制到剪贴板" - button_copy_to_other_project: "Duplicate in another project" + button_copy_to_other_project: "复制到其他项目" button_custom-fields: "自定义字段" button_delete: "删除" button_delete_watcher: "删除关注者" @@ -357,10 +357,10 @@ zh-CN: learn_about: "详细了解新功能" #Include the version to invalidate outdated translations in other locales. #Otherwise, e.g. chinese might still have the translations for 10.0 in the 12.0 release. - "14_4": + "14_5": standard: new_features_html: > - 该版本含有各种新的功能和改进。 例如:
  • 个人设置中的暗色模式选项
  • 项目属性的独立查看和编辑权限
  • 改进基于状态的进度报告
  • Nextcloud存储的连接验证
  • 项目列表的更多过滤选项
+ The release contains various new features and improvements, such as:
  • Keep and restore local versions of WYSIWYG content changes.
  • Enable a storage for multiple projects at once.
  • Export work packages in an updated modal with additional settings.
  • Display custom field columns/filters in project lists also in the Community Edition.
  • Support CloudFlare Turnstile as Captcha.
ical_sharing_modal: title: "订阅日历" inital_setup_error_message: "获取数据时发生错误。" diff --git a/config/locales/crowdin/js-zh-TW.yml b/config/locales/crowdin/js-zh-TW.yml index d9011c3862e5..f57a92894960 100644 --- a/config/locales/crowdin/js-zh-TW.yml +++ b/config/locales/crowdin/js-zh-TW.yml @@ -74,7 +74,7 @@ zh-TW: button_copy: "複製" button_copy_to_clipboard: "複製到剪貼簿" button_copy_link_to_clipboard: "複製到剪貼簿" - button_copy_to_other_project: "Duplicate in another project" + button_copy_to_other_project: "複製到其它專案" button_custom-fields: "客製欄位" button_delete: "删除" button_delete_watcher: "刪除監看者" @@ -138,8 +138,8 @@ zh-TW: description_select_work_package: "選取工作項目 #%{id}" description_subwork_package: "子工作項目 #%{id}" editor: - revisions: "Show local modifications" - no_revisions: "No local modifications found" + revisions: "顯示本機修改" + no_revisions: "本機未修改" preview: "切換預覽模式" source_code: "切換Markdown模式" error_saving_failed: "保存文件失敗, 出現以下錯誤: %{error}" @@ -277,9 +277,9 @@ zh-TW: 更改可能需要一些時間才能生效。當更新完所有相關工作包時,您將收到通知。 work_packages_settings: warning_progress_calculation_mode_change_from_status_to_field_pre_14_4_without_percent_complete_edition_html: >- - Changing progress calculation mode from status-based to work-based will make % Complete a non-editable field whose value is derived from Work and Remaining work. Existing values for % Complete are preserved. If values for Work and Remaining work were not present, they will be required in order to change % Complete. + 將進度計算模式從基於狀態更改為基於工作將使完成百分比成為不可編輯,其值源自工時剩餘工時% Complete 的現有值將會保留。如果工時剩餘工時的值不存在,則需要更改它們'才能修改完成百分比。 warning_progress_calculation_mode_change_from_status_to_field_html: >- - Changing progress calculation mode from status-based to work-based will make the % Complete field freely editable. If you optionally enter values for Work or Remaining work, they will also be linked to % Complete. Changing Remaining work can then update % Complete. + 將進度計算模式從基於狀態變更為基於工作將使完成百分比欄位可自由編輯。如果您選擇輸入工時剩餘工時,它們也會連結到完成百分比。更改剩餘工作可以更新完成百分比。 warning_progress_calculation_mode_change_from_field_to_status_html: >- 將進度計算模式從基於工時的方式改為基於狀態,將會導致所有現有的 %完整的 值丟失,並被與每個狀態相關的值所替代。 剩餘工時 的現有值也可能被重新計算,以反映這種變化。此操作不可逆轉。 custom_actions: @@ -356,10 +356,10 @@ zh-TW: learn_about: "瞭解更多新功能的資訊" #Include the version to invalidate outdated translations in other locales. #Otherwise, e.g. chinese might still have the translations for 10.0 in the 12.0 release. - "14_4": + "14_5": standard: new_features_html: > - 該版本含有各種新的功能和改進。 例如:
  • 個人設置中的暗色模式選項
  • 項目屬性的獨立查看和編輯權限
  • 改進基於狀態的進度報告
  • Nextcloud存儲的連接驗證
  • 項目列表的更多過濾選項
+ The release contains various new features and improvements, such as:
  • Keep and restore local versions of WYSIWYG content changes.
  • Enable a storage for multiple projects at once.
  • Export work packages in an updated modal with additional settings.
  • Display custom field columns/filters in project lists also in the Community Edition.
  • Support CloudFlare Turnstile as Captcha.
ical_sharing_modal: title: "訂閱日曆" inital_setup_error_message: "更新資料時發生錯誤" @@ -1183,7 +1183,7 @@ zh-TW: other: "%{count} 天" zero: "0 天" word: - other: "%{count} words" + other: "%{count} 字節" zen_mode: button_activate: "啟動 zen 模式" button_deactivate: "停用 zen 模式" diff --git a/config/locales/crowdin/zh-TW.yml b/config/locales/crowdin/zh-TW.yml index 580a403d87be..3d4bee3003e1 100644 --- a/config/locales/crowdin/zh-TW.yml +++ b/config/locales/crowdin/zh-TW.yml @@ -299,7 +299,7 @@ zh-TW: actions: label_enable_single: "於此專案使用,請按一下停用" label_disable_single: "於此專案未使用,請按一下啟用" - remove_from_project: "Remove from project" + remove_from_project: "從專案移除" label_enable_all: "全部啟用" label_disable_all: "全部停用" is_required_blank_slate: @@ -1031,10 +1031,10 @@ zh-TW: assigned_to: format: "%{message}" done_ratio: - does_not_match_work_and_remaining_work: "does not match Work and Remaining work" - cannot_be_set_when_work_is_zero: "cannot be set when Work is 0h" - must_be_set_when_remaining_work_is_set: "required when Remaining work is set." - must_be_set_when_work_and_remaining_work_are_set: "required when Work and Remaining work are set." + does_not_match_work_and_remaining_work: "工作與剩餘工作不符" + cannot_be_set_when_work_is_zero: "工時為0無法設置" + must_be_set_when_remaining_work_is_set: "剩餘工時已設定時必填" + must_be_set_when_work_and_remaining_work_are_set: "工時與剩餘工時已設定時必填" inclusion: "必須介於 0 和 100 之間。" due_date: not_start_date: "儘管日期是里程碑所必需的,但不是開始日期。" @@ -1064,17 +1064,17 @@ zh-TW: does_not_exist: "指定的類別不存在" estimated_hours: not_a_number: "不是有效的持續時間。" - cant_be_inferior_to_remaining_work: "cannot be lower than Remaining work." - must_be_set_when_remaining_work_and_percent_complete_are_set: "required when Remaining work and % Complete are set." + cant_be_inferior_to_remaining_work: "不能低於剩餘工時。" + must_be_set_when_remaining_work_and_percent_complete_are_set: "剩餘工時 和 完成百分比 已設置時必填。" remaining_hours: not_a_number: "不是有效的持續時間。" - cant_exceed_work: "cannot be higher than Work." - must_be_set_when_work_is_set: "required when Work is set." - must_be_set_when_work_and_percent_complete_are_set: "required when Work and % Complete are set." + cant_exceed_work: "不能高於工時。" + must_be_set_when_work_is_set: "工時已設定時必填" + must_be_set_when_work_and_percent_complete_are_set: "工時 和 完成百分比 已設置時必填。" must_be_set_to_zero_hours_when_work_is_set_and_percent_complete_is_100p: >- - must be 0h when Work is set and % Complete is 100%. + 當工時設定後,其完成度100%時,剩餘工時必須為 0。 must_be_empty_when_work_is_empty_and_percent_complete_is_100p: >- - must be empty when Work is empty and % Complete is 100%. + 工時未設定設定,但完成度100%時,剩餘工時必須是空白。 readonly_status: "工作項目處於唯讀狀態,因此無法變更其屬性。" type: attributes: @@ -3079,9 +3079,9 @@ zh-TW: setting_work_package_done_ratio_field: "基於工時" setting_work_package_done_ratio_status: "基於狀態" setting_work_package_done_ratio_explanation_pre_14_4_without_percent_complete_edition_html: > - In work-based mode, % Complete is calculated from how much work is done in relation to total work. In status-based mode, each status has a % Complete value associated with it. Changing status will change % Complete. + 在基於工作模式下,完成百分比是根據已完成的工作量相對於總工作量來計算的。在基於狀態模式下,每個狀態都有一個與其關聯的完成百分比值。更改狀態將更改完成百分比。 setting_work_package_done_ratio_explanation_html: > - In work-based mode, % Complete can be freely set to any value. If you optionally enter a value for Work, Remaining work will automatically be derived. In status-based mode, each status has a % Complete value associated with it. Changing status will change % Complete. + 在基於工作模式下,完成百分比可以自由設定為任何值。如果您可以選擇輸入工時,則會自動算出剩餘工時。在基於狀態模式下,每個狀態都有一個與其關聯的完成百分比值。更改狀態將更改完成百分比。 setting_work_package_properties: "工作項目屬性" setting_work_package_startdate_is_adddate: "使用目前日期作為新工作項目的開始日期" setting_work_packages_projects_export_limit: "工作項目/專案匯出數量限制" @@ -3463,26 +3463,26 @@ zh-TW: progress: label_note: "備註" modal: - work_based_help_text: "Each field is automatically calculated from the two others when possible." - work_based_help_text_pre_14_4_without_percent_complete_edition: "% Complete is automatically derived from Work and Remaining work." + work_based_help_text: "在可能的情況下,每個欄位都會根據其他兩個欄位自動計算。" + work_based_help_text_pre_14_4_without_percent_complete_edition: "完成百分比由 \"工時\" 和 \"剩餘工時\" 自動得出。" status_based_help_text: "完成百分比由工作包狀態設定。" migration_warning_text: "在「基於工時」進度計算模式下,完成百分比無法手動設置,並且與「工時」相關聯。目前手動輸入數值已保留,無法編輯。 請務必輸入「工時」才能進行。" derivation_hints: done_ratio: - cleared_because_remaining_work_is_empty: "Cleared because Remaining work is empty." - cleared_because_work_is_0h: "Cleared because Work is 0h." - derived: "Derived from Work and Remaining work." + cleared_because_remaining_work_is_empty: "已清除,因為無剩餘工時。" + cleared_because_work_is_0h: "已清除,因為工時為0。" + derived: "源自工時和剩餘工時。" estimated_hours: - cleared_because_remaining_work_is_empty: "Cleared because Remaining work is empty." - derived: "Derived from Remaining work and % Complete." - same_as_remaining_work: "Set to same value as Remaining work." + cleared_because_remaining_work_is_empty: "已清除,因為無剩餘工時。" + derived: "源自剩餘工時和完成百分比。" + same_as_remaining_work: "設定與剩餘工時相同值。" remaining_hours: - cleared_because_work_is_empty: "Cleared because Work is empty." - cleared_because_percent_complete_is_empty: "Cleared because % Complete is empty." - decreased_like_work: "Decreased by the same amount as Work." - derived: "Derived from Work and % Complete." - increased_like_work: "Increased by the same amount as Work." - same_as_work: "Set to same value as Work." + cleared_because_work_is_empty: "已清除,因為無工時。" + cleared_because_percent_complete_is_empty: "已清除,因為無完成度。" + decreased_like_work: "減少至工時相同時數。" + derived: "源自工時和完成百分比。" + increased_like_work: "增加與工時相同時數。" + same_as_work: "設定與工時相同值。" permissions: comment: "留言" comment_description: "可查看此工作項目與留言" diff --git a/modules/gitlab_integration/config/locales/crowdin/hu.yml b/modules/gitlab_integration/config/locales/crowdin/hu.yml index 321e2c484016..4392d9124faa 100644 --- a/modules/gitlab_integration/config/locales/crowdin/hu.yml +++ b/modules/gitlab_integration/config/locales/crowdin/hu.yml @@ -64,6 +64,6 @@ hu: push_single_commit_comment: > **Frissítés az MR-ben:** [%{gitlab_user}](%{gitlab_user_url}) frissítette a következőkkel: [%{commit_number}](%{commit_url}) a(z) [%{repository}](%{repository_url}) ekkor: %{commit_timestamp}, üzenet: %{commit_note} push_single_commit_comment_with_ref: > - **Pushed in %{reference}:** [%{gitlab_user}](%{gitlab_user_url}) pushed [%{commit_number}](%{commit_url}) to [%{repository}](%{repository_url}) at %{commit_timestamp}: %{commit_note} + **Frissítés itt: %{reference}:** [%{gitlab_user}](%{gitlab_user_url}) frissítette a következőkkel: [%{commit_number}](%{commit_url}), itt [%{repository}](%{repository_url}), ekkor: %{commit_timestamp}, üzenet: %{commit_note} push_multiple_commits_comment: > **Frissítés az MR-ben:** [%{gitlab_user}](%{gitlab_user_url}) frissítette a következőkkel: [%{commit_number}](%{commit_url}) a(z) [%{repository}](%{repository_url}) ekkor: %{commit_timestamp}, üzenet: %{commit_note} diff --git a/modules/grids/config/locales/crowdin/js-hu.yml b/modules/grids/config/locales/crowdin/js-hu.yml index 2a12eba77036..49b6da0c8fcb 100644 --- a/modules/grids/config/locales/crowdin/js-hu.yml +++ b/modules/grids/config/locales/crowdin/js-hu.yml @@ -43,8 +43,8 @@ hu: title: 'Alprojektek' no_results: "Nincsenek alprojektek\n" project_favorites: - title: 'Favorite projects' - no_results: 'You currently have no favorite projects. Click on the star icon in the project dashboard to add one to your favorites.' + title: 'Kedvenc projektek' + no_results: 'Jelenleg nincsenek kedvenc projektjei. Kattintson a csillag ikonra a projekt műszerfalon, hogy felvegyen egyet a kedvencei közé.' time_entries_current_user: title: 'Eltöltött idő rögzítése' displayed_days: 'Napok megjelenítése a főoldalon.' diff --git a/modules/meeting/config/locales/crowdin/hu.yml b/modules/meeting/config/locales/crowdin/hu.yml index f90039b079ad..f8fb6c86d8c4 100644 --- a/modules/meeting/config/locales/crowdin/hu.yml +++ b/modules/meeting/config/locales/crowdin/hu.yml @@ -113,17 +113,17 @@ hu: label_start_date: "Kezdési dátum" meeting: attachments: - text: "Attached files are available to all meeting participants. You can also drag and drop these into agenda item notes." + text: "A csatolt fájlok az ülés valamennyi résztvevője számára elérhetők. Ezeket a napirendi pontok jegyzeteibe is behúzhatja." copy: - title: "Copy meeting: %{title}" - attachments: "Copy attachments" - attachments_text: "Copy over all attached files to the new meeting" + title: "%{title} megbeszélés másolása" + attachments: "Mellékletek másolása" + attachments_text: "Másolja át az összes csatolt fájlt az új megbeszélésre" agenda: "Napirend másolása" agenda_text: "A régi megbeszélés napirendjének másolása" email: send_emails: "Email participants" send_invitation_emails: > - Send an email invitation immediately to the participants selected above. You can also do this manually at any time later. + Azonnal küldjön e-mail meghívót a fent kiválasztott résztvevőknek. Ezt később bármikor manuálisan is megteheti. open_meeting_link: "Nyitott megbeszélés" invited: summary: "%{actor} meghívott a következő megbeszélésre: %{title}" @@ -145,10 +145,10 @@ hu: untitled_title: "Untitled section" delete_confirmation: "Deleting the section will also delete all of its agenda items. Are you sure you want to do this?" placeholder_title: "New section" - empty_text: "Drag items here or create a new one" + empty_text: "Húzza ide az elemeket, vagy hozzon létre egy újat" notice_successful_notification: "Értesítés sikeresen kiküldve" notice_timezone_missing: Nincs időzóna beállítva, %{zone} a feltételezett. Időzóna beállításához kattintson ide. - notice_meeting_updated: "This page has been updated by someone else. Reload to view changes." + notice_meeting_updated: "Ezt az oldalt valaki más frissítette. A változások megtekintéséhez töltse újra." permission_create_meetings: "Megbeszélések létrehozása" permission_edit_meetings: "Megbeszélések szerkesztése" permission_delete_meetings: "Megbeszélések törlése" @@ -180,10 +180,10 @@ hu: label_meeting_delete: "Megbeszélés törlése" label_meeting_created_by: "Létrehozta" label_meeting_last_updated: "Utoljára frissítve" - label_meeting_reload: "Reload" - label_agenda_items: "Agenda items" + label_meeting_reload: "Újratöltés" + label_agenda_items: "Napirendi pontok" label_agenda_items_reordered: "Átrakva" - label_agenda_item_remove: "Remove from agenda" + label_agenda_item_remove: "Levétel a napirendről" label_agenda_item_undisclosed_wp: "Munkacsomag #%{id} nem látható" label_agenda_item_deleted_wp: "Törölt munkacsomag-hivatkozás" label_agenda_item_actions: "A napirendi pontok intézkedései" @@ -192,18 +192,18 @@ hu: label_agenda_item_move_up: "Mozgatás felfelé" label_agenda_item_move_down: "Mozgás lefelé" label_agenda_item_add_notes: "Megjegyzések hozzáadása" - label_agenda_item_work_package: "Agenda item work package" - text_agenda_item_title: 'Agenda item "%{title}"' - text_agenda_work_package_deleted: 'Agenda item for deleted work package' - text_deleted_agenda_item: 'Deleted agenda item' + label_agenda_item_work_package: "Napirendi ponthoz kapcsolódó feladatcsoport" + text_agenda_item_title: 'Napirendi pont "%{title}"' + text_agenda_work_package_deleted: 'A törölt feladatcsoporthoz tartozó napirendi pont' + text_deleted_agenda_item: 'Törölt napirendi pont' label_initial_meeting_details: "Megbeszélés" label_meeting_details: "A megbeszélés részletei" label_meeting_details_edit: "Megbeszélés részleteinek szerkesztése" - label_meeting_state: "Meeting status" + label_meeting_state: "A megbeszélés státusza" label_meeting_state_open: "Open" - label_meeting_state_open_html: "Open" + label_meeting_state_open_html: "Nyitva" label_meeting_state_closed: "Lezárva" - label_meeting_state_closed_html: "Closed" + label_meeting_state_closed_html: "Lezárva" label_meeting_reopen_action: "A megbeszélés újranyitása" label_meeting_close_action: "Megbeszélés lezárása" text_meeting_open_description: "Ez a megbeszélés nyitott. A napirendi pontokat tetszés szerint hozzáadhatja/eltávolíthatja és szerkesztheti. A megbeszélés végeztével zárja be, hogy archíválja azt." diff --git a/modules/meeting/config/locales/crowdin/zh-TW.yml b/modules/meeting/config/locales/crowdin/zh-TW.yml index cda408567904..c5de434f42fb 100644 --- a/modules/meeting/config/locales/crowdin/zh-TW.yml +++ b/modules/meeting/config/locales/crowdin/zh-TW.yml @@ -120,7 +120,7 @@ zh-TW: agenda: "複製議程" agenda_text: "複製舊會議之議程" email: - send_emails: "Email participants" + send_emails: "寄發參與者" send_invitation_emails: > 立即發送電子郵件邀請函給上述選定的與會者。您也可以稍後隨時手動執行。 open_meeting_link: "打開會議連結" diff --git a/modules/storages/config/locales/crowdin/ru.yml b/modules/storages/config/locales/crowdin/ru.yml index 720107bc9b8c..cd283cf541a5 100644 --- a/modules/storages/config/locales/crowdin/ru.yml +++ b/modules/storages/config/locales/crowdin/ru.yml @@ -70,7 +70,7 @@ ru: dialog: automatically_managed_appendix: Кроме того, в данном случае в этом хранилище есть автоматически управляемая папка проекта, она и её файлы будут удалены навсегда. confirmation_text: Пожалуйста, подтвердите, что Вы понимаете и хотите удалить это файловое хранилище из данного проекта - heading_text: Remove project from %{storage} + heading_text: Удалить проект из %{storage} text: Это действие необратимо и удалит все ссылки из пакетов работ этого проекта на файлы и папки этого хранилища. label: Удалить проект services: diff --git a/modules/storages/config/locales/crowdin/zh-CN.yml b/modules/storages/config/locales/crowdin/zh-CN.yml index 30bdce3b7e2c..a1520221a8be 100644 --- a/modules/storages/config/locales/crowdin/zh-CN.yml +++ b/modules/storages/config/locales/crowdin/zh-CN.yml @@ -70,7 +70,7 @@ zh-CN: dialog: automatically_managed_appendix: 而且,在这种情况下,这个存储有一个自动托管的项目文件夹,它和它的文件将被永久删除。 confirmation_text: 请确认您已理解并要从此项目中删除此文件存储 - heading_text: Remove project from %{storage} + heading_text: 从 %{storage} 中删除项目 text: 此操作不可逆,将从此项目的工作包中删除所有链接到该存储的文件和文件夹。 label: 删除项目 services: diff --git a/modules/storages/config/locales/crowdin/zh-TW.yml b/modules/storages/config/locales/crowdin/zh-TW.yml index b9a4808504f9..10d31db55a7a 100644 --- a/modules/storages/config/locales/crowdin/zh-TW.yml +++ b/modules/storages/config/locales/crowdin/zh-TW.yml @@ -70,7 +70,7 @@ zh-TW: dialog: automatically_managed_appendix: 此外,在這種情況下,此儲存空間有一個自動管理的專案資料夾,此資料夾及其檔案將永遠刪除。 confirmation_text: 請確認您瞭解並希望從本專案中移除此檔案儲存空間 - heading_text: Remove project from %{storage} + heading_text: 從 %{storage} 移除專案 text: 此動作是不可逆轉的,並會移除此專案的工作項目到該儲存的檔案和資料夾的所有連結。 label: 移除專案 services: From 50b106ce556b1b01441953195701361dcd8014c7 Mon Sep 17 00:00:00 2001 From: ulferts Date: Thu, 5 Sep 2024 13:36:08 +0200 Subject: [PATCH 16/16] update ruby version requirement in docs --- docs/installation-and-operations/system-requirements/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/installation-and-operations/system-requirements/README.md b/docs/installation-and-operations/system-requirements/README.md index 04ab87a56dca..45853f3979fd 100644 --- a/docs/installation-and-operations/system-requirements/README.md +++ b/docs/installation-and-operations/system-requirements/README.md @@ -83,7 +83,7 @@ The [docker-based installation](../installation/docker) requires a system with D Both the package and docker based installations will install and setup the following dependencies that are required by OpenProject to run: -* __Runtime:__ [Ruby](https://www.ruby-lang.org/en/) Version = 2.7.x +* __Runtime:__ [Ruby](https://www.ruby-lang.org/en/) Version = 3.3.x * __Webserver:__ [Apache](https://httpd.apache.org/) or [nginx](https://nginx.org/en/docs/) * __Application server:__ [Puma](https://puma.io/)