Merge branch 'dev' into 45001-component-to-show-the-list-of-non-working-days-of-year

45001-component-to-show-the-list-of-non-working-days-of-year
bsatarnejad 2 years ago
commit e9aec723f3
  1. 6
      Gemfile
  2. 22
      Gemfile.lock
  3. 7
      app/contracts/users/create_contract.rb
  4. 2
      app/models/queries/members/filters/group_filter.rb
  5. 8
      app/views/activities/index.html.erb
  6. 12
      config/locales/crowdin/js-tr.yml
  7. 10
      config/locales/crowdin/tr.yml
  8. 2
      docs/README.md
  9. 2
      docs/installation-and-operations/README.md
  10. 2
      docs/installation-and-operations/installation-faq/README.md
  11. 16
      docs/installation-and-operations/installation/README.md
  12. 24
      docs/installation-and-operations/installation/manual/README.md
  13. 2
      docs/release-notes/12-2-0/README.md
  14. 2
      docs/release-notes/12-2-1/README.md
  15. BIN
      docs/user-guide/nextcloud-integration/NC_removeFileLinkButton.png
  16. 68
      docs/user-guide/nextcloud-integration/README.md
  17. BIN
      docs/user-guide/notifications/NotificationCenter-12.4-inbox.png
  18. BIN
      docs/user-guide/notifications/NotificationCenter-12.4-splitScreenView-structure.png
  19. 31
      docs/user-guide/notifications/README.md
  20. BIN
      docs/user-guide/notifications/openproject-notification-center-inbox.png
  21. 60896
      frontend/package-lock.json
  22. 18
      frontend/src/app/core/state/file-links/file-links.service.ts
  23. 1
      frontend/src/app/shared/components/sidemenu/sidemenu.component.sass
  24. 10
      frontend/src/app/shared/components/storages/file-picker-modal/file-picker-modal.component.ts
  25. 2
      frontend/src/app/spot/styles/sass/components/drop-modal.sass
  26. 1
      frontend/src/global_styles/content/_attributes_key_value.sass
  27. 4
      frontend/src/global_styles/content/_forms_mobile.sass
  28. 44
      lib/tasks/fix_missing_notification_settings.rake
  29. 3
      modules/storages/config/locales/js-en.yml
  30. 8
      modules/team_planner/config/locales/crowdin/js-tr.yml
  31. 18
      modules/team_planner/config/locales/crowdin/tr.yml
  32. 3
      spec/contracts/users/create_contract_spec.rb
  33. 142
      spec/features/activities/activity_page_navigation_spec.rb
  34. 2
      spec/models/queries/members/filters/group_filter_spec.rb
  35. 53
      spec/models/queries/members/members_query_integration_spec.rb

@ -39,6 +39,10 @@ gem 'responders', '~> 3.0'
gem 'ffi', '~> 1.15'
# Lock mail at 2.7 due to incompatibility
# TODO: Remove it once the new version is fixed
gem 'mail', '~> 2.7.1'
gem 'rdoc', '>= 2.4.2'
gem 'doorkeeper', '~> 5.5.0'
@ -195,7 +199,7 @@ gem 'rest-client', '~> 2.0'
gem 'ruby-progressbar', '~> 1.11.0', require: false
gem 'mini_magick', '~> 4.11.0', require: false
gem 'mini_magick', '~> 4.12.0', require: false
gem 'validate_url'

@ -291,13 +291,13 @@ GEM
awesome_nested_set (3.5.0)
activerecord (>= 4.0.0, < 7.1)
aws-eventstream (1.2.0)
aws-partitions (1.671.0)
aws-sdk-core (3.168.3)
aws-partitions (1.674.0)
aws-sdk-core (3.168.4)
aws-eventstream (~> 1, >= 1.0.2)
aws-partitions (~> 1, >= 1.651.0)
aws-sigv4 (~> 1.5)
jmespath (~> 1, >= 1.6.1)
aws-sdk-kms (1.60.0)
aws-sdk-kms (1.61.0)
aws-sdk-core (~> 3, >= 3.165.0)
aws-sigv4 (~> 1.1)
aws-sdk-s3 (1.117.2)
@ -612,11 +612,8 @@ GEM
loofah (2.19.0)
crass (~> 1.0.2)
nokogiri (>= 1.5.9)
mail (2.8.0)
mail (2.7.1)
mini_mime (>= 0.1.1)
net-imap
net-pop
net-smtp
marcel (1.0.2)
matrix (0.4.2)
messagebird-rest (1.4.2)
@ -626,7 +623,7 @@ GEM
mime-types (3.4.1)
mime-types-data (~> 3.2015)
mime-types-data (3.2022.0105)
mini_magick (4.11.0)
mini_magick (4.12.0)
mini_mime (1.1.2)
mini_portile2 (2.8.0)
minisyntax (0.2.5)
@ -644,7 +641,7 @@ GEM
net-ldap (0.17.1)
net-pop (0.1.2)
net-protocol
net-protocol (0.2.0)
net-protocol (0.2.1)
timeout
net-smtp (0.3.3)
net-protocol
@ -798,7 +795,7 @@ GEM
ffi (~> 1.0)
rbtree3 (0.7.0)
rchardet (1.8.0)
rdoc (6.4.0)
rdoc (6.5.0)
psych (>= 4.0.0)
recaptcha (5.12.3)
json
@ -850,7 +847,7 @@ GEM
rspec-retry (0.6.2)
rspec-core (> 3.3)
rspec-support (3.12.0)
rubocop (1.39.0)
rubocop (1.40.0)
json (~> 2.3)
parallel (~> 1.10)
parser (>= 3.1.2.1)
@ -1066,9 +1063,10 @@ DEPENDENCIES
listen (~> 3.7.0)
livingstyleguide (~> 2.1.0)
lograge (~> 0.12.0)
mail (~> 2.7.1)
matrix (~> 0.4.2)
meta-tags (~> 2.18.0)
mini_magick (~> 4.11.0)
mini_magick (~> 4.12.0)
multi_json (~> 1.15.0)
my_page!
net-ldap (~> 0.17.0)

@ -41,6 +41,7 @@ module Users
validate :authentication_defined
validate :type_is_user
validate :user_limit_not_exceeded
validate :notification_settings_present
private
@ -50,6 +51,12 @@ module Users
end
end
def notification_settings_present
if model.notification_settings.empty?
errors.add :notification_settings, :blank
end
end
def authentication_defined
errors.add :password, :blank if model.active? && no_auth?
end

@ -34,7 +34,7 @@ class Queries::Members::Filters::GroupFilter < Queries::Members::Filters::Member
end
def scope
scope = model.joins(:principal).merge(User.joins(:groups))
scope = model.joins(:principal)
scope.where(where)
end
end

@ -68,13 +68,13 @@ See COPYRIGHT and LICENSE files for more details.
<div style="float:left;">
<%= link_to_content_update(t(:label_previous),
{ from: (@date_to - @days - 1) },
{ from: (@date_to - @days - 1), with_subprojects: @with_subprojects ? '1' : '0' },
{title: t(:label_date_from_to, start: format_date(@date_to - 2*@days), end: format_date(@date_to - @days - 1)),
class: 'navigate-left'}) %>
</div>
<div style="float:right;">
<%= link_to_content_update(t(:label_next),
{ from: (@date_to + @days - 1) },
{ from: (@date_to + @days - 1), with_subprojects: @with_subprojects ? '1' : '0' },
{title: t(:label_date_from_to, start: format_date(@date_to), end: format_date(@date_to + @days - 1)),
class: 'navigate-right'}) unless @date_to >= Date.today %>
</div>
@ -104,8 +104,8 @@ See COPYRIGHT and LICENSE files for more details.
<%= hidden_field_tag 'with_subprojects', 0 %>
<p><label><%= check_box_tag 'with_subprojects', 1, @with_subprojects %> <%=t(:label_subproject_plural)%></label></p>
<% end %>
<%= hidden_field_tag('user_id', params[:user_id]) unless params[:user_id].blank? %>
<%= hidden_field_tag('apply', true) %>
<%= hidden_field_tag('user_id', params[:user_id]) if params[:user_id].present? %>
<%= hidden_field_tag('from', params[:from]) if params[:from].present? %>
<p><%= submit_tag t(:button_apply), class: 'button -small -highlight', name: nil %></p>
</fieldset>
<% end %>

@ -674,7 +674,7 @@ tr:
enable: 'Günlük email hatırlatıcılarını etkinleştir'
explanation: 'You will receive these reminders only for unread notifications and only at hours you specify. %{no_time_zone}'
no_time_zone: 'Until you configure a time zone for your account, the times will be interpreted to be in UTC.'
time_label: 'Time %{counter}:'
time_label: 'Zaman %{counter}:'
title: 'Okunmamış bildirimler için bana günlük e-posta hatırlatıcıları gönder'
workdays:
title: 'Bu günlerde e-posta hatırlatıcıları alın'
@ -891,7 +891,7 @@ tr:
click_on_show_relations_to_open_gantt: 'Click on "%{button_name}" for GANTT overview.'
show_relations: 'İlişkileri göster'
ignore_non_working_days:
title: 'Working days only'
title: 'Sadece iş günleri'
description_filter: "Filtre"
description_enter_text: "Metin girin"
description_options_hide: "Seçenekleri gizle"
@ -1086,7 +1086,7 @@ tr:
button_save: "Kaydet"
button_submit: "Gönder"
button_cancel: "İptal etmek"
button_delete: "Delete"
button_delete: "Sil"
form_submit:
title: 'Devam etmek için onaylayın'
text: 'Bu işlemi gerçekleştirmek istediğinizden emin misiniz?'
@ -1143,7 +1143,7 @@ tr:
zero: "0 s"
day:
one: "1 gün"
other: "%{count} days"
other: "%{count} gün"
zero: "0 gün"
zen_mode:
button_activate: 'Zen modunu etkinleştir'
@ -1217,7 +1217,7 @@ tr:
message:
label: 'Davet Mesajı'
description: 'We will send an email to the user, to which you can add a personal message here. An explanation for the invitation could be useful, or prehaps a bit of information regarding the project to help them get started.'
next_button: 'Next'
next_button: 'Sonraki'
summary:
next_button: 'Davet gönder'
success:
@ -1235,7 +1235,7 @@ tr:
selected_filter:
all: 'Tüm projeler'
selected: 'Sadece seçilen'
search_placeholder: 'Search project...'
search_placeholder: 'Proje ara...'
include_subprojects: 'Include all sub-projects'
tooltip:
include_all_selected: 'Project already included since Include all sub-projects is enabled.'

@ -219,7 +219,7 @@ tr:
copy:
#Contains custom strings for options when copying a project that cannot be found elsewhere.
members: 'Proje üyeleri'
overviews: 'Project overview'
overviews: 'Projeye Genel Bakış'
queries: 'Work packages: saved views'
wiki_page_attachments: 'Wiki pages: attachments'
work_package_attachments: 'Work packages: attachments'
@ -772,7 +772,7 @@ tr:
attributes:
user_id:
not_allowed_to_view: "is not allowed to view this resource."
locked: "is locked."
locked: "kilitli."
wiki_page:
attributes:
slug:
@ -1596,7 +1596,7 @@ tr:
label_enumerations: "Sayım Listesi"
label_enterprise: "Kurumsal"
label_enterprise_active_users: "%{current}/%{limit} aktif kullanıcı rezervasyonu"
label_enterprise_edition: "Enterprise edition"
label_enterprise_edition: "Enterprise sürüm"
label_environment: "Ortam"
label_estimates_and_time: "Tahminler & zaman"
label_equals: "şuysa"
@ -1899,7 +1899,7 @@ tr:
label_used_by_types: "Türleri tarafından kullanılan"
label_used_in_projects: "Projede kullanılan"
label_user: "Kullanıcı"
label_user_and_permission: "Users and permissions"
label_user_and_permission: "Kullanıcılar ve İzinler"
label_user_named: "%{name} kullanıcısı"
label_user_activity: "%{value}'ın faaliyet"
label_user_anonymous: "Anonim"
@ -2032,7 +2032,7 @@ tr:
one: 'There is 1 more work package with notifications.'
other: 'There are %{count} more work packages with notifications.'
reason:
watched: 'Watched'
watched: 'İzlendi'
assigned: 'Assigned'
responsible: 'Sorumlu'
mentioned: 'Mentioned'

@ -13,7 +13,7 @@ keywords: help, documentation
Get started with installing and upgrading OpenProject using [our Installation Guide starting point](./installation-and-operations/).
The guides for [manual](./installation-and-operations/installation/manual), [packaged](./installation-and-operations/installation/packaged) and [Docker-based](./installation-and-operations/installation/docker) installations are provided.
The guides [packaged](./installation-and-operations/installation/packaged) and [Docker-based](./installation-and-operations/installation/docker) installations are provided.
## Upgrading

@ -41,5 +41,5 @@ Compare the features of these versions [on the website](https://www.openproject.
For production environments and when using a [supported distribution](system-requirements), we recommend using the [packaged installation](installation/packaged/). This will install OpenProject as a system dependency using your distribution's package manager, and provide updates in the same fashion that all other system packages do.
A [manual installation](installation/manual) option is also documented, but due to the large number of components involved and the rapid evolution of OpenProject, we cannot ensure that the procedure is either up-to-date or that it will correctly work on your machine. This means that manual installation is NOT recommended.
An OUTDATED and OLD [manual installation](installation/manual) option exists, but due to the large number of components involved and the rapid evolution of OpenProject, we cannot ensure that the procedure is either up-to-date or that it will correctly work on your machine. This means that manual installation is NOT recommended NOR supported.

@ -22,7 +22,7 @@ If you use the docker images, you need to be familiar with Docker and Docker vol
### My favorite Linux distribution is not listed. What can I do?
You can either try the manual installation, or ask in the forum whether this could be added to the list of supported distributions. We try to support recent major distributions, but due to maintenance and operations cost cannot freely add to that list.
You can either try the OUTDATED and OLD manual installation guide, or add a Feature request whether your operating system could be added to the list of supported distributions. We try to support recent major distributions, but due to maintenance and operations cost cannot freely add to that list.
### What is the better option to run OpenProject in production environments: Docker or Linux packages?

@ -8,18 +8,16 @@ sidebar_navigation:
OpenProject can be setup in three different ways:
| Topic | Content |
|------------------------------------------------------------------|----------------------------------------------------------------------------------------------|
| [Installation with DEB/RPM packages](./packaged) | This is the recommended way to install OpenProject |
| [Installation with docker](./docker) | This allows to setup OpenProject in an isolated manner using Docker |
| [Installation with Univention Corporate Server](./univention) | OpenProject is available in the App Center and comes integrated with the identity management |
| [Other](misc/) | Extra information on installing OpenProject on specific platforms such as Kubernetes. |
| Topic | Content |
| ------------------------------------------------------------ | ------------------------------------------------------------ |
| [Installation with DEB/RPM packages](./packaged) | This is the recommended way to install OpenProject |
| [Installation with Docker](./docker) | This allows to setup OpenProject in an isolated manner using Docker |
| [Installation with Univention Corporate Server](./univention) | OpenProject is available in the App Center and comes integrated with the identity management |
| [Other](misc/) | Extra information on installing OpenProject on specific platforms such as Kubernetes. |
**We recommend downloading the DEB/RPM package installation.**
> **NOTE: We recommend using the DEB/RPM package installation.**
## Frequently asked questions (FAQ)
### Do you have a step-by-step guide to installing OpenProject Enterprise on-premises under Active Directory?
We have a guide on [how to use OpenProject with your Active Directory](../../system-admin-guide/authentication/ldap-authentication/).
In addition, with the Enterprise on-premises edition it is also possible to [link LDAP groups with groups in OpenProject](../../system-admin-guide/authentication/ldap-authentication/ldap-group-synchronization/).

@ -4,22 +4,24 @@ sidebar_navigation: false
# Manual installation guide
**IMPORTANT: We strongly recommend to use one of the officially supported [installation methods](../../installation). This guide is simply provided as a reference, and is most likely NOT up to date with relation to the latest OpenProject releases.**
> **IMPORTANT: We strongly recommend to use one of the officially supported [installation methods](../../installation).**
>
> **This guide is simply provided as an OLD and OUTDATED reference, and is NOT up to date with relation to the latest OpenProject releases and will be NOT maintained NOR supported. You are on your own and maybe could ask experienced users in the forum in order to use this guide for any integrations taht you would like to solve. We also removed it from the navigation sidebar on the left in order to hide it.**
Please be aware that:
* This guide requires that you have a clean Ubuntu 18.04 **x64** installation
* This guide **requires** that you have a clean **Ubuntu 18.04** **x64** installation
with administrative rights (i.e. you must be able to `sudo`). We have tested
the installation guide on an Ubuntu Server image, but it should work on any
derivative. You may need to alter some of the commands to match your
derivative.
* OpenProject will be installed with a PostgreSQL database.
* OpenProject will be installed with a **PostgreSQL** database.
* OpenProject will be served in a production environment with the Apache server
* OpenProject will be served in a production environment with the **Apache** server
(this guide should work similarly with other servers, like nginx and others)
Note: We have highlighted commands to execute like this
> **NOTE:** We have highlighted commands to execute like this
```bash
[user@host] command to execute
@ -147,7 +149,7 @@ v16.17.0
## Installation of OpenProject
We will install the OpenProject Community edition. It contains the recommended set of plugins for use
We will install the OpenProject Community Edition. It contains the recommended set of plugins for use
with OpenProject. For more information, see [github.com/opf/openproject](https://github.com/opf/openproject).
@ -213,11 +215,8 @@ a better performance of OpenProject:
rails_cache_store: :memcache
```
__NOTE:__ You should validate your `yml` files, for example with
[yamlchecker.com](https://yamlchecker.com/). Both, the `database.yml` and `configuration.yml`
file are sensitive to whitespace. It is pretty easy to write
invalid `yml` files without seeing the error. Validating those files
prevents you from such errors.
> __NOTE:__ You should validate your `yml` files, for example with [yamlchecker.com](https://yamlchecker.com/). Both, the `database.yml` and `configuration.yml` file are sensitive to whitespace. It is pretty easy to write invalid `yml` files without seeing the error. Validating those files prevents you from such errors.
>
To configure the environment variables such as the number of web server threads `OPENPROJECT_WEB_WORKERS`, copy the `.env.example` to `.env` and add the environment variables you want to configure. The variables will be automatically loaded to the application's environment.
@ -231,7 +230,8 @@ To configure the environment variables such as the number of web server threads
[openproject@host] RAILS_ENV="production" ./bin/rake assets:precompile
```
**NOTE:** When not specified differently, the default data loaded via db:seed will have an english localization. You can choose to seed in a different language by specifying the language via the `LOCALE` environment variable on the call to `db:seed`. E.g.
> **NOTE:** When not specified differently, the default data loaded via db:seed will have an english localization. You can choose to seed in a different language by specifying the language via the `LOCALE` environment variable on the call to `db:seed`. E.g.
```bash
[openproject@all] RAILS_ENV="production" OPENPROJECT_SEED_LOCALE=fr ./bin/rake db:seed
```

@ -75,7 +75,7 @@ In OpenProject 12.2, you are now able to mark work packages with notifications a
In 12.2, the way settings are being handled for controlling HTTPs mode of OpenProject have changed.
In case of a packaged installation, the configuration from the packager wizard will result in the correct configuration.
For docker and manual installations, you will need to set the environment variable `OPENPROJECT_HTTPS=false` if you actively want to disable HTTPS mode.
For docker you will need to set the environment variable `OPENPROJECT_HTTPS=false` if you actively want to disable HTTPS mode.
For more information, please see the respective installation pages:

@ -42,7 +42,7 @@ For cloud customers of OpenProject: The records affected by this bug were restor
## Changes to the HTTPS settings
If you are running OpenProject in a docker-based or manual installation, or if you manually integrate the packaged installation into your existing web server, you might need to set a new configuration value if you're not running under HTTPS.
If you are running OpenProject in a docker-based or if you manually integrate the packaged installation into your existing web server, you might need to set a new configuration value if you're not running under HTTPS.
For these installations, you will need to set the environment variable `OPENPROJECT_HTTPS=false` if you actively want to disable HTTPS mode.

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

@ -61,71 +61,7 @@ The following video gives you a short overview of how to use this integration:
![OpenProject Nextcloud integration video](https://openproject-docs.s3.eu-central-1.amazonaws.com/videos/OpenProject-Nextcloud-Integration-2.mp4)
### In OpenProject
In addition to listing files attached to a work package, the **Files** tab now also shows you Nextcloud files that are linked to the current work package. Hovering on any linked file with your mouse will give you options to **open or download the file, show the containing folder in Nextcloud or remove the link**.
![Empty_status_files](1_0_00-No_files_linked.png)
![OP_linked_files](1_1_00-All_files_available.png)
To link a Nextcloud file to the current work package, you can either:
- select a file from your computer, which will be uploaded to Nextcloud and linked to this work package
- select an existing file in Nextcloud to link to
#### Upload and link file(s)
If the file you want to link has not yet been uploaded to Nextcloud, you can do so by clicking on the **Upload files** link.
>> IMG: Focus on Upload file link
You will then be prompted to select a file (or multiple files) on your computer that you want to upload to Nextcloud.
>> IMG: Local browser file picker
Alternatively, you can also simply drag a file or folder on your computer to this area (under the name of your Nextcloud file storage) and drop it in the drop zone that appears.
Once you have selected or dropped the files you would like to upload, you will need to select a folder on Nextcloud to which they should be stored.
You can click on folders you see to navigate to them. A helpful breadcrumb shows you where you are in the folder hierarchy.
To navigate one level up or to go back to the root, simply click on the relevant parent in the breadcrumb.
> **Info**: If you have navigated particularly deep (over 4 levels), intermediate levels might be collapsed to save space, but you'll always be able to navigate back to the immediate parent or the root to go backwards.
To save the files you uploaded to the currently open folder, click on the **Choose location** button.
#### Link existing files
If the file you want to link already exists on Nextcloud, you simply have to create the link.
To do so, start by clicking on **Link existing file**.
A file picker will appear, displaying all the files and folders on your Nextcloud instance that you have permission to see.
>> IMG: Nextcloud file picker
To link a certain file or folder with this work package, click on the checkbox to the left of each item.
>> IMG: Certain files and folder checked
If the file you're looking for is inside a folder or multiple levels of folders, you can click on each one to navigate to it. A helpful breadcrumb shows you where you are in the folder hierarchy.
To navigate one level up or to go back to the root, simply click on the relevant parent in the breadcrumb.
> **Info**: If you have navigated particularly deep (over 4 levels), intermediate levels might be collapsed to save space, but you'll always be able to navigate back to the immediate parent or the root to go backwards.
Once you have selected the file(s) or folder(s) you wish to link to the work package, click on the **Link # files** button. The number on the button will represent the number of files/folders you have selected.
>> IMG: Focus on the "Link # files button"
> **Info**: To avoid the button being too long, it will say "Link 3 files" even if you have selected 2 files and 1 folder.
### In Nextcloud
On the file or folder that you want to link to a work package, click on the *three dots → **Details**.*
Liking files to OpenProject work packages is currently only available via Nextcloud. First, in Nextcloud, navigate to the file or folder that you want to link to a work package and click on the *three dots → **Details**.*
![NC_open_file_details](Nextcloud_open_file_details.png)
@ -169,7 +105,7 @@ There are three additional features related to the integration that you can enab
If you wish to unlink any linked file or folder, hover to it in the list of linked Files and click on the **Unlink** icon next to the _Delete_ icon.
>> IMG: Hover on unlink icon.
![A screenshot of the unlink icon when hovering on a linked file](NC_removeFileLinkButton.png)
You will be asked to confirm that you want to unlink. Click on **Remove link** to do so.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 KiB

After

Width:  |  Height:  |  Size: 152 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 141 KiB

After

Width:  |  Height:  |  Size: 406 KiB

@ -27,49 +27,38 @@ With in-app notifications, you will be notified about important changes that are
When there are notifications that require your attention, you will see a red badge on the notification bell icon on the right edge of the top header. The number on the badge indicates the number of total unread notifications (up to 99, after which the badge will simply indicate "99+").
To view the notifications, click on this bell icon.
To view the notifications, click the bell icon. This will take you to **Notification center**.
![A notification bell icon in the top bar has a badge showing the number of unread notifications](NotificationCenter-12.4-badge.png)
This will take you to **Notification center**.
![A screenshot of the Notification center with a number of unread notifications](NotificationCenter-12.4-inbox.png)
![A screenshot of the Notification center with a number of unread notifications](openproject-notification-center-inbox.png)
Each row in Notification center is a work package that has generated a notification. It is possible that you have received multiple notifications for the same work package (if, for example, the date of a work package you are watching was changed by one person and then the status later change by another, that would generate two notifications). A blue badge on the right edge of each row displays the number of unread notifications concerning that particular work package.
The work packages are listed in order of freshness. The work packages on top of the list have the "newest" notifications. This means if there is a new update to a work package that was further down in your notification list, it will be moved to the top since that is now the newest notification.
You can **click on a notification row** to view the Activity tab of that work package in split screen:
![Clicking on a notification row allows you to access the work package in split screen mode](NotificationCenter-12.4-splitScreenView.png)
## Manage notifications
The activity tab will auto-scroll to the last event that generated a notification.
Clicking on a notification with display the activity tab of the relevant work package in split screen. The activity tab will auto-scroll to the last event that generated a notification.
> **Info:** Not all work package activity generate notifications. For example, if you received a notification because you were mentioned, there might be other activities on that work package after that, even though the *Activity* tab will auto-scroll to highlight the mention when you click on the notification, since the mention was originally what triggered the notification.
## Manage notifications
This section explains the various ways that Notification center lets you manage your notifications.
![The different sections of Notification center highlighted with numbers 1 through 5](NotificationCenter-12.4-splitScreenView-structure.png)
You can filter or group notifications by using the two sets of predefined filters on the left-hand menu:
1. You can filter by the **reason** (area 1) you were notified: because you were mentioned (*@mention*), because you are either the assignee or accountable for that work package, because it concerns a work package you are watching or because you have an active date alert.
2. You can filter by **project** (area 2), for example to filter for notifications that originated from a specific project.
(Area 1) You can filter by the **reason** you were notified: because you were mentioned (*@mention*), because you are either the assignee or accountable for that work package, because it concerns a work package you are watching or because you have an active date alert.
(Area 2) You can filter by **project** (area 2), for example to filter for notifications that originated from a specific project.
You can also affect which notifications are visible on the screen (area 3):
(Area 3) You can also affect which notifications are visible on the screen:
- You can also choose to view either only **Unread** notification or **All**, which will also display notifications previously marked as read.
- You can also **Mark all as read** if you want to clean your notification inbox in one click.
> **Info:** The **Mark all as read** button clears all _visible_ notification rows. If you have a very large number unread notifications, the oldest ones might not be visible on the page. In this case, you might have to click the button multiple times to clear your inbox completely.
If you would like to view your current notification preferences or modify them, click on the [**Notification settings**](./notification-settings) button (area 4). You can also access your settings via your Avatar in the top right corner > *My account* > *Notification settings*.
(Area 4) If you would like to view your current notification preferences or modify them, click on the [**Notification settings**](./notification-settings) button. You can also access your settings via your Avatar in the top right corner > *My account* > *Notification settings*.
The split screen view (area 5) lets you not only view work package activity as previously described, but also lets you access all other work package tabs, including overview, files, relations and watchers.
(Area 5) The split screen view lets you not only view work package activity as previously described, but also lets you access all other work package tabs, including overview, files, relations and watchers.
In addition to the in-app notifications, you will also get a once-a-day summary of all notifications by email. To learn more about Email reminders, [click here](../../getting-started/my-account/#email-reminders).

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 KiB

File diff suppressed because it is too large Load Diff

@ -29,7 +29,7 @@
import { applyTransaction } from '@datorama/akita';
import { Injectable } from '@angular/core';
import { HttpHeaders } from '@angular/common/http';
import { from } from 'rxjs';
import { from, Observable } from 'rxjs';
import {
groupBy,
mergeMap,
@ -100,7 +100,12 @@ export class FileLinksResourceService extends ResourceCollectionService<IFileLin
);
}
addFileLinks(collectionKey:string, addFileLinksHref:string, storage:IHalResourceLink, filesToLink:IStorageFile[]):void {
addFileLinks(
collectionKey:string,
addFileLinksHref:string,
storage:IHalResourceLink,
filesToLink:IStorageFile[],
):Observable<IHALCollection<IFileLink>> {
const elements = filesToLink.map((file) => ({
originData: {
id: file.id,
@ -115,10 +120,10 @@ export class FileLinksResourceService extends ResourceCollectionService<IFileLin
_links: { storage },
}));
this.http
return this.http
.post<IHALCollection<IFileLink>>(addFileLinksHref, { _type: 'Collection', _embedded: { elements } })
.subscribe(
(collection) => {
.pipe(
tap((collection) => {
applyTransaction(() => {
const newFileLinks = collection._embedded.elements;
this.store.add(newFileLinks);
@ -136,8 +141,7 @@ export class FileLinksResourceService extends ResourceCollectionService<IFileLin
),
);
});
},
this.toastAndThrow.bind(this),
}),
);
}

@ -52,6 +52,7 @@
white-space: nowrap
line-height: 30px
text-decoration: none
width: 100%
&--item-icon
font-size: 24px

@ -38,8 +38,9 @@ import { take } from 'rxjs/operators';
import { I18nService } from 'core-app/core/i18n/i18n.service';
import { TimezoneService } from 'core-app/core/datetime/timezone.service';
import { IFileLink } from 'core-app/core/state/file-links/file-link.model';
import { IStorageFile } from 'core-app/core/state/storage-files/storage-file.model';
import { ToastService } from 'core-app/shared/components/toaster/toast.service';
import { OpModalLocalsMap } from 'core-app/shared/components/modal/modal.types';
import { IStorageFile } from 'core-app/core/state/storage-files/storage-file.model';
import { OpModalLocalsToken } from 'core-app/shared/components/modal/modal.service';
import { SortFilesPipe } from 'core-app/shared/components/storages/pipes/sort-files.pipe';
import { StorageFilesResourceService } from 'core-app/core/state/storage-files/storage-files.service';
@ -69,6 +70,9 @@ export class FilePickerModalComponent extends FilePickerBaseModalComponent {
alreadyLinkedFile: this.i18n.t('js.storages.file_links.already_linked_file'),
alreadyLinkedDirectory: this.i18n.t('js.storages.file_links.already_linked_directory'),
},
toast: {
successFileLinksCreated: (count:number):string => this.i18n.t('js.storages.file_links.success_create', { count }),
},
};
public get selectedFileCount():number {
@ -86,6 +90,7 @@ export class FilePickerModalComponent extends FilePickerBaseModalComponent {
protected readonly sortFilesPipe:SortFilesPipe,
protected readonly storageFilesResourceService:StorageFilesResourceService,
private readonly i18n:I18nService,
private readonly toastService:ToastService,
private readonly timezoneService:TimezoneService,
private readonly fileLinksResourceService:FileLinksResourceService,
) {
@ -105,6 +110,9 @@ export class FilePickerModalComponent extends FilePickerBaseModalComponent {
this.locals.addFileLinksHref as string,
this.storageLink,
files,
).subscribe(
(fileLinks) => { this.toastService.addSuccess(this.text.toast.successFileLinksCreated(fileLinks.count)); },
(error) => { this.toastService.addError(error); },
);
this.service.close();

@ -15,7 +15,7 @@
left: $spot-spacing-1
right: $spot-spacing-1
width: calc(100vw - (2 * #{$spot-spacing-1}))
max-height: calc(#{var(--app-height)} - (#{$spot-spacing-3_5} + #{$spot-spacing-1}))
height: calc(#{var(--app-height)} - (#{$spot-spacing-3_5} + #{$spot-spacing-1}))
box-shadow: $spot-shadow-light-mid
background: $spot-color-basic-white
border-radius: $border-radius

@ -44,6 +44,7 @@
@include text-shortener
flex: 0 1 auto
padding-right: $spot-spacing-0_5
width: 100% // prevent text-overflow from capping too early on Safari
.attributes-key-value--value-container
display: flex

@ -62,8 +62,8 @@
.form--field-inline-button
width: auto !important
.-browser-safari
// Special rule for mobile safari to prevent zooming into the text field
.-browser-safari, .-browser-chrome
// Special rule for mobile safari and chrome to prevent zooming into the text field
// when focused.
select,
textarea,

@ -0,0 +1,44 @@
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2022 the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++
namespace :migrations do
desc "Fix the missing notification settings"
task fix_missing_notification_settings: :environment do
ActiveRecord::Base.connection.execute <<~SQL.squish
INSERT INTO
notification_settings
(user_id)
SELECT
u.id
FROM
users u
WHERE type = 'User'
AND NOT EXISTS (SELECT * FROM notification_settings ns WHERE ns.user_id = u.id)
SQL
end
end

@ -42,6 +42,9 @@ en:
zero: "Select files to link"
one: "Link 1 file"
other: "Link %{count} files"
success_create:
one: "Successfully created 1 file link."
other: "Successfully created %{count} file links."
not_allowed_tooltip: "Please log in to Nextcloud to access this file"
already_linked_file: "This file is already linked to this work package."
already_linked_directory: "This directory is already linked to this work package."

@ -7,14 +7,14 @@ tr:
create_label: 'Takım planlayıcısı'
create_title: 'Yeni takım planlayıcısı oluştur'
unsaved_title: 'İsimsiz takım planlayıcısı'
no_data: 'Add assignees to set up your team planner.'
add_assignee: 'Add assignee'
remove_assignee: 'Remove assignee'
no_data: 'Ekip planlayıcınızı ayarlamak için atanan kişileri ekleyin.'
add_assignee: 'Atanan ekle'
remove_assignee: 'Atananı kaldır'
two_weeks: '2 hafta'
one_week: '1 hafta'
work_week: 'Çalışma Haftası'
today: 'Bugün'
drag_here_to_remove: 'Drag here to remove assignee and start and end dates.'
drag_here_to_remove: 'Atanan kişiyi ve başlangıç ve bitiş tarihlerini kaldırmak için buraya sürükleyin.'
cannot_drag_here: 'İzinler veya düzenleme kısıtlamaları nedeniyle iş paketi kaldırılamıyor.'
cannot_drag_to_non_working_day: 'Bu iş paketi, çalışma dışı bir günde başlayamaz/bitemez.'
quick_add:

@ -1,13 +1,13 @@
#English strings go here
tr:
permission_view_team_planner: "View team planner"
permission_manage_team_planner: "Manage team planner"
project_module_team_planner_view: "Team planner"
permission_view_team_planner: "Takım planlayıcıyı görüntüle"
permission_manage_team_planner: "Takım planlayıcıyı yönet"
project_module_team_planner_view: "Takım planlayıcısı"
team_planner:
label_team_planner: "Team planner"
label_create_new_team_planner: "Create new team planner"
label_team_planner_plural: "Team planners"
label_assignees: "Devralanlar"
label_team_planner: "Takım planlayıcısı"
label_create_new_team_planner: "Yeni takım planlayıcısı oluştur"
label_team_planner_plural: "Takım planlayıcıları"
label_assignees: "Atananlar"
upsale:
title: "Team planner"
description: "Get a complete overview of your team’s planning with Team Planner. Stretch, shorten and drag-and-drop work packages to modify dates, move them or change assignees."
title: "Takım planlayıcısı"
description: "Team Planner ile ekibinizin planlamasına ilişkin eksiksiz bir genel bakış elde edin. Tarihleri değiştirmek, taşımak veya atananları değiştirmek için iş paketlerini genişletin, kısaltın ve sürükleyip bırakın."

@ -43,7 +43,8 @@ describe Users::CreateContract do
login: user_login,
mail: user_mail,
password: user_password,
password_confirmation: user_password_confirmation
password_confirmation: user_password_confirmation,
notification_settings: [NotificationSetting.new]
}
end

@ -0,0 +1,142 @@
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2022 the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++
require 'spec_helper'
describe 'Activity page navigation' do
include ActiveSupport::Testing::TimeHelpers
shared_let(:project) { create(:project, enabled_module_names: Setting.default_projects_modules + ['activity']) }
shared_let(:subproject) do
create(:project, parent: project, enabled_module_names: Setting.default_projects_modules + ['activity'])
end
shared_let(:user) do
create(:user,
member_in_projects: [project, subproject],
member_with_permissions: %w[view_work_packages])
end
shared_let(:project_work_package) { create(:work_package, project:, subject: 'Work package for parent project') }
shared_let(:subproject_work_package) { create(:work_package, project: subproject, subject: 'Work package for subproject') }
shared_let(:project_older_work_package) do
travel_to 45.days.ago
create(:work_package, project:, subject: 'Work package older for parent project')
ensure
travel_back
end
shared_let(:subproject_older_work_package) do
travel_to 45.days.ago
create(:work_package, project: subproject, subject: 'Work package older for subproject')
ensure
travel_back
end
current_user { user }
it 'stays on the same period when changing filters' do
visit project_activity_index_path(project)
click_link('Previous')
expect(page)
.to have_link(text: /#{subproject_older_work_package.subject}/)
uncheck 'Subprojects'
click_button 'Apply'
# Still on the same page. Filters applied. subproject work package created
# 45 days ago should not be visible anymore
expect(page)
.not_to have_link(text: /#{subproject_older_work_package.subject}/)
end
shared_examples 'subprojects checkbox state is preserved' do
it 'keeps Subprojects checked/unchecked when navigating between pages' do
visit project_activity_index_path(project)
aggregate_failures do
# Subprojects is initially checked or not depending on a setting
if Setting.display_subprojects_work_packages?
expect(page).to have_checked_field('Subprojects')
else
expect(page).to have_unchecked_field('Subprojects')
end
# work packages for both projects are visible
expect(page)
.to have_link(text: /#{project_work_package.subject}/)
expect(page)
.to have_link(text: /#{subproject_work_package.subject}/)
end
uncheck 'Subprojects'
click_button 'Apply'
aggregate_failures do
expect(page).to have_unchecked_field('Subprojects')
expect(page)
.to have_link(text: /#{project_work_package.subject}/)
# work packages for subproject is not visible anymore
expect(page)
.not_to have_link(text: /#{subproject_work_package.subject}/)
end
click_link('Previous')
aggregate_failures do
# Subprojects should still be unchecked, bug #45348
expect(page).to have_unchecked_field('Subprojects')
expect(page)
.to have_link(text: /#{project_older_work_package.subject}/)
# work packages for subproject still not visible
expect(page)
.not_to have_link(text: /#{subproject_older_work_package.subject}/)
end
click_link('Next')
aggregate_failures do
# Subprojects should still be unchecked, bug #45348
expect(page).to have_unchecked_field('Subprojects')
expect(page)
.to have_link(text: /#{project_work_package.subject}/)
# work packages for subproject still not visible
expect(page)
.not_to have_link(text: /#{subproject_work_package.subject}/)
end
end
end
context 'with subprojects included by default', with_setting: { display_subprojects_work_packages: true } do
include_examples 'subprojects checkbox state is preserved'
end
context 'with subprojects NOT included by default', with_setting: { display_subprojects_work_packages: false } do
include_examples 'subprojects checkbox state is preserved'
end
end

@ -54,7 +54,7 @@ describe Queries::Members::Filters::GroupFilter, type: :model do
end
it_behaves_like 'list_optional group query filter' do
let(:model) { Member.joins(:principal).merge(User.joins(:groups)) }
let(:model) { Member.joins(:principal) }
let(:valid_values) { [group1.id.to_s] }
end
end

@ -0,0 +1,53 @@
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2022 the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++
require 'spec_helper'
describe Queries::Members::MemberQuery, 'Integration' do
let(:instance) { described_class.new }
current_user { user }
subject { instance.results }
context 'with two groups in a project' do
let(:project) { create(:project) }
let(:user) { create(:user) }
let(:role) { create(:role, permissions: %i[view_members manage_members]) }
let!(:group1) { create(:group, name: 'A', member_in_project: project, member_through_role: role, members: [user]) }
let!(:group2) { create(:group, name: 'B', member_in_project: project, member_through_role: role, members: [user]) }
it 'only returns one user when filtering for one group (Regression #45331)' do
instance.where 'project_id', '=', [project.id.to_s]
instance.where 'group', '=', [group1.id.to_s]
expect(subject.count).to eq 1
expect(subject.first.user_id).to eq user.id
end
end
end
Loading…
Cancel
Save