Merge pull request #16 from ulferts/experimental/new_wp_table/remove_wp_experimental

Experimental/new wp table/remove wp experimental
pull/4159/head
Oliver Günther 9 years ago
commit 0a805e1e60
  1. 2
      app/controllers/api/experimental/concerns/column_data.rb
  2. 79
      app/controllers/api/experimental/concerns/v3_naming.rb
  3. 2
      app/controllers/api/experimental/queries_controller.rb
  4. 102
      app/controllers/api/experimental/work_packages_controller.rb
  5. 62
      app/views/api/experimental/work_packages/index.api.rabl
  6. 5
      config/routes.rb
  7. 42
      frontend/app/components/api/api-work-packages/api-work-packages.service.ts
  8. 3
      frontend/app/components/common/path-heleper/path-helper.service.js
  9. 15
      frontend/app/components/modals/columns-modal/columns-modal.controller.js
  10. 5
      frontend/app/components/query/query-service.service.ts
  11. 2
      frontend/app/components/query/query.service.js
  12. 27
      frontend/app/components/routing/wp-list/wp-list.controller.ts
  13. 37
      frontend/app/components/work-packages/work-package.service.js
  14. 1
      frontend/app/openproject-app.js
  15. 38
      frontend/app/work_packages/config/index.js
  16. 5
      frontend/app/work_packages/directives/query-columns-directive.js
  17. 3
      lib/api/utilities/property_name_converter.rb
  18. 166
      spec/controllers/api/experimental/work_packages_controller_spec.rb

@ -29,7 +29,7 @@
module Api::Experimental::Concerns::ColumnData
def get_columns_for_json(columns)
columns.map do |column|
{ name: column.name,
{ name: internal_to_v3_name(column.name),
title: column.caption,
sortable: column.sortable?,
groupable: column.groupable?,

@ -0,0 +1,79 @@
#-- copyright
# OpenProject is a project management system.
# Copyright (C) 2012-2015 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-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 doc/COPYRIGHT.rdoc for more details.
#++
module Api::Experimental::Concerns::V3Naming
def v3_to_internal_name(string, append_id: true)
API::Utilities::PropertyNameConverter.to_ar_name(string,
context: WorkPackage.new,
refer_to_ids: append_id)
end
def internal_to_v3_name(string)
API::Utilities::PropertyNameConverter.from_ar_name(string)
end
def v3_params_as_internal
params[:c] = params[:c].map { |column|
v3_to_internal_name(column, append_id: false)
} if params[:c]
params[:f] = params[:f].map { |column|
v3_to_internal_name(column)
} if params[:f]
params[:op] = params[:op].each_with_object({}) { |(column, operator), hash|
hash[v3_to_internal_name(column)] = operator
} if params[:op]
params[:v] = params[:v].each_with_object({}) { |(column, value), hash|
hash[v3_to_internal_name(column)] = value
} if params[:v]
params[:sort] = begin
(params[:sort] || '').split(',').map { |sort|
criteria = sort.split(':')
"#{v3_to_internal_name(criteria.first, append_id: false)}:#{criteria.last}"
}.join(',')
end if params[:sort]
end
def json_query_as_v3(json_query)
json_query['column_names'] = (json_query['column_names'] || []).map { |column|
internal_to_v3_name(column)
}
json_query['sort_criteria'] = (json_query['sort_criteria'] || []).map { |criteria|
[internal_to_v3_name(criteria.first), criteria.last]
}
json_query['group_by'] = internal_to_v3_name(json_query['group_by'])
json_query['filters'].each do |filter|
filter[:name] = internal_to_v3_name(filter[:name])
end
json_query
end
end

@ -32,12 +32,14 @@ module Api::Experimental
include Api::Experimental::Concerns::GrapeRouting
include Api::Experimental::Concerns::ColumnData
include Api::Experimental::Concerns::QueryLoading
include Api::Experimental::Concerns::V3Naming
include QueriesHelper
include ExtendedHTTP
before_filter :find_optional_project
before_filter :setup_query_for_create, only: [:create]
before_filter :v3_params_as_internal, only: [:create, :update]
before_filter :setup_existing_query, only: [:update, :destroy]
before_filter :authorize_on_query, only: [:create, :destroy]
before_filter :authorize_update_on_query, only: [:update]

@ -35,79 +35,39 @@ module Api
include ::Api::Experimental::Concerns::GrapeRouting
include ::Api::Experimental::Concerns::ColumnData
include ::Api::Experimental::Concerns::QueryLoading
include ::Api::Experimental::Concerns::V3Naming
include PaginationHelper
include QueriesHelper
include SortHelper
include ExtendedHTTP
before_filter :find_optional_project
before_filter :load_query, only: [:index,
:column_sums]
before_filter :find_optional_project,
:v3_params_as_internal,
:load_query
def index
@work_packages = current_work_packages
columns = @query.involved_columns + [:id]
@column_names, @custom_field_column_ids = separate_columns_by_custom_fields(columns)
setup_context_menu_actions
@work_packages = ::API::Experimental::WorkPackageDecorator.decorate(@work_packages)
end
def column_data
column_names = valid_columns(params[:column_names] || [])
raise 'API Error: No column names' if column_names.empty?
raise 'API Error: No IDs' unless params[:ids]
ids = params[:ids].map(&:to_i)
work_packages = work_packages_of_ids(ids, column_names)
work_packages = ::API::Experimental::WorkPackageDecorator.decorate(work_packages)
@columns_data = fetch_columns_data(column_names, work_packages)
@columns_meta = {
total_sums: columns_total_sums(column_names, work_packages),
group_sums: columns_group_sums(column_names, work_packages, params[:group_by])
@display_meta = true
@work_packages_meta_data = {
query: query_as_json(@query, User.current),
columns: get_columns_for_json(@query.columns),
groupable_columns: get_columns_for_json(@query.groupable_columns),
page: page_param,
per_page: per_page_param,
per_page_options: Setting.per_page_options_array,
export_formats: export_formats,
_links: work_packages_links
}
end
def column_sums
column_names = valid_columns(params[:column_names] || [])
raise 'API Error' if column_names.empty?
work_packages = work_packages_of_query(@query, column_names)
work_packages = ::API::Experimental::WorkPackageDecorator.decorate(work_packages)
@column_sums = columns_total_sums(column_names, work_packages)
end
private
def setup_context_menu_actions
@can = WorkPackagePolicy.new(User.current)
end
def load_query
@query ||= init_query
rescue ActiveRecord::RecordNotFound
render_404
end
def current_work_packages
initialize_sort
results = @query.results order: sort_clause
work_packages = results.work_packages
.page(page_param)
.per_page(per_page_param)
.changed_since(@since)
set_work_packages_meta_data(@query, results, work_packages)
work_packages
end
def initialize_sort
# The session contains the previous sort criteria.
# For the WP#index, this behaviour is not supported by the frontend, therefore
@ -117,37 +77,6 @@ module Api
sort_update(@query.sortable_columns)
end
def work_packages_of_ids(ids, column_names)
scope = WorkPackage.visible.includes(includes_for_columns(column_names))
Array.wrap(scope.find(*ids)).sort_by { |wp| ids.index wp.id }
end
def work_packages_of_query(query, column_names)
# Note: Do not apply pagination. Used to obtain total query meta data.
results = query.results include: includes_for_columns(column_names)
results.work_packages
end
def set_work_packages_meta_data(query, results, work_packages)
@display_meta = true
@work_packages_meta_data = {
query: query_as_json(query, User.current),
columns: get_columns_for_json(query.columns),
groupable_columns: get_columns_for_json(query.groupable_columns),
work_package_count_by_group: results.work_package_count_by_group,
sums: query.columns.map { |column| results.total_sum_of(column) },
group_sums: query.group_by_column && query.columns.map { |column| results.grouped_sums(column) },
page: page_param,
per_page: per_page_param,
per_page_options: Setting.per_page_options_array,
total_entries: work_packages.total_entries,
export_formats: export_formats,
_links: work_packages_links
}
end
def work_packages_links
links = {}
links[:create] = api_experimental_work_packages_path(@project) if User.current.allowed_to?(:add_work_packages, @project)
@ -159,7 +88,8 @@ module Api
json_query = query.as_json(except: :filters, include: :filters, methods: [:starred])
json_query[:_links] = allowed_links_on_query(query, user)
json_query
json_query_as_v3(json_query)
end
def export_formats

@ -28,68 +28,6 @@
object false
child @work_packages => :work_packages do
@column_names.each do |column_name|
node(column_name, :if => lambda{ |wp| wp.respond_to?(column_name) }) do |wp|
case wp.send(column_name)
when Category
wp.send(column_name).as_json(only: [:id, :name])
when Project
wp.send(column_name).as_json(only: [:id, :name, :identifier])
when IssuePriority
wp.send(column_name).as_json(only: [:id, :name])
when Status
wp.send(column_name).as_json(only: [:id, :name])
when User, Group
wp.send(column_name).as_json(only: [:id, :firstname, :type], methods: :name)
when Version
wp.send(column_name).as_json(only: [:id, :name])
when WorkPackage
wp.send(column_name).as_json(only: [:id, :subject])
else
wp.send(column_name)
end
end
end
node(:custom_values) do |wp|
wp.custom_values_display_data @custom_field_column_ids
end
# add parent id by default to make hierarchies transparent
node :parent_id do |wp|
wp.parent_id
end
node :updated_at do |wp|
wp.updated_at.utc.iso8601
end
node :created_at do |wp|
wp.created_at.utc.iso8601
end
node :_actions do |wp|
@can.actions(wp)
end
node :_links do |wp|
if wp.persisted?
links = {
edit: -> { edit_work_package_path(wp) },
log_time: -> { new_work_package_time_entry_path(wp) },
watch: -> { watcher_link(wp, User.current) },
duplicate: -> { new_project_work_packages_path({ project_id: wp.project, copy_from: wp }) },
move: -> { new_move_work_packages_path(ids: [wp.id]) },
copy: -> { new_move_work_packages_path(ids: [wp.id], copy: true) },
delete: -> { work_packages_bulk_path(ids: [wp.id], method: :delete) }
}.select { |action, link| @can.allowed?(wp, action) }
links = links.update(links) { |key, old_val, new_val| new_val.() }
end
end
end
if @display_meta
node(:meta) { @work_packages_meta_data }
end

@ -111,10 +111,7 @@ OpenProject::Application.routes.draw do
end
namespace :experimental do
resources :work_packages, only: [:index] do
get :column_data, on: :collection
get :column_sums, on: :collection
end
resources :work_packages, only: [:index]
resources :queries, only: [:create, :update, :destroy] do
get :available_columns, on: :collection
get :custom_field_filters, on: :collection

@ -26,39 +26,40 @@
// See doc/COPYRIGHT.rdoc for more details.
//++
import {ApiMetaDataService} from "../api-meta-data/api-meta-data.service";
export class ApiWorkPackagesService {
protected WorkPackages;
//TODO: Add missing properties.
protected propertyMap = {
assigned_to: 'assignee',
updated_at: 'updatedAt'
};
constructor (protected DEFAULT_PAGINATION_OPTIONS,
protected $stateParams,
protected $q:ng.IQService,
protected apiV3:restangular.IService,
protected apiMetaData:ApiMetaDataService) {
this.WorkPackages = apiV3.service('work_packages');
protected apiV3:restangular.IService) {
}
public list(offset:number, pageSize:number, query:api.ex.Query) {
return this.WorkPackages.getList(this.queryAsV3Params(offset, pageSize, query)).then(wpCollection => {
const workPackages;
if (query.project_id) {
workPackages = this.apiV3.service('work_packages', this.apiV3.one('projects', query.project_id));
}
else {
workPackages = this.apiV3.service('work_packages');
}
return workPackages.getList(this.queryAsV3Params(offset, pageSize, query)).then(wpCollection => {
return wpCollection;
});
}
protected queryAsV3Params(offset:number, pageSize:number, query:api.ex.Query) {
const v3Filters = _.map(query.filters, (filter) => {
const newFilter = {};
newFilter[filter.name] = {operator: filter.operator, values: filter.values};
return newFilter;
});
const params = {
offset: offset,
pageSize: pageSize,
filters: [query.filters],
sortBy: query.sort_criteria,
filters: [v3Filters]
};
if (query.group_by) {
@ -69,11 +70,14 @@ export class ApiWorkPackagesService {
params['showSums'] = query.display_sums;
}
if (query.sort_criteria) {
params['sortBy'] = [query.sort_criteria];
}
return params;
}
}
angular
.module('openproject.api')
.service('apiWorkPackages', ApiWorkPackagesService);

@ -210,9 +210,6 @@ function PathHelper() {
// experimantal, TODO: Migrate to V3
return PathHelper.apiExperimental + '/users';
},
apiWorkPackagesColumnDataPath: function() {
return PathHelper.apiWorkPackagesPath() + '/column_data';
},
apiWorkPackagesPath: function() {
return PathHelper.apiExperimental + '/work_packages';
},

@ -69,10 +69,6 @@ function ColumnsModalController($scope, columnsModal, QueryService, WorkPackageS
});
});
function getNewlyAddedColumns() {
return _.difference(vm.selectedColumns, vm.oldSelectedColumns);
}
function getColumnNames(arr) {
return _.map(arr, function (column) {
return column.name;
@ -82,17 +78,6 @@ function ColumnsModalController($scope, columnsModal, QueryService, WorkPackageS
vm.updateSelectedColumns = function() {
QueryService.setSelectedColumns(getColumnNames(vm.selectedColumns));
// Augment work packages with new columns data
var addedColumns = getNewlyAddedColumns(),
currentWorkPackages = WorkPackagesTableService.getRowsData(),
groupBy = WorkPackagesTableService.getGroupBy();
if(groupBy.length === 0) groupBy = undefined; // don't pass an empty string as groupBy
if(addedColumns.length) {
$rootScope.refreshWorkPackages = WorkPackageService.augmentWorkPackagesWithColumnsData(currentWorkPackages, addedColumns, groupBy);
}
columnsModal.deactivate();
};

@ -197,10 +197,7 @@ function QueryService(Query,
var url = projectIdentifier ? PathHelper.apiProjectAvailableColumnsPath(projectIdentifier) : PathHelper.apiAvailableColumnsPath();
return QueryService.doGet(url, function(response){
availableColumns = response.data.available_columns;
return availableColumns;
});
return QueryService.doGet(url, (response) => response.data.available_columns);
},
getGroupBy: function() {

@ -237,7 +237,7 @@ function QueryConstructorService(Filter, Sortation, UrlParamsHelper, INITIALLY_S
* @returns {undefined}
*/
setDefaultFilter: function() {
var statusOpenFilterData = this.getExtendedFilterData({name: 'status_id', operator: 'o'});
var statusOpenFilterData = this.getExtendedFilterData({name: 'status', operator: 'o'});
this.filters = [new Filter(statusOpenFilterData)];
},

@ -104,14 +104,17 @@ function WorkPackagesListController($scope,
apiWorkPackages
.list(json.meta.page, json.meta.per_page, json.meta.query)
.then((workPackageCollection) => {
json.work_packages = workPackageCollection.getElements();
mergeApiResponses(json, workPackageCollection);
setupPage(json, !!queryParams);
});
QueryService.loadAvailableUnusedColumns($scope.projectIdentifier).then(function(data){
$scope.availableUnusedColumns = data;
});
QueryService.loadAvailableGroupedQueries($scope.projectIdentifier);
});
if ($scope.projectIdentifier) {
ProjectService.getProject($scope.projectIdentifier).then(function(project) {
$scope.project = project;
@ -119,7 +122,6 @@ function WorkPackagesListController($scope,
});
}
QueryService.loadAvailableGroupedQueries($scope.projectIdentifier);
});
}
@ -230,14 +232,29 @@ function WorkPackagesListController($scope,
$scope.query, PaginationService.getPaginationOptions())
.then(function (json:api.ex.WorkPackagesMeta) {
apiWorkPackages
.list(json.meta.page, json.meta.per_page, json.meta.query, json.meta.columns)
.list(json.meta.page, json.meta.per_page, json.meta.query)
.then((workPackageCollection) => {
json.work_packages = workPackageCollection.getElements();
// Copy V3 group/sum response into experimental format
mergeApiResponses(json, workPackageCollection);
setupWorkPackagesTable(json);
});
});
}
function mergeApiResponses(exJson, workPackages) {
exJson.work_packages = workPackages.elements;
if (workPackages.totalSums) {
exJson.meta.sums = exJson.meta.columns.map(column => workPackages.totalSums[column.name]);
} else {
exJson.meta.sums = new Array(exJson.meta.columns.length);
}
// TODO: no longer use detour over $source once the properties are available
// directly on the CollectionResource
exJson.meta.total_entries = workPackages.$source.total;
}
// Go
initialSetup();

@ -184,20 +184,6 @@ function WorkPackageService($http, PathHelper, UrlParamsHelper, WorkPackagesHelp
return WorkPackageService.doQuery(url, params);
},
loadWorkPackageColumnsData: function(workPackages, columnNames, group_by) {
var url = PathHelper.apiWorkPackagesColumnDataPath();
var params = {
'ids[]': workPackages.map(function(workPackage){
return workPackage.id;
}),
'column_names[]': columnNames,
'group_by': group_by
};
return WorkPackageService.doQuery(url, params);
},
// Note: Should this be on a project-service?
getWorkPackagesSums: function(projectIdentifier, query, columns){
var columnNames = columns.map(function(column){
@ -217,29 +203,6 @@ function WorkPackageService($http, PathHelper, UrlParamsHelper, WorkPackagesHelp
return WorkPackageService.doQuery(url, params);
},
augmentWorkPackagesWithColumnsData: function(workPackages, columns, group_by) {
var columnNames = columns.map(function(column) {
return column.name;
});
return WorkPackageService.loadWorkPackageColumnsData(workPackages, columnNames, group_by)
.then(function(data){
var columnsData = data.columns_data;
var columnsMeta = data.columns_meta;
angular.forEach(columns, function(column, i){
column.total_sum = columnsMeta.total_sums[i];
if (columnsMeta.group_sums) column.group_sums = columnsMeta.group_sums[i];
angular.forEach(workPackages, function(workPackage, j) {
WorkPackagesHelper.augmentWorkPackageWithData(workPackage, column.name, !!column.custom_field, columnsData[i][j]);
});
});
return workPackages;
});
},
loadWorkPackageForm: function(workPackage) {
if (this.authorizedFor(workPackage, 'update')) {
var options = { ajax: {

@ -75,6 +75,7 @@ angular.module(
'openproject.helpers',
'openproject.workPackages.config',
'openproject.workPackages.helpers',
'openproject.api',
'angular-cache'
]);
angular.module('openproject.helpers', ['openproject.services']);

@ -46,26 +46,26 @@ angular.module('openproject.workPackages.config')
})
.constant('AVAILABLE_WORK_PACKAGE_FILTERS', {
status_id: { type: 'list_status', modelName: 'status' , order: 1, locale_name: 'status' },
type_id: { type: 'list_model', modelName: 'type', order: 2, locale_name: 'type' },
priority_id: { type: 'list_model', modelName: 'priority', order: 3, locale_name: 'priority'},
assigned_to_id: { type: 'list_optional', modelName: 'user' , order: 4, locale_name: 'assigned_to' },
author_id: { type: 'list_model', modelName: 'user' , order: 5, locale_name: 'author' },
watcher_id: {type: 'list_model', modelName: 'user', order: 6, locale_name: 'watcher'},
responsible_id: {type: 'list_optional', modelName: 'user', order: 6, locale_name: 'responsible'},
fixed_version_id: {type: 'list_optional', modelName: 'version', order: 7, locale_name: 'fixed_version'},
category_id: { type: 'list_optional', modelName: 'category', order: 7, locale_name: 'category' },
member_of_group: {type: 'list_optional', modelName: 'group', order: 8, locale_name: 'member_of_group'},
assigned_to_role: {type: 'list_optional', modelName: 'role', order: 9, locale_name: 'assigned_to_role'},
status: { type: 'list_status', modelName: 'status' , order: 1, locale_name: 'status' },
type: { type: 'list_model', modelName: 'type', order: 2, locale_name: 'type' },
priority: { type: 'list_model', modelName: 'priority', order: 3, locale_name: 'priority'},
assignee: { type: 'list_optional', modelName: 'user' , order: 4, locale_name: 'assigned_to' },
author: { type: 'list_model', modelName: 'user' , order: 5, locale_name: 'author' },
watcher: {type: 'list_model', modelName: 'user', order: 6, locale_name: 'watcher'},
responsible: {type: 'list_optional', modelName: 'user', order: 6, locale_name: 'responsible'},
version: {type: 'list_optional', modelName: 'version', order: 7, locale_name: 'fixed_version'},
category: { type: 'list_optional', modelName: 'category', order: 7, locale_name: 'category' },
memberOfGroup: {type: 'list_optional', modelName: 'group', order: 8, locale_name: 'member_of_group'},
assignedToRole: {type: 'list_optional', modelName: 'role', order: 9, locale_name: 'assigned_to_role'},
subject: { type: 'text', order: 10, locale_name: 'subject' },
created_at: { type: 'date_past', order: 11, locale_name: 'created_at' },
updated_at: { type: 'date_past', order: 12, locale_name: 'updated_at' },
start_date: { type: 'date', order: 13, locale_name: 'start_date' },
due_date: { type: 'date', order: 14, locale_name: 'due_date' },
estimated_hours: { type: 'integer', order: 15, locale_name: 'estimated_hours' },
done_ratio: { type: 'integer', order: 16, locale_name: 'done_ratio' },
project_id: { type: 'list_model', modelName: 'project', order: 17, locale_name: 'project' },
subproject_id: { type: 'list_subprojects', modelName: 'sub_project', order: 18, locale_name: 'subproject' }
createdOn: { type: 'date_past', order: 11, locale_name: 'created_at' },
updatedOn: { type: 'date_past', order: 12, locale_name: 'updated_at' },
startDate: { type: 'date', order: 13, locale_name: 'start_date' },
dueDate: { type: 'date', order: 14, locale_name: 'due_date' },
estimatedTime: { type: 'integer', order: 15, locale_name: 'estimated_hours' },
percentageDone: { type: 'integer', order: 16, locale_name: 'done_ratio' },
project: { type: 'list_model', modelName: 'project', order: 17, locale_name: 'project' },
subprojectId: { type: 'list_subprojects', modelName: 'sub_project', order: 18, locale_name: 'subproject' }
})
.constant('DEFAULT_SORT_CRITERIA', 'parent:desc')

@ -68,8 +68,9 @@ module.exports = function(WorkPackagesTableHelper, WorkPackagesTableService, Wor
var newColumns = WorkPackagesTableHelper.selectColumnsByName(scope.columns, columnNames);
WorkPackageService.augmentWorkPackagesWithColumnsData(workPackages, newColumns, groupBy)
.then(function(){ scope.$emit('queryStateChange'); });
scope.$emit('queryStateChange');
// WorkPackageService.augmentWorkPackagesWithColumnsData(workPackages, newColumns, groupBy)
// .then(function(){ scope.$emit('queryStateChange'); });
}
}
};

@ -54,7 +54,8 @@ module API
created_on: 'createdAt',
updated_on: 'updatedAt',
remaining_hours: 'remainingTime',
spent_hours: 'spentTime'
spent_hours: 'spentTime',
subproject: 'subprojectId'
}
# Converts the attribute name as refered to by ActiveRecord to a corresponding API-conform

@ -88,13 +88,6 @@ describe Api::Experimental::WorkPackagesController, type: :controller do
describe '#index' do
context 'with no work packages available' do
it 'assigns an empty work packages array' do
get 'index', format: 'json'
expect(assigns(:work_packages)).to eq([])
# expect(assigns(:allowed_statuses)).to eq([])
end
it 'renders the index template' do
get 'index', format: 'json'
expect(response).to render_template('api/experimental/work_packages/index')
@ -102,13 +95,13 @@ describe Api::Experimental::WorkPackagesController, type: :controller do
it 'assigns a query which has the default filter arguments set' do
allow(Query).to receive(:new).and_call_original
expected_query = Query.new
expected_query = Query.new name: '_'
expect(Query).to receive(:new).with(anything, initialize_with_default_filter: true)
.and_return(expected_query)
get 'index', format: 'json'
expect(assigns(:query)).to eql expected_query
#expect(assigns(:query)).to eq expected_query
end
%w(group_by c fields f sort is_public name display_sums).each do |filter_param|
@ -125,59 +118,6 @@ describe Api::Experimental::WorkPackagesController, type: :controller do
end
end
context 'with work packages' do
let(:query) { FactoryGirl.build_stubbed(:query).tap(&:add_default_filter) }
before do
# FIXME: find a better solution does not involve reaching into the internals
allow(controller).to receive(:retrieve_query).and_return(query)
allow(query).to receive_message_chain(:results, :work_packages, :page, :per_page, :changed_since).and_return(work_packages)
allow(query).to receive_message_chain(:results, :work_package_count_by_group).and_return([])
allow(query).to receive_message_chain(:results, :column_total_sums).and_return([])
allow(query).to receive_message_chain(:results, :column_group_sums).and_return([])
allow(query).to receive_message_chain(:results, :total_sum_of).and_return(2)
allow(query).to receive_message_chain(:results, :total_entries).and_return([])
# FIXME: METADATA TOO TRICKY TO DEAL WITH
allow(controller).to receive(:set_work_packages_meta_data)
end
context 'with project_1 work packages' do
let(:work_packages) { [work_package_1, work_package_2, work_package_3] }
it 'assigns work packages array + actions' do
get 'index', format: 'json', query_id: query_1.id, project_id: project_1.id
expect(assigns(:work_packages).size).to eq(2)
expect(assigns(:can).allowed?(work_package_1, :edit)).to be_truthy
expect(assigns(:can).allowed?(work_package_1, :log_time)).to be_truthy
expect(assigns(:can).allowed?(work_package_1, :move)).to be_truthy
expect(assigns(:can).allowed?(work_package_1, :copy)).to be_truthy
expect(assigns(:can).allowed?(work_package_1, :delete)).to be_truthy
end
end
context 'with default query' do
let(:work_packages) { [work_package_1, work_package_2, work_package_3] }
before do
# As work_package_3 is in project_2 we need to make the
# current user a member
FactoryGirl.create(:member, project: project_2,
principal: current_user,
roles: [role])
end
it 'assigns work packages array + actions' do
get 'index', format: 'json'
expect(assigns(:work_packages).size).to eq(3)
expect(assigns(:project)).to be_nil
end
end
end
context 'without the necessary permissions' do
let(:role) { FactoryGirl.create(:role, permissions: []) }
@ -217,106 +157,4 @@ describe Api::Experimental::WorkPackagesController, type: :controller do
end
end
end
describe '#column_data' do
context 'with incorrect parameters' do
specify {
expect { get :column_data, format: 'json' }.to raise_error(/API Error/)
}
specify {
expect { get :column_data, format: 'json', ids: [1, 2] }.to raise_error(/API Error/)
}
specify {
expect { get :column_data, format: 'json', column_names: %w(subject status) }.to raise_error(/API Error/)
}
end
context 'with column ids and column names' do
before do
# N.B.: for the purpose of example only. It makes little sense to sum a ratio.
allow(Setting).to receive(:work_package_list_summable_columns).and_return(
%w(estimated_hours done_ratio)
)
allow(WorkPackage).to receive_message_chain(:visible, :includes, :find) {
FactoryGirl.create_list(:work_package, 2, estimated_hours: 5, done_ratio: 33)
}
end
it 'handles incorrect column names' do
expect { get :column_data, format: 'json', ids: [1, 2], column_names: %w(non_existent) }.to raise_error(/API Error/)
end
it 'assigns column data' do
get :column_data, format: 'json', ids: [1, 2], column_names: %w(subject status estimated_hours)
expect(assigns(:columns_data).size).to eq(3)
expect(assigns(:columns_data).first.size).to eq(2)
end
it 'assigns column metadata' do
get :column_data, format: 'json', ids: [1, 2],
column_names: %w(subject status estimated_hours done_ratio)
expect(assigns(:columns_meta)).to have_key(:group_sums)
expect(assigns(:columns_meta)).to have_key(:total_sums)
expect(assigns(:columns_meta)[:total_sums].size).to eq(4)
expect(assigns(:columns_meta)[:total_sums][2]).to eq(10.0)
expect(assigns(:columns_meta)[:total_sums][3]).to eq(66)
end
it 'renders the column_data template' do
get :column_data, format: 'json', ids: [1, 2], column_names: %w(subject status estimated_hours)
expect(response).to render_template('api/experimental/work_packages/column_data')
end
end
context 'without the necessary permissions' do
let(:role) { FactoryGirl.create(:role, permissions: []) }
it 'should return 403 for the global action' do
get 'column_data', format: 'json'
expect(response.response_code).to eql(403)
end
it 'should return 403 for the project based action' do
get 'column_data', format: 'json', project_id: project_1.id
expect(response.response_code).to eql(403)
end
end
end
describe '#column_sums' do
it 'returns 200' do
get 'column_sums', column_names: ['id'], format: 'json'
expect(response.response_code).to eql(200)
end
it 'renders template' do
get 'column_sums', column_names: ['id'], format: 'json'
expect(response).to render_template('api/experimental/work_packages/column_sums')
end
context 'without the necessary permissions' do
let(:role) { FactoryGirl.create(:role, permissions: []) }
it 'should return 403 for the global action' do
get 'column_sums', format: 'json'
expect(response.response_code).to eql(403)
end
it 'should return 403 for the project based action' do
get 'column_sums', format: 'json', project_id: project_1.id
expect(response.response_code).to eql(403)
end
end
end
end

Loading…
Cancel
Save