diff --git a/config/initializers/menus.rb b/config/initializers/menus.rb index 74b281889850..6d5a3d9bc8d3 100644 --- a/config/initializers/menus.rb +++ b/config/initializers/menus.rb @@ -68,7 +68,7 @@ OpenProject::Static::Links.help_link, last: true, caption: '', - icon: 'icon-help op-app-help--icon', + icon: 'help op-app-help--icon', html: { accesskey: OpenProject::AccessKeys.key_for(:help), title: I18n.t('label_help'), target: '_blank' } diff --git a/docs/development/data-flow/README.md b/docs/development/data-flow/README.md index 072a865ef122..bd2811fc3e2f 100644 --- a/docs/development/data-flow/README.md +++ b/docs/development/data-flow/README.md @@ -1,4 +1,4 @@ -# Data flow and Usage +# Data flow and usage Regardless of the type of installation of OpenProject, the following diagram provides a high-level overview of through which systems data related to OpenProject is flowing. diff --git a/docs/getting-started/my-activity/README.md b/docs/getting-started/my-activity/README.md index 1c2d87061324..f96040114b07 100644 --- a/docs/getting-started/my-activity/README.md +++ b/docs/getting-started/my-activity/README.md @@ -18,7 +18,9 @@ You will see two lists by default. **Projects** will show all projects you are a member of. -**Activity** will show all of your activities that are being recorded in OpenProject. Note that only activities from projects that have enabled the "Activity" module will be shown. +**Activity** will show all of your activities that are being recorded in OpenProject. + +>Please note that only activities from projects that have the **Activity** module enabled will be shown. ![Openproject_my_activity_page](openproject_my_activity_overview.png) diff --git a/docs/release-notes/13-0-7/README.md b/docs/release-notes/13-0-7/README.md new file mode 100644 index 000000000000..e51224bec30f --- /dev/null +++ b/docs/release-notes/13-0-7/README.md @@ -0,0 +1,27 @@ +--- +title: OpenProject 13.0.7 +sidebar_navigation: + title: 13.0.7 +release_version: 13.0.7 +release_date: 2023-10-23 +--- + +# OpenProject 13.0.7 + +Release date: 2023-10-23 + +We released [OpenProject 13.0.7](https://community.openproject.com/versions/1938). +The release contains several bug fixes and we recommend updating to the newest version. + + +#### Bug fixes and changes + +- Fixed: File Drag and Drop \[[#49507](https://community.openproject.com/wp/49507)\] +- Fixed: Help icon not shown when having a custom help link setting \[[#50666](https://community.openproject.com/wp/50666)\] + +#### Contributions +A big thanks to community members for reporting bugs and helping us identifying and providing fixes. + +Special thanks for reporting and finding bugs go to + +Patrick Stapf diff --git a/docs/release-notes/README.md b/docs/release-notes/README.md index 78523647d263..20ed43d5c0d6 100644 --- a/docs/release-notes/README.md +++ b/docs/release-notes/README.md @@ -14,6 +14,13 @@ Stay up to date and get an overview of the new features included in the releases +## 13.0.7 + +Release date: 2023-10-23 + +[Release Notes](13-0-7/) + + ## 13.0.6 Release date: 2023-10-13 diff --git a/frontend/src/app/shared/components/attachments/attachments.component.ts b/frontend/src/app/shared/components/attachments/attachments.component.ts index da917fe50b2b..a0e3848fb813 100644 --- a/frontend/src/app/shared/components/attachments/attachments.component.ts +++ b/frontend/src/app/shared/components/attachments/attachments.component.ts @@ -113,7 +113,13 @@ export class OpAttachmentsComponent extends UntilDestroyedMixin implements OnIni }; private onGlobalDragEnter:(_event:DragEvent) => void = (_event) => { - this.dragging += 1; + // When the global drag and drop is active and the dragging happens over the DOM + // elements, the dragenter and dragleave events are always fired in pairs. + // On dragenter the this.dragging is set to 2 and on dragleave we deduct it to 1, + // meaning the drag and drop remains active. When the drag and drop action is canceled + // i.e. by the "Escape" key, an extra dragleave event is fired. + // In this case this.dragging will be deducted to 0, disabling the active drop areas. + this.dragging = 2; this.cdRef.detectChanges(); }; diff --git a/frontend/src/app/shared/components/editor/components/ckeditor/op-ckeditor.component.ts b/frontend/src/app/shared/components/editor/components/ckeditor/op-ckeditor.component.ts index 02fa45e1c8f1..dc13f6fa0136 100644 --- a/frontend/src/app/shared/components/editor/components/ckeditor/op-ckeditor.component.ts +++ b/frontend/src/app/shared/components/editor/components/ckeditor/op-ckeditor.component.ts @@ -232,13 +232,6 @@ export class OpCkeditorComponent implements OnInit, OnDestroy { model.on('op:attachment-added', () => document.body.dispatchEvent(new DragEvent('dragend'))); model.on('op:attachment-removed', () => document.body.dispatchEvent(new DragEvent('dragend'))); - // Emitting a global dragleave on every dragleave of the ckeditor element - // IMPORTANT: This emits much more dragleave events then dragenter events. - // In the end, this leads to a break in every drop zone that listens to those two global events - // to determine its state. Without it, if no dragleave is fired, the drop zones enter a failed state, - // not vanishing after ending the drag. - this.$element.on('dragleave', () => document.body.dispatchEvent(new DragEvent('dragleave'))); - this.initializeDone.emit(watchdog.editor); return watchdog.editor; }); diff --git a/frontend/src/app/shared/components/storages/storage/storage.component.ts b/frontend/src/app/shared/components/storages/storage/storage.component.ts index 36efddd44129..4919c1efbe34 100644 --- a/frontend/src/app/shared/components/storages/storage/storage.component.ts +++ b/frontend/src/app/shared/components/storages/storage/storage.component.ts @@ -189,7 +189,13 @@ export class StorageComponent extends UntilDestroyedMixin implements OnInit, OnD }; private onGlobalDragEnter:(_event:DragEvent) => void = (_event) => { - this.dragging += 1; + // When the global drag and drop is active and the dragging happens over the DOM + // elements, the dragenter and dragleave events are always fired in pairs. + // On dragenter the this.dragging is set to 2 and on dragleave we deduct it to 1, + // meaning the drag and drop remains active. When the drag and drop action is canceled + // i.e. by the "Escape" key, an extra dragleave event is fired. + // In this case this.dragging will be deducted to 0, disabling the active drop areas. + this.dragging = 2; this.cdRef.detectChanges(); }; diff --git a/frontend/src/global_styles/common/header/app-help.sass b/frontend/src/global_styles/common/header/app-help.sass index b18f0f9c524f..57acde51d631 100644 --- a/frontend/src/global_styles/common/header/app-help.sass +++ b/frontend/src/global_styles/common/header/app-help.sass @@ -1,5 +1,6 @@ .op-app-help - &--icon + // For the higher specificity we switch to this nested class notation + .op-app-help--icon &::before display: flex justify-content: center diff --git a/lib/open_project/version.rb b/lib/open_project/version.rb index 1c5645415d88..50e0f4b62947 100644 --- a/lib/open_project/version.rb +++ b/lib/open_project/version.rb @@ -33,7 +33,7 @@ module OpenProject module VERSION # :nodoc: MAJOR = 13 MINOR = 0 - PATCH = 6 + PATCH = 7 class << self # Used by semver to define the special version (if any). diff --git a/lib/redmine/menu_manager/top_menu/help_menu.rb b/lib/redmine/menu_manager/top_menu/help_menu.rb index 4b088d72f44e..3a8c4df6ff37 100644 --- a/lib/redmine/menu_manager/top_menu/help_menu.rb +++ b/lib/redmine/menu_manager/top_menu/help_menu.rb @@ -49,7 +49,7 @@ def render_help_dropdown title: I18n.t(:label_help), class: 'op-app-menu--item-action', aria: { haspopup: 'true' } do - op_icon('icon-help op-app-help--icon') + spot_icon('help', size: '1_25', classnames: 'op-app-help--icon') end render_menu_dropdown( diff --git a/modules/avatars/config/locales/crowdin/az.yml b/modules/avatars/config/locales/crowdin/az.yml index 18037cdce663..0042df653ea2 100644 --- a/modules/avatars/config/locales/crowdin/az.yml +++ b/modules/avatars/config/locales/crowdin/az.yml @@ -3,39 +3,39 @@ az: plugin_openproject_avatars: name: "Avatarlar" description: >- - This plugin allows OpenProject users to upload a picture to be used as an avatar or use registered images from Gravatar. + Bu plagin OpenProject istifadəçilərinə avatar kimi istifadə edilmək üçün şəkil yükləməyə və ya Gravatar-dan qeydə alınmış şəkillərdən istifadə etməyə imkan verir. label_avatar: "Avatar" label_avatar_plural: "Avatarlar" label_current_avatar: "Cari avatar" - label_choose_avatar: "Choose Avatar from file" - message_avatar_uploaded: "Avatar changed successfully." - error_image_upload: "Error saving the image." - error_image_size: "The image is too large." - button_change_avatar: "Change avatar" - are_you_sure_delete_avatar: "Are you sure you want to delete your avatar?" - avatar_deleted: "Avatar deleted successfully." - unable_to_delete_avatar: "Avatar could not be deleted." - wrong_file_format: "Allowed formats are jpg, png, gif" - empty_file_error: "Please upload a valid image (jpg, png, gif)" + label_choose_avatar: "Avatar seçin" + message_avatar_uploaded: "Avatar uğurla dəyişdirildi" + error_image_upload: "Şəkli yadda saxlama xətası" + error_image_size: "Şəkil çox böyükdür" + button_change_avatar: "Avatarı dəyişdirin" + are_you_sure_delete_avatar: "Avatarınızı silmək istədiyinizə əminsiniz?" + avatar_deleted: "Avatar uğurla silindi." + unable_to_delete_avatar: "Avatar silinmədi." + wrong_file_format: "İcazə verilən formatlar jpg, png, gif-dir" + empty_file_error: "Zəhmət olmasa düzgün şəkil yükləyin (jpg, png, gif)" avatars: label_avatar: "Avatar" label_gravatar: 'Gravatar' label_current_avatar: 'Cari avatar' label_local_avatar: 'Fərdi avatar' text_current_avatar: | - The following image shows the current avatar. + Aşağıdakı şəkil cari avatar olduğunu göstərir. text_upload_instructions: | - Upload your own custom avatar of 128 by 128 pixels. Larger files will be resized and cropped to match. - A preview of your avatar will be shown before uploading, once you selected an image. - text_change_gravatar_html: 'To change or add the Gravatar for your mail address, go to %{gravatar_url}.' + 128x128 piksel ölçüsündə öz fərdi avatarınızı yükləyin. Daha böyük faylların ölçüsü dəyişdiriləcək və uyğunlaşmaq üçün kəsiləcək. + Siz şəkil seçdikdən sonra, avatarınız yükləməzdən əvvəl sızə göstəriləcək + text_change_gravatar_html: 'Poçt ünvanınızın Gravatarını dəyişmək və ya əlavə etmək üçün %{gravatar_url} ünvanına keçin.' text_your_local_avatar: | - OpenProject allows you to upload your own custom avatar. + OpenProject sizə öz fərdi avatarınızı yükləməyə imkan verir. text_local_avatar_over_gravatar: | - If you set one, this custom avatar is used in precedence over the gravatar above. + Əgər birini təyin etsəniz, bu fərdi avatar yuxarıdakı qravatardan üstün olaraq istifadə olunur. text_your_current_gravatar: | - OpenProject uses your gravatar if you registered one, or a default image or icon if one exists. - The current gravatar is as follows: + OpenProject qravatarınızdan, əgər varsa, defolt şəkil və ya ikonadan istifadə edir. + Hazırkı qravatar aşağıdakı kimidir settings: - enable_gravatars: 'Enable user gravatars' - gravatar_default: "Default Gravatar image" - enable_local_avatars: 'Enable user custom avatars' + enable_gravatars: 'İstifadəçi qravatarlarını aktivləşdirin' + gravatar_default: "Defolt Gravatar şəkli" + enable_local_avatars: 'İstifadəçinin fərdi avatarlarını aktivləşdirin' diff --git a/modules/avatars/config/locales/crowdin/js-az.yml b/modules/avatars/config/locales/crowdin/js-az.yml index fd569287335f..bf0c33d2699a 100644 --- a/modules/avatars/config/locales/crowdin/js-az.yml +++ b/modules/avatars/config/locales/crowdin/js-az.yml @@ -4,12 +4,12 @@ az: label_preview: 'İlkin baxılış' button_update: 'Yeniləmə' avatars: - label_choose_avatar: "Choose Avatar from file" - uploading_avatar: "Uploading your avatar." + label_choose_avatar: "Avatar seçin" + uploading_avatar: "Avatarınız yüklənir" text_upload_instructions: | - Upload your own custom avatar of 128 by 128 pixels. Larger files will be resized and cropped to match. - A preview of your avatar will be shown before uploading, once you selected an image. - error_image_too_large: "Image is too large." - wrong_file_format: "Allowed formats are jpg, png, gif" - empty_file_error: "Please upload a valid image (jpg, png, gif)" + 128x128 piksel ölçüsündə öz fərdi avatarınızı yükləyin. Daha böyük faylların ölçüsü dəyişdiriləcək və uyğunlaşmaq üçün kəsiləcək. + Siz şəkil seçdikdən sonra, avatarınız yükləməzdən əvvəl sızə göstəriləcək + error_image_too_large: "Şəkil çox böyükdür" + wrong_file_format: "İcazə verilən formatlar jpg, png, gif-dir" + empty_file_error: "Zəhmət olmasa düzgün şəkil yükləyin (jpg, png, gif)" diff --git a/modules/backlogs/config/locales/crowdin/az.yml b/modules/backlogs/config/locales/crowdin/az.yml index 2641b3cbf942..683c7aa8a615 100644 --- a/modules/backlogs/config/locales/crowdin/az.yml +++ b/modules/backlogs/config/locales/crowdin/az.yml @@ -27,7 +27,7 @@ az: attributes: work_package: position: "Vəzifə" - remaining_hours: "Remaining hours" + remaining_hours: "Qalan vaxt %d saat" remaining_time: "Remaining hours" derived_remaining_hours: "Derived remaining hours" derived_remaining_time: "Derived remaining hours" diff --git a/modules/storages/app/contracts/storages/project_storages/base_contract.rb b/modules/storages/app/contracts/storages/project_storages/base_contract.rb index 08faa3abed12..896572111781 100644 --- a/modules/storages/app/contracts/storages/project_storages/base_contract.rb +++ b/modules/storages/app/contracts/storages/project_storages/base_contract.rb @@ -52,10 +52,20 @@ class BaseContract < ::ModelContract end end + validate :project_folder_automatic_mode, unless: -> { errors.include?(:project_folder_mode) } + private def project_folder_mode_manual? @model.project_folder_manual? end + + def project_folder_automatic_mode + return unless @model.project_folder_automatic? + + unless @model.automatic_management_possible? + errors.add :project_folder_mode, :mode_unavailable + end + end end end diff --git a/modules/storages/app/models/storages/project_storage.rb b/modules/storages/app/models/storages/project_storage.rb index 36cd29fc5739..89b8a90c25e7 100644 --- a/modules/storages/app/models/storages/project_storage.rb +++ b/modules/storages/app/models/storages/project_storage.rb @@ -51,6 +51,10 @@ class Storages::ProjectStorage < ApplicationRecord scope :automatic, -> { where(project_folder_mode: 'automatic') } + def automatic_management_possible? + storage.present? && storage.provider_type_nextcloud? && storage.automatically_managed? + end + def project_folder_path "#{storage.group_folder}/#{project.name.gsub('/', '|')} (#{project.id})/" end diff --git a/modules/storages/app/views/storages/project_settings/_project_folder_form.html.erb b/modules/storages/app/views/storages/project_settings/_project_folder_form.html.erb index 2a06dde01bbc..8fdadbb09775 100644 --- a/modules/storages/app/views/storages/project_settings/_project_folder_form.html.erb +++ b/modules/storages/app/views/storages/project_settings/_project_folder_form.html.erb @@ -88,18 +88,20 @@ See COPYRIGHT and LICENSE files for more details. <%= t(:"storages.instructions.no_specific_folder") %> -