Merge remote-tracking branch 'origin/dev' into reactivex_new_import_style

pull/6207/head
Oliver Günther 7 years ago
commit 716500f876
No known key found for this signature in database
GPG Key ID: 88872239EB414F99
  1. 26
      .codeclimate.yml
  2. 5
      Gemfile
  3. 4
      Gemfile.lock
  4. 1
      app/models/queries/work_packages.rb
  5. 75
      app/models/queries/work_packages/filter/filter_for_wp_mixing.rb
  6. 46
      app/models/queries/work_packages/filter/id_filter.rb
  7. 47
      app/models/queries/work_packages/filter/parent_filter.rb
  8. 1
      app/models/queries/work_packages/filter/type_filter.rb
  9. 6
      app/models/work_package.rb
  10. 10
      config/environments/production.rb
  11. 2
      config/locales/crowdin/hu.yml
  12. 12
      config/locales/crowdin/js-lt.yml
  13. 68
      config/locales/crowdin/lt.yml
  14. 2
      config/locales/crowdin/ru.yml
  15. 143
      config/puma.rb
  16. 4
      frontend/app/components/wp-fast-table/wp-table-filters.ts
  17. 59
      lib/api/v3/queries/schemas/by_work_package_filter_dependency_representer.rb
  18. 22
      lib/api/v3/queries/schemas/id_filter_dependency_representer.rb
  19. 39
      lib/api/v3/queries/schemas/parent_filter_dependency_representer.rb
  20. 2
      lib/open_project/configuration.rb
  21. 133
      spec/lib/api/v3/queries/schemas/parent_filter_dependency_representer_spec.rb
  22. 4
      spec/lib/open_project/configuration_spec.rb
  23. 16
      spec/models/queries/work_packages/filter/id_filter_spec.rb
  24. 259
      spec/models/queries/work_packages/filter/parent_filter_spec.rb
  25. 2
      spec/support/capybara.rb

@ -1,8 +1,30 @@
---
version: "2"
languages:
Ruby: true
JavaScript: true
engines:
checks:
file-lines:
enabled: false
method-count:
enabled: false
method-lines:
enabled: false
method-complexity:
enabled: true
config:
threshold: 10
complex-logic:
enabled: true
config:
threshold: 10
# Similar codes trips up at the long TS/angular injection
# constructors all the time, which are similar by nature.
similar-code:
enabled: false
identical-code:
enabled: true
plugins:
rubocop:
enabled: true
brakeman:
@ -35,6 +57,8 @@ exclude_paths:
- .bundle/**/*
- lib/plugins/rfpdf/**/*
- frontend/vendor/**/*
- "**/*.d.ts"
- "**/node_modules/"
- spec/**
- spec_legacy/**/*
- lib/redcloth3.rb

@ -153,9 +153,6 @@ gem 'cocaine', '~> 0.5.8'
# also, better than thin since we can control worker concurrency.
gem 'unicorn'
# Puma server for development and on paas.
gem 'puma', '~> 3.11.3'
gem 'nokogiri', '~> 1.8.2'
# carrierwave 0.11.3 should allow to use fog-aws without the rest of the
@ -237,6 +234,7 @@ group :development do
end
group :development, :test do
gem 'puma', '~> 3.11.3'
gem 'pry-rails', '~> 0.3.6'
gem 'pry-stack_explorer', '~> 0.4.9.2'
@ -267,6 +265,7 @@ group :opf_plugins do
end
group :docker, optional: true do
gem 'passenger', '~> 5.2'
# Used to easily precompile assets
gem 'sqlite3', require: false
gem 'rails_12factor', require: !!ENV['HEROKU']

@ -371,6 +371,9 @@ GEM
parallel
parser (2.4.0.0)
ast (~> 2.2)
passenger (5.2.1)
rack
rake (>= 0.8.1)
pdf-core (0.7.0)
pg (0.21.0)
plaintext (0.1.0)
@ -661,6 +664,7 @@ DEPENDENCIES
openproject-token (~> 1.0.1)
openproject-translations!
parallel_tests (~> 2.14.0)
passenger (~> 5.2)
pg (~> 0.21.0)
plaintext (= 0.1.0)
prawn (~> 2.2)

@ -57,6 +57,7 @@ module Queries::WorkPackages
register.filter Query, filters_module::UpdatedAtFilter
register.filter Query, filters_module::VersionFilter
register.filter Query, filters_module::WatcherFilter
register.filter Query, filters_module::ParentFilter
columns_module = Queries::WorkPackages::Columns

@ -0,0 +1,75 @@
#-- encoding: UTF-8
#-- copyright
# OpenProject is a project management system.
# Copyright (C) 2012-2018 the OpenProject Foundation (OPF)
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2017 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See docs/COPYRIGHT.rdoc for more details.
#++
module Queries::WorkPackages::Filter::FilterForWpMixin
def type
:list
end
def allowed_values
raise NotImplementedError, 'There would be too many candidates'
end
def value_objects
scope.find(values)
end
def allowed_objects
raise NotImplementedError, 'There would be too many candidates'
end
def available?
scope.exists?
end
def ar_object_filter?
true
end
def allowed_values_subset
scope.where(id: values).pluck(:id).map(&:to_s)
end
private
def scope
if context.project
WorkPackage
.visible
.for_projects(context.project.self_and_descendants)
else
WorkPackage.visible
end
end
def type_strategy
@type_strategy ||= Queries::Filters::Strategies::HugeList.new(self)
end
end

@ -28,48 +28,10 @@
# See docs/COPYRIGHT.rdoc for more details.
#++
class Queries::WorkPackages::Filter::IdFilter < Queries::WorkPackages::Filter::WorkPackageFilter
def type
:list
end
require_relative './filter_for_wp_mixing'
def allowed_values
raise NotImplementedError, 'There would be too many candidates'
end
class Queries::WorkPackages::Filter::IdFilter <
Queries::WorkPackages::Filter::WorkPackageFilter
def value_objects
raise NotImplementedError, 'There would be too many candidates'
end
def allowed_objects
raise NotImplementedError, 'There would be too many candidates'
end
def available?
scope.exists?
end
def ar_object_filter?
true
end
def allowed_values_subset
scope.where(id: values).pluck(:id).map(&:to_s)
end
private
def scope
if context.project
WorkPackage
.visible
.for_projects(context.project.self_and_descendants)
else
WorkPackage.visible
end
end
def type_strategy
@type_strategy ||= Queries::Filters::Strategies::HugeList.new(self)
end
include ::Queries::WorkPackages::Filter::FilterForWpMixin
end

@ -0,0 +1,47 @@
#-- encoding: UTF-8
#-- copyright
# OpenProject is a project management system.
# Copyright (C) 2012-2018 the OpenProject Foundation (OPF)
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2017 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See docs/COPYRIGHT.rdoc for more details.
#++
require_relative './filter_for_wp_mixing'
class Queries::WorkPackages::Filter::ParentFilter <
Queries::WorkPackages::Filter::WorkPackageFilter
include ::Queries::WorkPackages::Filter::FilterForWpMixin
def includes
:parent_relation
end
def where
operator_strategy.sql_for_field(values,
Relation.table_name,
'from_id')
end
end

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

@ -299,6 +299,12 @@ class WorkPackage < ActiveRecord::Base
project && type ? (project.all_work_package_custom_fields & type.custom_fields) : []
end
# aliasing subject to name
# using :alias is not possible as AR will add the subject method later
def name
subject
end
def status_id=(sid)
self.status = nil
write_attribute(:status_id, sid)

@ -52,15 +52,7 @@ OpenProject::Application.configure do
# config.action_dispatch.rack_cache = true
# Enable Rails's static asset server when requested
if OpenProject::Configuration.enable_internal_assets_server?
config.public_file_server.enabled = true
config.public_file_server.headers = {
'Access-Control-Allow-Origin' => '*',
'Access-Control-Allow-Methods' => 'GET, OPTIONS, HEAD',
'Cache-Control' => 'public, s-maxage=31536000, max-age=15552000',
'Expires' => "#{1.year.from_now.to_formatted_s(:rfc822)}"
}
end
config.public_file_server.enabled = false
# Compress JavaScripts and CSS.
config.assets.js_compressor = nil

@ -2225,7 +2225,7 @@ hu:
text_journal_aggregation_time_explanation: Fűzze össze a tartalmat az értesítésekben,
amennyiben az idő kisebb, mint a megadott érték. Ez ugyanúgy késleltetheti az
e-mail kiküldését.
text_journal_changed: "%{label} changed from %{old} </br><strong>to</strong> %{new}"
text_journal_changed: "%{label} megváltoztatva %{old} </br><strong></strong> %{new}"
text_journal_changed_no_detail: "%{label} frissítve"
text_journal_changed_with_diff: "%{label} megváltozott (%{link})"
text_journal_deleted: "%{label} törölve (%{old})"

@ -6,10 +6,10 @@ lt:
loading: Įkeliama ...
autocomplete_select:
placeholder:
multi: Add "%{name}"
single: Select "%{name}"
remove: Remove %{name}
active: Active %{label} %{name}
multi: Pridėti „%{name}“
single: Pasirinkti „%{name}“
remove: Pašalinti %{name}
active: Aktyvus %{label} %{name}
close_popup_title: Užverti iškylantį langą
close_filter_title: Užverti filtrą
close_form_title: Užverti formą
@ -71,8 +71,8 @@ lt:
one: Pirmasis rikiavimo kriterijus
two: Antrasis rikiavimo kriterijus
three: Trečiasis rikiavimo kriterijus
upsale_for_more: For more advanced filters, check out the
upsale_link: Enterprise Edition.
upsale_for_more: Norėdami naudoti daugiau papildomų filtrų, patikrinkite
upsale_link: "„Enterprise Edition“."
general_text_no: ne
general_text_yes: taip
general_text_No: Ne

@ -61,16 +61,16 @@ lt:
custom_actions:
actions:
name: Veiksmai
add: Add action
conditions: Conditions
plural: Custom actions
new: New custom action
edit: Edit custom action %{name}
execute: Execute %{name}
add: Pridėti veiksmą
conditions: Sąlygos
plural: Pasirinktiniai veiksmai
new: Naujas pasirinktinis veiksmas
edit: Redaguoti pasirinktinį veiksmą %{name}
execute: Vykdyti %{name}
upsale:
title: Custom actions is an Enterprise Edition feature
description: Custom actions streamline everyday work by combining a set of individual
steps into one button.
title: Pasirinktiniai veiksmai yra „Enterprise Edition“ funkcija
description: Pasirinktiniai veiksmai supaprastina kasdienį darbą suderindami
atskirus žingsnius į vieną mygtuką.
custom_fields:
text_add_new_custom_field: 'Norėdami pridėti naujus pritaikytus laukelius prie
projekto, pirmiausia reikia juos sukurti. Tik tada yra galimybė juos pridėti
@ -271,8 +271,8 @@ lt:
announcements:
show_until: Rodyti iki
attachment:
attachment_content: Attachment content
attachment_file_name: Attachment file name
attachment_content: Prisegto failo turinys
attachment_file_name: Prisegto failo vardas
downloads: Atsisiuntimai
file: Failas
filename: Failas
@ -453,12 +453,12 @@ lt:
custom_field:
at_least_one_custom_option: Turi būti prieinama bent viena savybė.
custom_actions:
only_one_allowed: "(%{name}) only one value is allowed."
empty: "(%{name}) value can't be empty."
inclusion: "(%{name}) value is not set to one of the allowed values."
not_an_integer: "(%{name}) is not an integer."
smaller_than_or_equal_to: "(%{name}) must be smaller than or equal to %{count}."
greater_than_or_equal_to: "(%{name}) must be greater than or equal to %{count}."
only_one_allowed: leidžiama (%{name}) tik viena reikšmė.
empty: "(%{name}) reikšmė negali būti tuščia."
inclusion: "(%{name}) nenustatyta kaip viena iš leidžiamų reikšmių."
not_an_integer: "(%{name}) nėra sveikasis skaičius."
smaller_than_or_equal_to: "(%{name}) turi būti mažesnis arba lygus %{count}."
greater_than_or_equal_to: "(%{name}) turi būti didesnis arba lygus %{count}."
enterprise_token:
unreadable: neįmanoma perskaityti. Ar tai tikrai yra paramos raktas?
parse_schema_filter_params_service:
@ -571,7 +571,7 @@ lt:
attribute_help_text: Atributo pagalbos tekstas
board: Forumas
comment: Komentaras
custom_action: Custom action
custom_action: Pasirinktinis veiksmas
custom_field: Kliento laukelis
group: Grupė
category: Kategorija
@ -1026,12 +1026,12 @@ lt:
pdf_with_descriptions: PDF su aprašymu
extraction:
available:
pdftotext: Pdftotext available (optional)
unrtf: Unrtf available (optional)
catdoc: Catdoc available (optional)
xls2csv: Xls2csv available (optional)
catppt: Catppt available (optional)
tesseract: Tesseract available (optional)
pdftotext: Pdf-į-tekstą pasiekiamas (pasirinktinai)
unrtf: Unrtf pasiekiamas (pasirinktinai)
catdoc: Catdoc pasiekiamas (pasirinktinai)
xls2csv: Xls2csv pasiekiamas (pasirinktinai)
catppt: Catppt pasiekiamas (pasirinktinai)
tesseract: Tesseract pasiekiamas (pasirinktinai)
general_csv_decimal_separator: "."
general_csv_encoding: UTF-8
general_csv_separator: ","
@ -2107,7 +2107,7 @@ lt:
setting_file_max_size_displayed: Maksimalus tekstinių failų dydis rodomas vienoje
eilutėje
setting_host_name: Šeimininko vardas
setting_invitation_expiration_days: Activation E-Mail expires after
setting_invitation_expiration_days: Aktyvavimo laiškas baigia galioti po
setting_work_package_done_ratio: Skaičiuoti darbų paketo atlikimo santykį su
setting_work_package_done_ratio_field: Naudoti darbų paketo laukelį
setting_work_package_done_ratio_status: Naudoti darbų paketo būseną
@ -2171,7 +2171,7 @@ lt:
setting_accessibility_mode_for_anonymous: Leisti lengvos prieigos režimą anoniminiams
vartotojams
setting_user_format: Vartotojo atvaizdavimo formatas
setting_user_default_timezone: Users default time zone
setting_user_default_timezone: Numatytoji vartotojo laiko juosta
setting_users_deletable_by_admins: Administratoriai gali ištrinti vartotojų paskyras
setting_users_deletable_by_self: Vartotojai gali ištrinti savo paskyras
setting_welcome_text: Pasisveikinimo bloko tekstas
@ -2243,7 +2243,7 @@ lt:
naudojant iOS.
'
text_database_allows_tsv: Database allows TSVector (optional)
text_database_allows_tsv: Duomenų bazė leidžia TSVector (pasirinktinai)
text_default_administrator_account_changed: Administratoriaus numatytoji paskyra
pakeista
text_default_encoding: 'Numatytasis: UTF-8'
@ -2281,7 +2281,7 @@ lt:
text_journal_aggregation_time_explanation: Kombinuoti žurnalus rodymui, ar jų amžius
skiriasi mažiau nei nustatyta trukmė. Tai taip pat vėlins įspėjimo el. laiškų
atsiuntimą tokia pat laiko trukme.
text_journal_changed: "%{label} changed from %{old} </br><strong>to</strong> %{new}"
text_journal_changed: "%{label} pakeista iš %{old} </br><strong>į</strong> %{new}"
text_journal_changed_no_detail: "%{label} atnaujintas"
text_journal_changed_with_diff: "%{label} pasikeitė (%{link})"
text_journal_deleted: "%{label} ištrintas (%{old})"
@ -2543,8 +2543,8 @@ lt:
years: Metai(-ų)
title_remove_and_delete_user: Pašalinti pakviestą vartotoją iš projekto ir ištrinti
jį/ją.
tooltip_user_default_timezone: 'The default time zone for new users. Can be changed
in a user''s settings.
tooltip_user_default_timezone: 'Numatytoji laiko juosta naujiems vartotojams. Gali
būti pakeista vartotojo nustatymuose.
'
tooltip_resend_invitation: 'Siunčia naują pakvietimo laišką su nauju atpažinimo
@ -2620,9 +2620,11 @@ lt:
warning: Įspėjimas
warning_attachments_not_saved: "%{count} failas (-ai, -ų) negali būti išsaugotas
(-i)."
warning_registration_token_expired: |
The activation email has expired. We sent you a new one to %{email}.
Please click the link inside of it to activate your account.
warning_registration_token_expired: 'Aktyvavimo el. laiško galiojimas pasibaigė.
Išsiuntėme jums naują %{email}. Paspauskite laiške duotą nuorodą, kad aktyvuotumėte
savo paskyrą.
'
menu_item: Meniu punktas
menu_item_setting: Matomumas
wiki_menu_item_for: Meniu punktas wiki puslapiui „%{title}“

@ -2279,7 +2279,7 @@ ru:
text_journal_aggregation_time_explanation: Объединить журналы для отображения, если
разница в их возрасте меньше заданного значения. Это приведет к задержке почтовых
уведомлений на указанное время.
text_journal_changed: "%{label} changed from %{old} </br><strong>to</strong> %{new}"
text_journal_changed: "%{label} изменено с %{old} </br><strong>на</strong> %{new}"
text_journal_changed_no_detail: "%{label} обновлено"
text_journal_changed_with_diff: "%{label} изменена (%{link})"
text_journal_deleted: "%{label} удалена (%{old})"

@ -0,0 +1,143 @@
#!/usr/bin/env puma
# Load "path" as a rackup file.
#
# The default is "config.ru".
#
# rackup '/u/apps/lolcat/config.ru'
# Set the port on which puma binds
port ENV['PORT'] || 3000
# Set the environment in which the rack's app will run. The value must be a string.
#
# The default is "development".
#
# environment 'production'
environment ENV['RAILS_ENV'] || 'development'
# Disable request logging.
#
# The default is "false".
#
# quiet
# Configure "min" to be the minimum number of threads to use to answer
# requests and "max" the maximum.
#
# The default is "0, 16".
#
threads 1, 1
# Code to run before doing a restart. This code should
# close log files, database connections, etc.
#
# This can be called multiple times to add code each time.
#
# on_restart do
# puts 'On restart...'
# end
# Command to use to restart puma. This should be just how to
# load puma itself (ie. 'ruby -Ilib bin/puma'), not the arguments
# to puma, as those are the same as the original process.
#
# restart_command '/u/app/lolcat/bin/restart_puma'
# === Cluster mode ===
# How many worker processes to run. Typically this is set to
# to the number of available cores.
#
# The default is "0".
#
workers ENV['WEB_CONCURRENCY'] || 4
# Code to run immediately before the master starts workers.
#
# before_fork do
# puts "Starting workers..."
# end
# Code to run in a worker before it starts serving requests.
#
# This is called everytime a worker is to be started.
#
on_worker_boot do
ActiveRecord::Base.establish_connection
end
# Code to run in a worker right before it exits.
#
# This is called everytime a worker is to about to shutdown.
#
# on_worker_shutdown do
# puts 'On worker shutdown...'
# end
# Code to run in the master right before a worker is started. The worker's
# index is passed as an argument.
#
# This is called everytime a worker is to be started.
#
# on_worker_fork do
# puts 'Before worker fork...'
# end
# Code to run in the master after a worker has been started. The worker's
# index is passed as an argument.
#
# This is called everytime a worker is to be started.
#
# after_worker_fork do
# puts 'After worker fork...'
# end
# Allow workers to reload bundler context when master process is issued
# a USR1 signal. This allows proper reloading of gems while the master
# is preserved across a phased-restart. (incompatible with preload_app)
# (off by default)
# prune_bundler
# Preload the application before starting the workers; this conflicts with
# phased restart feature. (off by default)
preload_app! if ENV['RAILS_ENV'] == 'production'
# Additional text to display in process listing
#
# tag 'app name'
#
# If you do not specify a tag, Puma will infer it. If you do not want Puma
# to add a tag, use an empty string.
# Verifies that all workers have checked in to the master process within
# the given timeout. If not the worker process will be restarted. This is
# not a request timeout, it is to protect against a hung or dead process.
# Setting this value will not protect against slow requests.
# Default value is 60 seconds.
#
# worker_timeout 60
# Change the default worker timeout for booting
#
# If unspecified, this defaults to the value of worker_timeout.
#
# worker_boot_timeout 60
# === Puma control rack application ===
# Start the puma control rack application on "url". This application can
# be communicated with to control the main server. Additionally, you can
# provide an authentication token, so all requests to the control server
# will need to include that token as a query parameter. This allows for
# simple authentication.
#
# Check out https://github.com/puma/puma/blob/master/lib/puma/app/status.rb
# to see what the app has available.
#
# activate_control_app 'unix:///var/run/pumactl.sock'
# activate_control_app 'unix:///var/run/pumactl.sock', { auth_token: '12345' }
# activate_control_app 'unix:///var/run/pumactl.sock', { no_token: true }

@ -78,8 +78,8 @@ export class WorkPackageTableFilters extends WorkPackageTableBaseState<QueryFilt
let availableFilters = this.availableSchemas
.map(schema => (schema.filter.allowedValues as QueryFilterResource[])[0]);
// We do not use the id filter as of now as we do not have adequate
// We do not use the filters id and parent as of now as we do not have adequate
// means to select the values.
return _.filter(availableFilters, filter => filter.id !== 'id');
return _.filter(availableFilters, filter => filter.id !== 'id' && filter.id !== 'parent');
}
}

@ -0,0 +1,59 @@
#-- encoding: UTF-8
#-- copyright
# OpenProject is a project management system.
# Copyright (C) 2012-2018 the OpenProject Foundation (OPF)
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2017 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See docs/COPYRIGHT.rdoc for more details.
#++
module API
module V3
module Queries
module Schemas
class ByWorkPackageFilterDependencyRepresenter <
FilterDependencyRepresenter
def json_cache_key
super + (filter.project.present? ? [filter.project.id] : [])
end
def href_callback
if filter.project
api_v3_paths.work_packages_by_project(filter.project.id)
else
api_v3_paths.work_packages
end
end
private
def type
'[]WorkPackage'
end
end
end
end
end
end

@ -32,27 +32,7 @@ module API
module V3
module Queries
module Schemas
class IdFilterDependencyRepresenter <
FilterDependencyRepresenter
def json_cache_key
super + (filter.project.present? ? [filter.project.id] : [])
end
def href_callback
if filter.project
api_v3_paths.work_packages_by_project(filter.project.id)
else
api_v3_paths.work_packages
end
end
private
def type
'[]WorkPackage'
end
end
class IdFilterDependencyRepresenter < ByWorkPackageFilterDependencyRepresenter; end
end
end
end

@ -0,0 +1,39 @@
#-- encoding: UTF-8
#-- copyright
# OpenProject is a project management system.
# Copyright (C) 2012-2018 the OpenProject Foundation (OPF)
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2017 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See docs/COPYRIGHT.rdoc for more details.
#++
module API
module V3
module Queries
module Schemas
class ParentFilterDependencyRepresenter < ByWorkPackageFilterDependencyRepresenter; end
end
end
end
end

@ -65,8 +65,6 @@ module OpenProject
'rails_relative_url_root' => '',
'rails_force_ssl' => false,
'rails_asset_host' => nil,
# Enable internal asset server
'enable_internal_assets_server' => false,
# user configuration
'default_comment_sort_order' => 'asc',

@ -0,0 +1,133 @@
#-- copyright
# OpenProject is a project management system.
# Copyright (C) 2012-2018 the OpenProject Foundation (OPF)
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2017 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See docs/COPYRIGHT.rdoc for more details.
#++
require 'spec_helper'
describe ::API::V3::Queries::Schemas::ParentFilterDependencyRepresenter, clear_cache: true do
include ::API::V3::Utilities::PathHelper
let(:project) { FactoryGirl.build_stubbed(:project) }
let(:query) { FactoryGirl.build_stubbed(:query, project: project) }
let(:filter) { Queries::WorkPackages::Filter::ParentFilter.create!(context: query) }
let(:form_embedded) { false }
let(:instance) do
described_class.new(filter,
operator,
form_embedded: form_embedded)
end
subject(:generated) { instance.to_json }
context 'generation' do
context 'properties' do
describe 'values' do
context 'within project' do
let(:path) { 'values' }
let(:type) { '[]WorkPackage' }
let(:href) { api_v3_paths.work_packages_by_project(project.id) }
context "for operator 'Queries::Operators::Equals'" do
let(:operator) { Queries::Operators::Equals }
it_behaves_like 'filter dependency with allowed link'
end
context "for operator 'Queries::Operators::NotEquals'" do
let(:operator) { Queries::Operators::NotEquals }
it_behaves_like 'filter dependency with allowed link'
end
end
context 'outside of a project' do
let(:project) { nil }
let(:path) { 'values' }
let(:type) { '[]WorkPackage' }
let(:href) { api_v3_paths.work_packages }
context "for operator 'Queries::Operators::Equals'" do
let(:operator) { Queries::Operators::Equals }
it_behaves_like 'filter dependency with allowed link'
end
context "for operator 'Queries::Operators::NotEquals'" do
let(:operator) { Queries::Operators::NotEquals }
it_behaves_like 'filter dependency with allowed link'
end
end
end
end
describe 'caching' do
let(:operator) { Queries::Operators::Equals }
let(:other_project) { FactoryGirl.build_stubbed(:project) }
before do
# fill the cache
instance.to_json
end
it 'is cached' do
expect(instance)
.not_to receive(:to_hash)
instance.to_json
end
it 'busts the cache on a different operator' do
instance.send(:operator=, Queries::Operators::NotEquals)
expect(instance)
.to receive(:to_hash)
instance.to_json
end
it 'busts the cache on a different project' do
query.project = other_project
expect(instance)
.to receive(:to_hash)
instance.to_json
end
it 'busts the cache on changes to the locale' do
expect(instance)
.to receive(:to_hash)
I18n.with_locale(:de) do
instance.to_json
end
end
end
end
end

@ -243,6 +243,8 @@ describe OpenProject::Configuration do
Setting[:email_delivery_method] = nil
# reload configuration to isolate specs
OpenProject::Configuration.load
# clear settings cache to isolate specs
Setting.clear_cache
end
it 'does nothing if no legacy configuration given' do
@ -292,6 +294,8 @@ describe OpenProject::Configuration do
after do
# reload configuration to isolate specs
OpenProject::Configuration.load
# clear settings cache to isolate specs
Setting.clear_cache
end
it 'uses the legacy method to configure email settings' do

@ -57,7 +57,7 @@ describe Queries::WorkPackages::Filter::IdFilter, type: :model do
expect(instance).to be_available
end
it 'is fals if no work package exists/ is visible' do
it 'is false if no work package exists/ is visible' do
allow(WorkPackage)
.to receive_message_chain(:visible, :for_projects, :exists?)
.with(no_args)
@ -105,8 +105,18 @@ describe Queries::WorkPackages::Filter::IdFilter, type: :model do
end
describe '#value_object' do
it 'raises an error' do
expect { instance.value_objects }.to raise_error NotImplementedError
let(:visible_wp) { FactoryGirl.build_stubbed(:work_package) }
it 'returns the work package for the values' do
allow(WorkPackage)
.to receive_message_chain(:visible, :for_projects, :find)
.with(no_args)
.with(project)
.with(instance.values)
.and_return([visible_wp])
expect(instance.value_objects)
.to match_array [visible_wp]
end
end

@ -0,0 +1,259 @@
#-- encoding: UTF-8
#-- copyright
# OpenProject is a project management system.
# Copyright (C) 2012-2018 the OpenProject Foundation (OPF)
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2017 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See docs/COPYRIGHT.rdoc for more details.
#++
require 'spec_helper'
describe Queries::WorkPackages::Filter::ParentFilter, type: :model do
let(:project) { FactoryGirl.build_stubbed(:project) }
let(:query) do
FactoryGirl.build_stubbed(:query, project: project)
end
it_behaves_like 'basic query filter' do
let(:class_key) { :parent }
let(:type) { :list }
before do
instance.context = query
end
describe '#available?' do
context 'within a project' do
it 'is true if any work package exists and is visible' do
allow(WorkPackage)
.to receive_message_chain(:visible, :for_projects, :exists?)
.with(no_args)
.with(project)
.with(no_args)
.and_return true
expect(instance).to be_available
end
it 'is false if no work package exists/ is visible' do
allow(WorkPackage)
.to receive_message_chain(:visible, :for_projects, :exists?)
.with(no_args)
.with(project)
.with(no_args)
.and_return false
expect(instance).not_to be_available
end
end
context 'outside of a project' do
let(:project) { nil }
it 'is true if any work package exists and is visible' do
allow(WorkPackage)
.to receive_message_chain(:visible, :exists?)
.with(no_args)
.and_return true
expect(instance).to be_available
end
it 'is false if no work package exists/ is visible' do
allow(WorkPackage)
.to receive_message_chain(:visible, :exists?)
.with(no_args)
.and_return false
expect(instance).not_to be_available
end
end
end
describe '#ar_object_filter?' do
it 'is true' do
expect(instance).to be_ar_object_filter
end
end
describe '#allowed_values' do
it 'raises an error' do
expect { instance.allowed_values }.to raise_error NotImplementedError
end
end
describe '#value_object' do
let(:visible_wp) { FactoryGirl.build_stubbed(:work_package) }
it 'returns the work package for the values' do
allow(WorkPackage)
.to receive_message_chain(:visible, :for_projects, :find)
.with(no_args)
.with(project)
.with(instance.values)
.and_return([visible_wp])
expect(instance.value_objects)
.to match_array [visible_wp]
end
end
describe '#allowed_objects' do
it 'raises an error' do
expect { instance.allowed_objects }.to raise_error NotImplementedError
end
end
describe '#valid_values!' do
let(:visible_wp) { FactoryGirl.build_stubbed(:work_package) }
let(:invisible_wp) { FactoryGirl.build_stubbed(:work_package) }
context 'within a project' do
it 'removes all non existing/non visible ids' do
instance.values = [visible_wp.id.to_s, invisible_wp.id.to_s, '999999']
allow(WorkPackage)
.to receive_message_chain(:visible, :for_projects, :where, :pluck)
.with(no_args)
.with(project)
.with(id: instance.values)
.with(:id)
.and_return([visible_wp.id])
instance.valid_values!
expect(instance.values)
.to match_array [visible_wp.id.to_s]
end
end
context 'outside of a project' do
let(:project) { nil }
it 'removes all non existing/non visible ids' do
instance.values = [visible_wp.id.to_s, invisible_wp.id.to_s, '999999']
allow(WorkPackage)
.to receive_message_chain(:visible, :where, :pluck)
.with(no_args)
.with(id: instance.values)
.with(:id)
.and_return([visible_wp.id])
instance.valid_values!
expect(instance.values)
.to match_array [visible_wp.id.to_s]
end
end
end
describe '#validate' do
let(:visible_wp) { FactoryGirl.build_stubbed(:work_package) }
let(:invisible_wp) { FactoryGirl.build_stubbed(:work_package) }
context 'within a project' do
it 'is valid if only visible wps are values' do
instance.values = [visible_wp.id.to_s]
allow(WorkPackage)
.to receive_message_chain(:visible, :for_projects, :where, :pluck)
.with(no_args)
.with(project)
.with(id: instance.values)
.with(:id)
.and_return([visible_wp.id])
expect(instance).to be_valid
end
it 'is invalid if invisible wps are values' do
instance.values = [invisible_wp.id.to_s, visible_wp.id.to_s]
allow(WorkPackage)
.to receive_message_chain(:visible, :for_projects, :where, :pluck)
.with(no_args)
.with(project)
.with(id: instance.values)
.with(:id)
.and_return([visible_wp.id])
expect(instance).not_to be_valid
end
end
context 'outside of a project' do
let(:project) { nil }
it 'is valid if only visible wps are values' do
instance.values = [visible_wp.id.to_s]
allow(WorkPackage)
.to receive_message_chain(:visible, :where, :pluck)
.with(no_args)
.with(id: instance.values)
.with(:id)
.and_return([visible_wp.id])
expect(instance).to be_valid
end
it 'is invalid if invisible wps are values' do
instance.values = [invisible_wp.id.to_s, visible_wp.id.to_s]
allow(WorkPackage)
.to receive_message_chain(:visible, :where, :pluck)
.with(no_args)
.with(id: instance.values)
.with(:id)
.and_return([visible_wp.id])
expect(instance).not_to be_valid
end
end
end
describe '#where and #includes' do
let(:parent) { FactoryGirl.create(:work_package) }
let(:visible_wp) { FactoryGirl.create(:work_package, parent: parent) }
before do
visible_wp
instance.values = [parent.id.to_s]
instance.operator = '='
end
it 'filters' do
scope = WorkPackage
.references(instance.includes)
.includes(instance.includes)
.where(instance.where)
expect(scope)
.to match_array [visible_wp]
end
end
end
end

@ -41,7 +41,7 @@ Capybara.register_server :single_puma do |app, port, host|
workers: 0,
daemon: false,
Silent: false,
Threads: "0:4",
Threads: "1:1",
config_files: ['-']
end
Capybara.server = :single_puma

Loading…
Cancel
Save