OpenProject is the leading open source project management software.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
openproject/lib/api/v3/queries/query_representer.rb

435 lines
14 KiB

#-- encoding: UTF-8
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2021 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 docs/COPYRIGHT.rdoc for more details.
#++
require 'roar/decorator'
require 'roar/json/hal'
module API
module V3
module Queries
class QueryRepresenter < ::API::Decorators::Single
self_link
include API::Decorators::LinkedResource
include API::Decorators::DateProperty
associated_resource :project,
setter: ->(fragment:, **) {
id = id_from_href "projects", fragment['href']
id = if id.to_i.nonzero?
id # return numerical ID
else
Project.where(identifier: id).pluck(:id).first # lookup Project by identifier
end
represented.project_id = id if id
},
skip_link: ->(*) {
false
},
skip_render: ->(*) {
represented.project.nil?
}
link :results do
path = if represented.project
api_v3_paths.work_packages_by_project(represented.project.id)
else
api_v3_paths.work_packages
end
url_query = ::API::V3::Queries::QueryParamsRepresenter
Boards module (#7008) * Hack spike to show D&D use case [ci skip] * Add ordered work packages * Save order on existing work packages * Boards WIP * CDK drag * Add dragula handler [ci skip] * Add filter to return all manual sorted work packages * Print icon on hover * Boards routing and list components * Better loading indicator on list with streaming result [ci skip] * Add new board and list buttons [ci skip] * Post new query [ci skip] * Added creation of new board lists with persisted queries [ci skip] * Render placeholder row in empty queries [ci skip] * Push boards on grid * Use base class in scope [ci skip] * Extend api for options * Hack spike to show D&D use case [ci skip] * Add ordered work packages * Save order on existing work packages * Boards WIP * CDK drag * Add dragula handler [ci skip] * Add filter to return all manual sorted work packages * Print icon on hover * Boards routing and list components * Better loading indicator on list with streaming result [ci skip] * Add new board and list buttons [ci skip] * Post new query [ci skip] * Added creation of new board lists with persisted queries [ci skip] * Render placeholder row in empty queries [ci skip] * Save queries in grids [ci skip] * Renaming queries [ci skip] * Add existing work packages to board [ci skip] * Introduce card view component for work packages * Extend grids to allow project scope for boards (#7025) Extends the grid backend to also be able to handle boards. In particular, it adds the ability of boards to be attached to projects and changes the page property of grids to a scope property that better describes that more than one board can belong to the same scope (e.g. /projects/:project_id/boards). For a fully featured board, though, widgets need to be able to store options, so that they can store queries. Those widgets might also need to have custom processing and validation. That part has not been implemented. * introduce project association for boards * have dedicated grid registration classes * update and create form for board grids * extract defaults into grid registration [ci skip] * Add drag and drop to card view [ci skip] * Add options to grid * Fix option migration name * Renaming boards [ci skip] * Frontend deletion of boards * Avoid map on NodeList which doesnt exist [ci skip] * Add inline create to boards [ci skip] * Smaller create button [ci skip] * Add navigation for boards * Make inner grid same height * Replace index page with table * Workaround for widget registration [ci skip] * Fixed height for cards and tables [ci skip] * Implement escape as cancel d&d action [ci skip] * Fix and extend grid specs for name and options * Extend board specs for required name * Fix migration for MySQL references https://stackoverflow.com/a/45825566/420614 * Make board list extend from widget Since we cannot configure widgets yet, it's not yet possible to use a board-list widget anywhere. * Fix specs * Fix escape listener removal [ci skip] * Fix renamed to_path in relation spec [ci skip] * Allow deletion of grids for boards * Avoid reloading resource multiple times with replays * Frontend synchronization on deletion [ci skip] * Delete through table * Use work packages board path * Use work packages board path * Fix augmented columns breaking re-rendering * Fix duplicated permission with forums * Strengthen tab switch in specs * Add hidden flag for project-context queries Allows the API to create a hidden query that will not be rendered to the user even if it is within a project context. * private queries * Add hidden flag for project-context queries Allows the API to create a hidden query that will not be rendered to the user even if it is within a project context. * Move boards below work packages * Add Board configuration modal * Fix reloading with onPush * Saving / Switching of display mode [ci skip] * Extract wp-query-selectable-title into common component * Fix renaming of board-list * Fix auto-hide notifications in boards * Add permissions to seeders * Reorder lists in board * Linting * Remove default gravatar from settings * Show assignees avatar in the card view of WPs * Fix specs * Add missing method * Fix timeline icon * Use URL as input to be able to show avatars for groups, too * Fix test * Add further specs * Use correct data attribute to avoid unnecessary data base calls * Add further specs * Deletion of board lists * Pass permission via gon to decide whether we can create boards * Fix rename spec * Cherry-pick of 7873d59 and 30abc7f
6 years ago
.new(represented)
.to_url_query(merge_params: params.slice(:offset, :pageSize))
{
href: [path, url_query].join('?')
}
end
link :star do
next if represented.starred || !allowed_to?(:star)
{
href: api_v3_paths.query_star(represented.id),
method: :patch
}
end
link :unstar do
next unless represented.starred && allowed_to?(:unstar)
{
href: api_v3_paths.query_unstar(represented.id),
method: :patch
}
end
link :schema do
href = if represented.project
api_v3_paths.query_project_schema(represented.project.identifier)
else
api_v3_paths.query_schema
end
{
href: href
}
end
link :update do
href = if represented.new_record?
api_v3_paths.create_query_form
else
api_v3_paths.query_form(represented.id)
end
{
href: href,
method: :post
}
end
link :updateImmediately do
next unless represented.new_record? && allowed_to?(:create) ||
represented.persisted? && allowed_to?(:update)
{
href: api_v3_paths.query(represented.id),
method: :patch
}
end
link :updateOrderedWorkPackages do
next unless represented.new_record? && allowed_to?(:create) ||
represented.persisted? && allowed_to?(:reorder_work_packages)
{
href: api_v3_paths.query_order(represented.id),
method: :put
}
end
link :delete do
next if represented.new_record? ||
!allowed_to?(:destroy)
{
href: api_v3_paths.query(represented.id),
method: :delete
}
end
associated_resource :user
resources :sortBy,
getter: ->(*) {
if represented.sort_criteria
map_with_sort_by_as_decorated(represented.sort_criteria_columns) do |sort_by|
::API::V3::Queries::SortBys::QuerySortByRepresenter.new(sort_by)
end
end
},
setter: ->(fragment:, **) {
criteria = Array(fragment).map do |sort_by|
column_direction_from_href(sort_by)
end
represented.sort_criteria = criteria.compact if fragment
},
link: ->(*) {
map_with_sort_by_as_decorated(represented.sort_criteria_columns) do |sort_by|
{
href: api_v3_paths.query_sort_by(sort_by.converted_name, sort_by.direction_name),
title: sort_by.name
}
end
}
resource :groupBy,
getter: ->(*) {
if represented.grouped?
column = represented.group_by_column
::API::V3::Queries::GroupBys::QueryGroupByRepresenter.new(column)
end
},
setter: ->(fragment:, **) {
attr = id_from_href "queries/group_bys", fragment['href']
represented.group_by =
if attr.nil?
nil
else
::API::Utilities::PropertyNameConverter.to_ar_name(attr, context: WorkPackage.new)
end
},
link: ->(*) {
column = represented.group_by_column
if column
{
href: api_v3_paths.query_group_by(convert_attribute(column.name)),
title: column.caption
}
else
{
href: nil,
title: nil
}
end
}
resources :columns,
getter: ->(*) {
represented.columns.map do |column|
::API::V3::Queries::Columns::QueryColumnsFactory.create(column)
end
},
setter: ->(fragment:, **) {
columns = Array(fragment).map do |column|
name = id_from_href "queries/columns", column['href']
::API::Utilities::PropertyNameConverter.to_ar_name(name, context: WorkPackage.new) if name
end
represented.column_names = columns.map(&:to_sym).compact if fragment
},
link: ->(*) {
represented.columns.map do |column|
{
href: api_v3_paths.query_column(convert_attribute(column.name)),
title: column.caption
}
end
}
resources :highlighted_attributes,
getter: ->(*) {
represented.highlighted_columns.map do |column|
::API::V3::Queries::Columns::QueryColumnsFactory.create(column)
end
},
setter: ->(fragment:, **) {
columns = Array(fragment).map do |column|
name = id_from_href "queries/columns", column['href']
::API::Utilities::PropertyNameConverter.to_ar_name(name, context: WorkPackage.new) if name
end
represented.highlighted_attributes = columns.map(&:to_sym).compact if fragment
},
link: ->(*) {
represented.highlighted_columns.map do |column|
{
href: api_v3_paths.query_column(convert_attribute(column.name)),
title: column.caption
}
end
}
Boards module (#7008) * Hack spike to show D&D use case [ci skip] * Add ordered work packages * Save order on existing work packages * Boards WIP * CDK drag * Add dragula handler [ci skip] * Add filter to return all manual sorted work packages * Print icon on hover * Boards routing and list components * Better loading indicator on list with streaming result [ci skip] * Add new board and list buttons [ci skip] * Post new query [ci skip] * Added creation of new board lists with persisted queries [ci skip] * Render placeholder row in empty queries [ci skip] * Push boards on grid * Use base class in scope [ci skip] * Extend api for options * Hack spike to show D&D use case [ci skip] * Add ordered work packages * Save order on existing work packages * Boards WIP * CDK drag * Add dragula handler [ci skip] * Add filter to return all manual sorted work packages * Print icon on hover * Boards routing and list components * Better loading indicator on list with streaming result [ci skip] * Add new board and list buttons [ci skip] * Post new query [ci skip] * Added creation of new board lists with persisted queries [ci skip] * Render placeholder row in empty queries [ci skip] * Save queries in grids [ci skip] * Renaming queries [ci skip] * Add existing work packages to board [ci skip] * Introduce card view component for work packages * Extend grids to allow project scope for boards (#7025) Extends the grid backend to also be able to handle boards. In particular, it adds the ability of boards to be attached to projects and changes the page property of grids to a scope property that better describes that more than one board can belong to the same scope (e.g. /projects/:project_id/boards). For a fully featured board, though, widgets need to be able to store options, so that they can store queries. Those widgets might also need to have custom processing and validation. That part has not been implemented. * introduce project association for boards * have dedicated grid registration classes * update and create form for board grids * extract defaults into grid registration [ci skip] * Add drag and drop to card view [ci skip] * Add options to grid * Fix option migration name * Renaming boards [ci skip] * Frontend deletion of boards * Avoid map on NodeList which doesnt exist [ci skip] * Add inline create to boards [ci skip] * Smaller create button [ci skip] * Add navigation for boards * Make inner grid same height * Replace index page with table * Workaround for widget registration [ci skip] * Fixed height for cards and tables [ci skip] * Implement escape as cancel d&d action [ci skip] * Fix and extend grid specs for name and options * Extend board specs for required name * Fix migration for MySQL references https://stackoverflow.com/a/45825566/420614 * Make board list extend from widget Since we cannot configure widgets yet, it's not yet possible to use a board-list widget anywhere. * Fix specs * Fix escape listener removal [ci skip] * Fix renamed to_path in relation spec [ci skip] * Allow deletion of grids for boards * Avoid reloading resource multiple times with replays * Frontend synchronization on deletion [ci skip] * Delete through table * Use work packages board path * Use work packages board path * Fix augmented columns breaking re-rendering * Fix duplicated permission with forums * Strengthen tab switch in specs * Add hidden flag for project-context queries Allows the API to create a hidden query that will not be rendered to the user even if it is within a project context. * private queries * Add hidden flag for project-context queries Allows the API to create a hidden query that will not be rendered to the user even if it is within a project context. * Move boards below work packages * Add Board configuration modal * Fix reloading with onPush * Saving / Switching of display mode [ci skip] * Extract wp-query-selectable-title into common component * Fix renaming of board-list * Fix auto-hide notifications in boards * Add permissions to seeders * Reorder lists in board * Linting * Remove default gravatar from settings * Show assignees avatar in the card view of WPs * Fix specs * Add missing method * Fix timeline icon * Use URL as input to be able to show avatars for groups, too * Fix test * Add further specs * Use correct data attribute to avoid unnecessary data base calls * Add further specs * Deletion of board lists * Pass permission via gon to decide whether we can create boards * Fix rename spec * Cherry-pick of 7873d59 and 30abc7f
6 years ago
property :ordered_work_packages,
skip_render: true,
exec_context: :decorator,
getter: nil,
setter: ->(fragment:, **) {
next unless represented.new_record?
Boards module (#7008) * Hack spike to show D&D use case [ci skip] * Add ordered work packages * Save order on existing work packages * Boards WIP * CDK drag * Add dragula handler [ci skip] * Add filter to return all manual sorted work packages * Print icon on hover * Boards routing and list components * Better loading indicator on list with streaming result [ci skip] * Add new board and list buttons [ci skip] * Post new query [ci skip] * Added creation of new board lists with persisted queries [ci skip] * Render placeholder row in empty queries [ci skip] * Push boards on grid * Use base class in scope [ci skip] * Extend api for options * Hack spike to show D&D use case [ci skip] * Add ordered work packages * Save order on existing work packages * Boards WIP * CDK drag * Add dragula handler [ci skip] * Add filter to return all manual sorted work packages * Print icon on hover * Boards routing and list components * Better loading indicator on list with streaming result [ci skip] * Add new board and list buttons [ci skip] * Post new query [ci skip] * Added creation of new board lists with persisted queries [ci skip] * Render placeholder row in empty queries [ci skip] * Save queries in grids [ci skip] * Renaming queries [ci skip] * Add existing work packages to board [ci skip] * Introduce card view component for work packages * Extend grids to allow project scope for boards (#7025) Extends the grid backend to also be able to handle boards. In particular, it adds the ability of boards to be attached to projects and changes the page property of grids to a scope property that better describes that more than one board can belong to the same scope (e.g. /projects/:project_id/boards). For a fully featured board, though, widgets need to be able to store options, so that they can store queries. Those widgets might also need to have custom processing and validation. That part has not been implemented. * introduce project association for boards * have dedicated grid registration classes * update and create form for board grids * extract defaults into grid registration [ci skip] * Add drag and drop to card view [ci skip] * Add options to grid * Fix option migration name * Renaming boards [ci skip] * Frontend deletion of boards * Avoid map on NodeList which doesnt exist [ci skip] * Add inline create to boards [ci skip] * Smaller create button [ci skip] * Add navigation for boards * Make inner grid same height * Replace index page with table * Workaround for widget registration [ci skip] * Fixed height for cards and tables [ci skip] * Implement escape as cancel d&d action [ci skip] * Fix and extend grid specs for name and options * Extend board specs for required name * Fix migration for MySQL references https://stackoverflow.com/a/45825566/420614 * Make board list extend from widget Since we cannot configure widgets yet, it's not yet possible to use a board-list widget anywhere. * Fix specs * Fix escape listener removal [ci skip] * Fix renamed to_path in relation spec [ci skip] * Allow deletion of grids for boards * Avoid reloading resource multiple times with replays * Frontend synchronization on deletion [ci skip] * Delete through table * Use work packages board path * Use work packages board path * Fix augmented columns breaking re-rendering * Fix duplicated permission with forums * Strengthen tab switch in specs * Add hidden flag for project-context queries Allows the API to create a hidden query that will not be rendered to the user even if it is within a project context. * private queries * Add hidden flag for project-context queries Allows the API to create a hidden query that will not be rendered to the user even if it is within a project context. * Move boards below work packages * Add Board configuration modal * Fix reloading with onPush * Saving / Switching of display mode [ci skip] * Extract wp-query-selectable-title into common component * Fix renaming of board-list * Fix auto-hide notifications in boards * Add permissions to seeders * Reorder lists in board * Linting * Remove default gravatar from settings * Show assignees avatar in the card view of WPs * Fix specs * Add missing method * Fix timeline icon * Use URL as input to be able to show avatars for groups, too * Fix test * Add further specs * Use correct data attribute to avoid unnecessary data base calls * Add further specs * Deletion of board lists * Pass permission via gon to decide whether we can create boards * Fix rename spec * Cherry-pick of 7873d59 and 30abc7f
6 years ago
5 years ago
Hash(fragment).each do |wp_id, position|
represented.ordered_work_packages.build(work_package_id: wp_id, position: position)
end
Boards module (#7008) * Hack spike to show D&D use case [ci skip] * Add ordered work packages * Save order on existing work packages * Boards WIP * CDK drag * Add dragula handler [ci skip] * Add filter to return all manual sorted work packages * Print icon on hover * Boards routing and list components * Better loading indicator on list with streaming result [ci skip] * Add new board and list buttons [ci skip] * Post new query [ci skip] * Added creation of new board lists with persisted queries [ci skip] * Render placeholder row in empty queries [ci skip] * Push boards on grid * Use base class in scope [ci skip] * Extend api for options * Hack spike to show D&D use case [ci skip] * Add ordered work packages * Save order on existing work packages * Boards WIP * CDK drag * Add dragula handler [ci skip] * Add filter to return all manual sorted work packages * Print icon on hover * Boards routing and list components * Better loading indicator on list with streaming result [ci skip] * Add new board and list buttons [ci skip] * Post new query [ci skip] * Added creation of new board lists with persisted queries [ci skip] * Render placeholder row in empty queries [ci skip] * Save queries in grids [ci skip] * Renaming queries [ci skip] * Add existing work packages to board [ci skip] * Introduce card view component for work packages * Extend grids to allow project scope for boards (#7025) Extends the grid backend to also be able to handle boards. In particular, it adds the ability of boards to be attached to projects and changes the page property of grids to a scope property that better describes that more than one board can belong to the same scope (e.g. /projects/:project_id/boards). For a fully featured board, though, widgets need to be able to store options, so that they can store queries. Those widgets might also need to have custom processing and validation. That part has not been implemented. * introduce project association for boards * have dedicated grid registration classes * update and create form for board grids * extract defaults into grid registration [ci skip] * Add drag and drop to card view [ci skip] * Add options to grid * Fix option migration name * Renaming boards [ci skip] * Frontend deletion of boards * Avoid map on NodeList which doesnt exist [ci skip] * Add inline create to boards [ci skip] * Smaller create button [ci skip] * Add navigation for boards * Make inner grid same height * Replace index page with table * Workaround for widget registration [ci skip] * Fixed height for cards and tables [ci skip] * Implement escape as cancel d&d action [ci skip] * Fix and extend grid specs for name and options * Extend board specs for required name * Fix migration for MySQL references https://stackoverflow.com/a/45825566/420614 * Make board list extend from widget Since we cannot configure widgets yet, it's not yet possible to use a board-list widget anywhere. * Fix specs * Fix escape listener removal [ci skip] * Fix renamed to_path in relation spec [ci skip] * Allow deletion of grids for boards * Avoid reloading resource multiple times with replays * Frontend synchronization on deletion [ci skip] * Delete through table * Use work packages board path * Use work packages board path * Fix augmented columns breaking re-rendering * Fix duplicated permission with forums * Strengthen tab switch in specs * Add hidden flag for project-context queries Allows the API to create a hidden query that will not be rendered to the user even if it is within a project context. * private queries * Add hidden flag for project-context queries Allows the API to create a hidden query that will not be rendered to the user even if it is within a project context. * Move boards below work packages * Add Board configuration modal * Fix reloading with onPush * Saving / Switching of display mode [ci skip] * Extract wp-query-selectable-title into common component * Fix renaming of board-list * Fix auto-hide notifications in boards * Add permissions to seeders * Reorder lists in board * Linting * Remove default gravatar from settings * Show assignees avatar in the card view of WPs * Fix specs * Add missing method * Fix timeline icon * Use URL as input to be able to show avatars for groups, too * Fix test * Add further specs * Use correct data attribute to avoid unnecessary data base calls * Add further specs * Deletion of board lists * Pass permission via gon to decide whether we can create boards * Fix rename spec * Cherry-pick of 7873d59 and 30abc7f
6 years ago
}
property :starred,
writeable: true
8 years ago
property :results,
exec_context: :decorator,
render_nil: true,
8 years ago
embedded: true,
if: ->(*) {
results
}
8 years ago
property :id,
writeable: false
property :name
date_time_property :created_at
date_time_property :updated_at
property :filters,
exec_context: :decorator
property :display_sums, as: :sums
property :is_public, as: :public
property :hidden
# Timeline properties
property :timeline_visible
property :show_hierarchies
property :timeline_zoom_level
property :timeline_labels
# Visible representation of the results
property :display_representation
# Highlighting properties
property :highlighting_mode,
render_nil: false
attr_accessor :results,
:params
def initialize(model,
current_user:,
results: nil,
embed_links: false,
params: {})
8 years ago
self.results = results
self.params = params
super(model, current_user: current_user, embed_links: embed_links)
end
self.to_eager_load = [:query_menu_item,
:user,
{ project: :work_package_custom_fields }]
def _type
'Query'
end
def filters
represented.filters.map do |filter|
::API::V3::Queries::Filters::QueryFilterInstanceRepresenter
.new(filter)
end
end
def filters=(filters_hash)
represented.filters = []
filters_hash.each do |filter_attributes|
name = get_filter_name filter_attributes
if name && (filter = represented.filter_for name)
filter_representer = ::API::V3::Queries::Filters::QueryFilterInstanceRepresenter.new(filter)
filter = filter_representer.from_hash filter_attributes
represented.filters << filter
else
raise API::Errors::InvalidRequestBody, "Could not read filter from: #{filter_attributes}"
end
end
end
Fix/bump representable (#5465) * bump reform and roar -> bumps representer * adapt to changed validation interface * disable initializer patch for now * adapt to changed representable attr interface * can no longer have private methods inside a representer * private no longer possible for representer * bump reform * wip - restyle validation * remove commented out patch * apply injection as prescribed * reactivate reform error symbols patch * remove patch to Hash superfluous wit ruby 2.3 * remove outdated human_attribute_name patch * whitespace fixes * adapt filter name after removal of human_attribute_name patch * adapt filter specs to no longer rely on human_attribute_name patch * fix version filter name * remove reliance on no longer existing human_attribute_name patch * use correct key in journal formatter * remove private from representer * adapt to altered setter interface * reenable i18n for error messages in contracts * no private methods in representer * defined model for contracts * fix validaton * instantiate correct Object * define model for contract * circumvent now existing render method on reform * replace deprecated constant * patch correct reform class - not the module - via prepend * refactor too complex method * replace deprations * remove remnants of parentId * prevent error symbols from existing twice * adapt user representer to altered setter interface * adapt watcher representer to altered setter interface * remove now unnessary patch * adapt setter to altered interface * adapt spec * fix custom field setters * remove parentId from wp representer As the parent is a wp resource, clients should use the parent link instead * adapt spec to changed valid? interface * remove parentId from wp schema * replace references of parentId in frontend * remove TODO [ci skip]
8 years ago
private
def allowed_to?(action)
return false unless current_user
@policy ||= QueryPolicy.new(current_user)
@policy.allowed?(represented, action)
end
def self_v3_path(*_args)
base = if represented.new_record?
default_query_path
else
super
end
[base, query_props].select(&:present?).join('?')
end
def convert_attribute(attribute)
::API::Utilities::PropertyNameConverter.from_ar_name(attribute)
end
def get_filter_name(filter_attributes)
href = filter_attributes.dig("_links", "filter", "href")
id = id_from_href "queries/filters", href
::API::Utilities::QueryFiltersNameConverter.to_ar_name id, refer_to_ids: true if id
end
def id_from_href(expected_namespace, href)
return nil if href.blank?
::API::Utilities::ResourceLinkParser.parse_id(
href,
property: (expected_namespace && expected_namespace.split("/").last) || "filter_value",
expected_version: "3",
expected_namespace: expected_namespace
)
end
def column_direction_from_href(sort_by)
if id = id_from_href("queries/sort_bys", sort_by['href'])
column, direction = id.split("-") # e.g. ["start_date", "desc"]
if column && direction
column = ::API::Utilities::PropertyNameConverter.to_ar_name(column, context: WorkPackage.new)
direction = nil unless ["asc", "desc"].include? direction
[column, direction]
end
end
end
def map_with_sort_by_as_decorated(sort_criteria)
sort_criteria.reject { |c, o| c.nil? || o.nil? }.map do |column, order|
decorated = ::API::V3::Queries::SortBys::SortByDecorator.new(column, order)
yield decorated
end
end
def default_query_path
if represented.project
api_v3_paths.query_project_default(represented.project.id)
else
api_v3_paths.query_default
end
end
def query_props
params.symbolize_keys.except(:id).to_query
end
end
end
end
end