Merge pull request #1072 from opf/feature/angular-api-work-package-loading
Feature/angular api work package loadingpull/1075/head
commit
05a957883a
@ -0,0 +1,43 @@ |
||||
angular.module('openproject.workPackages.config') |
||||
|
||||
.constant('INITIALLY_SELECTED_COLUMNS', ['id', 'project', 'type', 'status', 'priority', 'subject', 'assigned_to_id', 'updated_at']) |
||||
|
||||
.constant('OPERATORS_AND_LABELS_BY_FILTER_TYPE', { |
||||
list: {'=':'is','!':'is not'}, |
||||
list_model: {'=':'is','!':'is not'}, |
||||
list_status: {'o':'open','=':'is','!':'is not','c':'closed','*':'all'}, // TODO RS: Need a generalised solution
|
||||
list_optional: {'=':'is','!':'is not','!*':'none','*':'all'}, |
||||
list_subprojects: {'*':'all','!*':'none','=':'is'}, |
||||
date: {'<t+':'in less than','>t+':'in more than','t+':'in','t':'today','w':'this week','>t-':'less than days ago','<t-':'more than days ago','t-':'days ago'}, |
||||
date_past: {'>t-':'less than days ago','<t-':'more than days ago','t-':'days ago','t':'today','w':'this week'}, |
||||
string: {'=':'is','~':'contains','!':'is not','!~':"doesn't contain"}, |
||||
text: {'~':'contains','!~':"doesn't contain"}, |
||||
integer: {'=':'is','>=':'>=','<=':'<=','!*':'none','*':'all'} |
||||
}) |
||||
|
||||
.constant('AVAILABLE_WORK_PACKAGE_FILTERS', { |
||||
status_id: { type: 'list_status', modelName: 'status' , order: 1, name: 'Status' }, |
||||
type_id: { type: 'list_model', modelName: 'type', order: 2, name: 'Type' }, |
||||
priority_id: { type: 'list_model', modelName: 'priority', order: 3, name: 'Priority'}, |
||||
assigned_to_id: { type: 'list_model', modelName: 'user' , order: 4, name: 'Assigned to' }, |
||||
author_id: { type: 'list_model', modelName: 'user' , order: 5, name: 'Author' }, |
||||
responsible_id: {type: 'list_model', modelName: 'user', order: 6, name: 'Watcher'}, |
||||
fixed_version_id: {type: 'list_model', modelName: 'version', order: 7, name: 'Version'}, |
||||
member_of_group: {type: 'list_model', modelName: 'group', order: 8, name: 'Assignee\'s group'}, |
||||
assigned_to_role: {type: 'list_model', modelName: 'role', order: 9, name: 'Assignee\'s role'}, |
||||
subject: { type: 'text', order: 10, name: 'Subject' }, |
||||
created_at: { type: 'date_past', order: 11, name: 'Created on' }, |
||||
updated_at: { type: 'date_past', order: 12, name: 'Updated on' }, |
||||
start_date: { type: 'date', order: 13, name: 'Start date' }, |
||||
due_date: { type: 'date', order: 14, name: 'Due date' }, |
||||
estimated_hours: { type: 'integer', order: 15, name: 'Estimated time' }, |
||||
done_ratio: { type: 'integer', order: 16, name: '% done' }, |
||||
}) |
||||
|
||||
.constant('DEFAULT_SORT_CRITERIA', 'parent:desc') |
||||
|
||||
.constant('DEFAULT_PAGINATION_OPTIONS', { |
||||
page: 1, |
||||
perPage: 10, |
||||
perPageOptions: [10, 20, 50, 100, 500, 1000] |
||||
}); |
@ -1,11 +1,11 @@ |
||||
// TODO move to UI components
|
||||
angular.module('openproject.uiComponents') |
||||
|
||||
.directive('iconWrapper', ['I18n', function(I18n){ |
||||
.directive('iconWrapper', [function(){ |
||||
return { |
||||
restrict: 'EA', |
||||
replace: true, |
||||
scope: { iconName: '@', title: '=iconTitle' }, |
||||
scope: { iconName: '@', title: '@iconTitle' }, |
||||
templateUrl: '/templates/components/icon_wrapper.html' |
||||
}; |
||||
}]); |
||||
|
@ -1,22 +1,28 @@ |
||||
// TODO move to UI components
|
||||
angular.module('openproject.uiComponents') |
||||
|
||||
.directive('toggledMultiselect', ['WorkPackagesHelper', function(WorkPackagesHelper){ |
||||
.directive('toggledMultiselect', ['WorkPackagesHelper', 'I18n', function(WorkPackagesHelper, I18n){ |
||||
return { |
||||
restrict: 'EA', |
||||
replace: true, |
||||
scope: { |
||||
name: '=', |
||||
values: '=', |
||||
availableFilterValues: '=', |
||||
availableOptions: '=' |
||||
}, |
||||
templateUrl: '/templates/components/toggled_multiselect.html', |
||||
link: function(scope, element, attributes){ |
||||
scope.I18n = I18n; |
||||
|
||||
scope.toggleMultiselect = function(){ |
||||
scope.isMultiselect = !scope.isMultiselect; |
||||
} |
||||
}; |
||||
|
||||
scope.isSelected = function(value) { |
||||
return Array.isArray(scope.values) && (scope.values.indexOf(value) !== -1 || scope.values.indexOf(value.toString()) !== -1); |
||||
}; |
||||
|
||||
scope.isMultiselect = (scope.values != undefined && scope.values.length > 1); |
||||
scope.isMultiselect = (Array.isArray(scope.values) && scope.values.length > 1); |
||||
} |
||||
}; |
||||
}]); |
||||
|
@ -1,18 +0,0 @@ |
||||
// TODO move to UI components
|
||||
angular.module('openproject.helpers') |
||||
|
||||
.service('FunctionDecorators', ['$timeout', function($timeout) { |
||||
var currentRun; |
||||
|
||||
return { |
||||
withDelay: function(delay, callback, params) { |
||||
$timeout.cancel(currentRun); |
||||
|
||||
currentRun = $timeout(function() { |
||||
return callback.apply(this, params); |
||||
}, delay); |
||||
|
||||
return currentRun; |
||||
} |
||||
}; |
||||
}]); |
@ -0,0 +1,38 @@ |
||||
// TODO move to UI components
|
||||
angular.module('openproject.helpers') |
||||
|
||||
.service('WorkPackageLoadingHelper', ['$timeout', function($timeout) { |
||||
var currentRun; |
||||
|
||||
return { |
||||
withDelay: function(delay, callback, params) { |
||||
$timeout.cancel(currentRun); |
||||
|
||||
currentRun = $timeout(function() { |
||||
return callback.apply(this, params); |
||||
}, delay); |
||||
|
||||
return currentRun; |
||||
}, |
||||
|
||||
/** |
||||
* @name withLoading |
||||
* |
||||
* @description Wraps a data-loading function and manages the loading state within the scope |
||||
* @param {scope} a scope on which an isLoading flag is set |
||||
* @param {function} callback Function returning a promise |
||||
* @param {array} params Params forwarded to the callback |
||||
* @returns {promise} Promise returned by the callback |
||||
*/ |
||||
withLoading: function(scope, callback, params, errorCallback) { |
||||
scope.isLoading = true; |
||||
|
||||
return callback.apply(this, params) |
||||
.then(function(results){ |
||||
scope.isLoading = false; |
||||
|
||||
return results; |
||||
}, errorCallback); |
||||
} |
||||
}; |
||||
}]); |
@ -0,0 +1,21 @@ |
||||
angular.module('openproject.services') |
||||
|
||||
.service('GroupService', ['$http', 'PathHelper', function($http, PathHelper) { |
||||
|
||||
var GroupService = { |
||||
getGroups: function() { |
||||
var url = PathHelper.apiGroupsPath(); |
||||
|
||||
return GroupService.doQuery(url); |
||||
}, |
||||
|
||||
doQuery: function(url, params) { |
||||
return $http.get(url, { params: params }) |
||||
.then(function(response){ |
||||
return response.data.groups; |
||||
}); |
||||
} |
||||
}; |
||||
|
||||
return GroupService; |
||||
}]); |
@ -0,0 +1,52 @@ |
||||
angular.module('openproject.services') |
||||
|
||||
.service('PaginationService', ['DEFAULT_PAGINATION_OPTIONS', function(DEFAULT_PAGINATION_OPTIONS) { |
||||
var paginationOptions = { |
||||
page: DEFAULT_PAGINATION_OPTIONS.page, |
||||
perPage: DEFAULT_PAGINATION_OPTIONS.perPage, |
||||
perPageOptions: DEFAULT_PAGINATION_OPTIONS.perPageOptions |
||||
}; |
||||
|
||||
PaginationService = { |
||||
getPaginationOptions: function() { |
||||
return paginationOptions; |
||||
}, |
||||
getPage: function() { |
||||
return paginationOptions.page; |
||||
}, |
||||
setPage: function(page) { |
||||
paginationOptions.page = page; |
||||
}, |
||||
getPerPage: function() { |
||||
return paginationOptions.perPage; |
||||
}, |
||||
setPerPage: function(perPage) { |
||||
paginationOptions.perPage = perPage; |
||||
}, |
||||
getPerPageOptions: function() { |
||||
return paginationOptions.perPageOptions; |
||||
}, |
||||
setPerPageOptions: function(perPageOptions) { |
||||
paginationOptions.perPageOptions = perPageOptions; |
||||
}, |
||||
|
||||
getLowerPageBound: function() { |
||||
return paginationOptions.perPage * (paginationOptions.page - 1) + 1; |
||||
}, |
||||
getUpperPageBound: function(limit) { |
||||
return Math.min(paginationOptions.perPage * paginationOptions.page, limit); |
||||
}, |
||||
|
||||
resetPage: function() { |
||||
paginationOptions.page = 1; |
||||
}, |
||||
nextPage: function() { |
||||
paginationOptions.page = paginationOptions.page + 1; |
||||
}, |
||||
previousPage: function() { |
||||
paginationOptions.page = paginationOptions.page - 1; |
||||
} |
||||
}; |
||||
|
||||
return PaginationService; |
||||
}]); |
@ -0,0 +1,21 @@ |
||||
angular.module('openproject.services') |
||||
|
||||
.service('PriorityService', ['$http', 'PathHelper', function($http, PathHelper) { |
||||
|
||||
var PriorityService = { |
||||
getPriorities: function() { |
||||
var url = PathHelper.apiPrioritiesPath(); |
||||
|
||||
return PriorityService.doQuery(url); |
||||
}, |
||||
|
||||
doQuery: function(url, params) { |
||||
return $http.get(url, { params: params }) |
||||
.then(function(response){ |
||||
return response.data.planning_element_priorities; |
||||
}); |
||||
} |
||||
}; |
||||
|
||||
return PriorityService; |
||||
}]); |
@ -0,0 +1,70 @@ |
||||
angular.module('openproject.services') |
||||
|
||||
.service('QueryService', ['$http', 'PathHelper', '$q', 'AVAILABLE_WORK_PACKAGE_FILTERS', 'StatusService', 'TypeService', 'PriorityService', 'UserService', 'VersionService', 'RoleService', 'GroupService', function($http, PathHelper, $q, AVAILABLE_WORK_PACKAGE_FILTERS, StatusService, TypeService, PriorityService, UserService, VersionService, RoleService, GroupService) { |
||||
|
||||
var availableColumns = [], availableFilterValues = {}; |
||||
|
||||
var QueryService = { |
||||
getAvailableColumns: function(projectIdentifier) { |
||||
var url = projectIdentifier ? PathHelper.apiProjectAvailableColumnsPath(projectIdentifier) : PathHelper.apiAvailableColumnsPath(); |
||||
|
||||
return QueryService.doQuery(url); |
||||
}, |
||||
|
||||
getAvailableFilterValues: function(filterName, projectIdentifier) { |
||||
var modelName = AVAILABLE_WORK_PACKAGE_FILTERS[filterName].modelName; |
||||
|
||||
if(availableFilterValues[modelName]) { |
||||
return $q.when(availableFilterValues[modelName]); |
||||
} else { |
||||
var retrieveAvailableValues; |
||||
|
||||
switch(modelName) { |
||||
case 'status': |
||||
retrieveAvailableValues = StatusService.getStatuses(projectIdentifier); |
||||
break; |
||||
case 'type': |
||||
retrieveAvailableValues = TypeService.getTypes(projectIdentifier); |
||||
break; |
||||
case 'priority': |
||||
retrieveAvailableValues = PriorityService.getPriorities(projectIdentifier); |
||||
break; |
||||
case 'user': |
||||
retrieveAvailableValues = UserService.getUsers(projectIdentifier); |
||||
break; |
||||
case 'version': |
||||
retrieveAvailableValues = VersionService.getProjectVersions(projectIdentifier); |
||||
break; |
||||
case 'role': |
||||
retrieveAvailableValues = RoleService.getRoles(); |
||||
break; |
||||
case 'group': |
||||
retrieveAvailableValues = GroupService.getGroups(); |
||||
break; |
||||
} |
||||
|
||||
return retrieveAvailableValues.then(function(values) { |
||||
return QueryService.storeAvailableFilterValues(modelName, values); |
||||
}); |
||||
} |
||||
}, |
||||
|
||||
storeAvailableFilterValues: function(modelName, values) { |
||||
availableFilterValues[modelName] = values; |
||||
return values; |
||||
}, |
||||
|
||||
doQuery: function(url, params) { |
||||
return $http({ |
||||
method: 'GET', |
||||
url: url, |
||||
params: params, |
||||
headers: {'Content-Type': 'application/x-www-form-urlencoded'} |
||||
}).then(function(response){ |
||||
return response.data; |
||||
}); |
||||
} |
||||
}; |
||||
|
||||
return QueryService; |
||||
}]); |
@ -0,0 +1,21 @@ |
||||
angular.module('openproject.services') |
||||
|
||||
.service('RoleService', ['$http', 'PathHelper', function($http, PathHelper) { |
||||
|
||||
var RoleService = { |
||||
getRoles: function() { |
||||
var url = PathHelper.apiRolesPath(); |
||||
|
||||
return RoleService.doQuery(url); |
||||
}, |
||||
|
||||
doQuery: function(url, params) { |
||||
return $http.get(url, { params: params }) |
||||
.then(function(response){ |
||||
return response.data.roles; |
||||
}); |
||||
} |
||||
}; |
||||
|
||||
return RoleService; |
||||
}]); |
@ -0,0 +1,27 @@ |
||||
angular.module('openproject.services') |
||||
|
||||
.service('StatusService', ['$http', 'PathHelper', function($http, PathHelper) { |
||||
|
||||
var StatusService = { |
||||
getStatuses: function(projectIdentifier) { |
||||
var url; |
||||
|
||||
if(projectIdentifier) { |
||||
url = PathHelper.apiProjectStatusesPath(projectIdentifier); |
||||
} else { |
||||
url = PathHelper.apiStatusesPath(); |
||||
} |
||||
|
||||
return StatusService.doQuery(url); |
||||
}, |
||||
|
||||
doQuery: function(url, params) { |
||||
return $http.get(url, { params: params }) |
||||
.then(function(response){ |
||||
return response.data.statuses; |
||||
}); |
||||
} |
||||
}; |
||||
|
||||
return StatusService; |
||||
}]); |
@ -0,0 +1,28 @@ |
||||
angular.module('openproject.services') |
||||
|
||||
.service('TypeService', ['$http', 'PathHelper', function($http, PathHelper) { |
||||
|
||||
var TypeService = { |
||||
getTypes: function(projectIdentifier) { |
||||
var url; |
||||
|
||||
if(projectIdentifier) { |
||||
url = PathHelper.apiProjectWorkPackageTypesPath(projectIdentifier); |
||||
} else { |
||||
url = PathHelper.apiWorkPackageTypesPath(); |
||||
} |
||||
|
||||
|
||||
return TypeService.doQuery(url); |
||||
}, |
||||
|
||||
doQuery: function(url, params) { |
||||
return $http.get(url, { params: params }) |
||||
.then(function(response){ |
||||
return response.data.planning_element_types; |
||||
}); |
||||
} |
||||
}; |
||||
|
||||
return TypeService; |
||||
}]); |
@ -0,0 +1,21 @@ |
||||
angular.module('openproject.services') |
||||
|
||||
.service('VersionService', ['$http', 'PathHelper', function($http, PathHelper) { |
||||
|
||||
var VersionService = { |
||||
getProjectVersions: function(projectIdentifier) { |
||||
var url = PathHelper.apiProjectVersionsPath(projectIdentifier); |
||||
|
||||
return VersionService.doQuery(url); |
||||
}, |
||||
|
||||
doQuery: function(url, params) { |
||||
return $http.get(url, { params: params }) |
||||
.then(function(response){ |
||||
return response.data.versions; |
||||
}); |
||||
} |
||||
}; |
||||
|
||||
return VersionService; |
||||
}]); |
@ -0,0 +1,51 @@ |
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2013 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 |
||||
module V3 |
||||
|
||||
module ApiController |
||||
|
||||
include ::Api::V2::ApiController |
||||
extend ::Api::V2::ApiController::ClassMethods |
||||
|
||||
def api_version |
||||
/api\/v3\// |
||||
end |
||||
|
||||
permeate_permissions :authorize, |
||||
:apply_at_timestamp, |
||||
:determine_base, |
||||
:find_all_projects_by_project_id, |
||||
:find_project_by_project_id, |
||||
:jump_to_project_menu_item, |
||||
:find_optional_project_and_raise_error |
||||
|
||||
end |
||||
end |
||||
end |
@ -0,0 +1,51 @@ |
||||
module Api::V3::Concerns::ColumnData |
||||
def get_columns_for_json(columns) |
||||
columns.map do |column| |
||||
{ name: column.name, |
||||
title: column.caption, |
||||
sortable: column.sortable, |
||||
groupable: column.groupable, |
||||
custom_field: column.is_a?(QueryCustomFieldColumn) && |
||||
column.custom_field.as_json(only: [:id, :field_format]), |
||||
meta_data: get_column_meta(column) |
||||
} |
||||
end |
||||
end |
||||
|
||||
private |
||||
|
||||
def get_column_meta(column) |
||||
# This is where we want to add column specific behaviour to instruct the front end how to deal with it |
||||
# Needs to be things like user link,project link, datetime |
||||
{ |
||||
data_type: column_data_type(column), |
||||
link: !!(link_meta()[column.name]) ? link_meta()[column.name] : { display: false } |
||||
} |
||||
end |
||||
|
||||
def link_meta |
||||
{ |
||||
subject: { display: true, model_type: "work_package" }, |
||||
type: { display: false }, |
||||
status: { display: false }, |
||||
priority: { display: false }, |
||||
parent: { display: true, model_type: "user" }, |
||||
assigned_to: { display: true, model_type: "user" }, |
||||
responsible: { display: true, model_type: "user" }, |
||||
author: { display: true, model_type: "user" }, |
||||
project: { display: true, model_type: "project" } |
||||
} |
||||
end |
||||
|
||||
def column_data_type(column) |
||||
if column.is_a?(QueryCustomFieldColumn) |
||||
return column.custom_field.field_format |
||||
elsif (c = WorkPackage.columns_hash[column.name.to_s] and !c.nil?) |
||||
return c.type.to_s |
||||
elsif (c = WorkPackage.columns_hash[column.name.to_s + "_id"] and !c.nil?) |
||||
return "object" |
||||
else |
||||
return "default" |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,47 @@ |
||||
#-- encoding: UTF-8 |
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2014 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 |
||||
module V3 |
||||
|
||||
class GroupsController < ApplicationController |
||||
|
||||
include ::Api::V3::ApiController |
||||
|
||||
def index |
||||
@groups = Group.all |
||||
|
||||
respond_to do |format| |
||||
format.api |
||||
end |
||||
end |
||||
|
||||
end |
||||
end |
||||
end |
@ -0,0 +1,24 @@ |
||||
|
||||
|
||||
module Api::V3 |
||||
class QueriesController < ApplicationController |
||||
unloadable |
||||
|
||||
include ApiController |
||||
include Concerns::ColumnData |
||||
|
||||
include QueriesHelper |
||||
include ExtendedHTTP |
||||
|
||||
before_filter :find_optional_project |
||||
|
||||
def available_columns |
||||
query = retrieve_query |
||||
@available_columns = get_columns_for_json(query.available_columns) |
||||
|
||||
respond_to do |format| |
||||
format.api |
||||
end |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,47 @@ |
||||
#-- encoding: UTF-8 |
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2014 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 |
||||
module V3 |
||||
|
||||
class RolesController < ApplicationController |
||||
|
||||
include ::Api::V3::ApiController |
||||
|
||||
def index |
||||
@roles = Role.all |
||||
|
||||
respond_to do |format| |
||||
format.api |
||||
end |
||||
end |
||||
|
||||
end |
||||
end |
||||
end |
@ -0,0 +1,54 @@ |
||||
#-- encoding: UTF-8 |
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2014 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 |
||||
module V3 |
||||
|
||||
class VersionsController < ApplicationController |
||||
before_filter :find_project |
||||
|
||||
include ::Api::V3::ApiController |
||||
|
||||
def index |
||||
@versions = @project.shared_versions.all |
||||
|
||||
respond_to do |format| |
||||
format.api |
||||
end |
||||
end |
||||
|
||||
private |
||||
|
||||
def find_project |
||||
@project = Project.find(params[:project_id]) |
||||
end |
||||
|
||||
end |
||||
end |
||||
end |
@ -0,0 +1,196 @@ |
||||
|
||||
|
||||
module Api |
||||
module V3 |
||||
|
||||
class WorkPackagesController < ApplicationController |
||||
unloadable |
||||
|
||||
DEFAULT_SORT_ORDER = ['parent', 'desc'] |
||||
|
||||
include ApiController |
||||
include Concerns::ColumnData |
||||
|
||||
include PaginationHelper |
||||
include QueriesHelper |
||||
include SortHelper |
||||
include ExtendedHTTP |
||||
|
||||
|
||||
# before_filter :authorize # TODO specify authorization |
||||
before_filter :authorize_request, only: [:column_data] |
||||
|
||||
before_filter :find_optional_project, only: [:index] |
||||
|
||||
before_filter :load_query, only: [:index] |
||||
before_filter :assign_work_packages, only: [:index] |
||||
|
||||
def index |
||||
@custom_field_column_names = @query.columns.select{|c| c.name.to_s =~ /cf_(.*)/}.map(&:name) |
||||
@column_names = ['id'] | @query.columns.map(&:name) - @custom_field_column_names |
||||
|
||||
# the data for the index is already produced in the assign_work_packages |
||||
respond_to do |format| |
||||
format.api |
||||
end |
||||
end |
||||
|
||||
def column_data |
||||
raise 'API Error: No IDs' unless params[:ids] |
||||
raise 'API Error: No column names' unless params[:column_names] |
||||
|
||||
column_names = params[:column_names] |
||||
ids = params[:ids].map(&:to_i) |
||||
work_packages = Array.wrap(WorkPackage.visible.find(*ids)).sort {|a,b| ids.index(a.id) <=> ids.index(b.id)} |
||||
|
||||
@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]) |
||||
} |
||||
end |
||||
|
||||
def column_sums |
||||
raise 'API Error' unless params[:column_names] |
||||
|
||||
column_names = params[:column_names] |
||||
project = Project.find_visible(current_user, params[:project_id]) |
||||
work_packages = project.work_packages |
||||
|
||||
@column_sums = columns_total_sums(column_names, work_packages) |
||||
end |
||||
|
||||
private |
||||
|
||||
def columns_total_sums(column_names, work_packages) |
||||
column_names.map do |column_name| |
||||
column_sum(column_name, work_packages) |
||||
end |
||||
end |
||||
|
||||
def column_sum(column_name, work_packages) |
||||
fetch_column_data(column_name, work_packages, false).map{|c| c.nil? ? 0 : c}.compact.sum if column_should_be_summed_up?(column_name) |
||||
end |
||||
|
||||
def columns_group_sums(column_names, work_packages, group_by) |
||||
# NOTE RS: This is basically the grouped_sums method from sums.rb but we have no query to play with here |
||||
return unless group_by |
||||
column_names.map do |column_name| |
||||
work_packages.map { |wp| wp.send(group_by) } |
||||
.uniq |
||||
.inject({}) do |group_sums, current_group| |
||||
work_packages_in_current_group = work_packages.select{|wp| wp.send(group_by) == current_group} |
||||
group_sums.merge current_group => column_sum(column_name, work_packages_in_current_group) |
||||
end |
||||
end |
||||
end |
||||
|
||||
def load_query |
||||
@query ||= retrieve_query |
||||
rescue ActiveRecord::RecordNotFound |
||||
render_404 |
||||
end |
||||
|
||||
def authorize_request |
||||
# TODO: need to give this action a global role i think. tried making load_column_data role in reminde.rb |
||||
# but couldn't get it working. |
||||
# authorize_global unless performed? |
||||
end |
||||
|
||||
def assign_work_packages |
||||
@work_packages = current_work_packages(@project) unless performed? |
||||
end |
||||
|
||||
def current_work_packages(projects) |
||||
sort_init(@query.sort_criteria.empty? ? [DEFAULT_SORT_ORDER] : @query.sort_criteria) |
||||
sort_update(@query.sortable_columns) |
||||
|
||||
results = @query.results include: [:assigned_to, :type, :priority, :category, :fixed_version], |
||||
order: sort_clause |
||||
|
||||
work_packages = results.work_packages |
||||
.page(page_param) |
||||
.per_page(per_page_param) |
||||
.changed_since(@since) |
||||
.all |
||||
set_work_packages_meta_data(@query, results, work_packages) |
||||
|
||||
work_packages |
||||
end |
||||
|
||||
def set_work_packages_meta_data(query, results, work_packages) |
||||
@display_meta = true |
||||
|
||||
@work_packages_meta_data = { |
||||
query: query.as_json(except: :filters, include: :filters), |
||||
columns: get_columns_for_json(query.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 |
||||
} |
||||
end |
||||
|
||||
# TODO RS: Taken from work_packages_controller, not dry - move to application controller. |
||||
def per_page_param |
||||
case params[:format] |
||||
when 'csv', 'pdf' |
||||
Setting.work_packages_export_limit.to_i |
||||
when 'atom' |
||||
Setting.feeds_limit.to_i |
||||
else |
||||
super |
||||
end |
||||
end |
||||
|
||||
def fetch_columns_data(column_names, work_packages) |
||||
column_names.map do |column_name| |
||||
fetch_column_data(column_name, work_packages) |
||||
end |
||||
end |
||||
|
||||
def fetch_column_data(column_name, work_packages, display = true) |
||||
if column_name =~ /cf_(.*)/ |
||||
custom_field = CustomField.find($1) |
||||
work_packages.map do |work_package| |
||||
custom_value = work_package.custom_values.find_by_custom_field_id($1) |
||||
if display |
||||
work_package.custom_value_display(custom_value) |
||||
else |
||||
custom_field.cast_value custom_value.try(:value) |
||||
end |
||||
end |
||||
else |
||||
work_packages.map do |work_package| |
||||
# Note: Doing as_json here because if we just take the value.attributes then we can't get any methods later. |
||||
# Name and subject are the default properties that the front end currently looks for to summarize an object. |
||||
value = work_package.send(column_name) |
||||
value.is_a?(ActiveRecord::Base) ? value.as_json( only: "id", methods: [:name, :subject] ) : value |
||||
end |
||||
end |
||||
end |
||||
|
||||
def column_should_be_summed_up?(column_name) |
||||
# see ::Query::Sums mix in |
||||
column_is_numeric?(column_name) && Setting.work_package_list_summable_columns.include?(column_name.to_s) |
||||
end |
||||
|
||||
def column_is_numeric?(column_name) |
||||
# TODO RS: We want to leave out ids even though they are numeric |
||||
[:int, :float].include? column_type(column_name) |
||||
end |
||||
|
||||
def column_type(column_name) |
||||
if column_name =~ /cf_(.*)/ |
||||
CustomField.find($1).field_format.to_sym |
||||
else |
||||
column = WorkPackage.columns_hash[column_name] |
||||
column.nil? ? :none : column.type |
||||
end |
||||
end |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,4 @@ |
||||
|
||||
collection @groups => :groups |
||||
attributes :id, |
||||
:name |
@ -0,0 +1,36 @@ |
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2013 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. |
||||
#++ |
||||
|
||||
collection @available_columns => :available_columns |
||||
|
||||
node(:name) { |c| c[:name] } |
||||
node(:title) { |c| c[:title] } |
||||
node(:sortable) { |c| c[:sortable] } |
||||
node(:groupable) { |c| c[:groupable] } |
||||
node(:custom_field) { |c| c[:custom_field] } |
||||
node(:meta_data) { |c| c[:meta_data] } |
@ -0,0 +1,4 @@ |
||||
|
||||
collection @roles => :roles |
||||
attributes :id, |
||||
:name |
@ -0,0 +1,4 @@ |
||||
|
||||
collection @versions => :versions |
||||
attributes :id, |
||||
:name |
@ -0,0 +1,33 @@ |
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2013 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. |
||||
#++ |
||||
|
||||
object false |
||||
|
||||
node(:columns_data) { @columns_data } |
||||
|
||||
node(:columns_meta) { @columns_meta } |
@ -0,0 +1,31 @@ |
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2013 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. |
||||
#++ |
||||
|
||||
object false |
||||
|
||||
node(:column_sums) { @column_sums } |
@ -0,0 +1,62 @@ |
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2013 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. |
||||
#++ |
||||
|
||||
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]) |
||||
when IssuePriority |
||||
wp.send(column_name).as_json(only: [:id, :name]) |
||||
when Status |
||||
wp.send(column_name).as_json(only: [:id, :name]) |
||||
when User |
||||
wp.send(column_name).as_json(only: [:id, :firstname], methods: :name) |
||||
when Version |
||||
wp.send(column_name).as_json(only: [:id, :name]) |
||||
when WorkPackage |
||||
wp.send(column_name).as_json(only: [:id, :name]) |
||||
else |
||||
wp.send(column_name) |
||||
end |
||||
end |
||||
end |
||||
|
||||
node(:custom_values) do |wp| |
||||
wp.custom_values_display_data @custom_field_column_names |
||||
end |
||||
end |
||||
|
||||
if @display_meta |
||||
node(:meta) { @work_packages_meta_data } |
||||
end |
@ -1,3 +1,3 @@ |
||||
<span class="icon-context icon-button icon-{{iconName}}"> |
||||
<span class="hidden-for-sighted"></span> |
||||
<span class="icon-context icon-button icon-{{iconName}}" title="{{title}}"> |
||||
<span class="hidden-for-sighted">{{title}}</span> |
||||
</span> |
||||
|
@ -1,4 +1,4 @@ |
||||
<div ng-if="loading" |
||||
<div ng-if="isLoading" |
||||
id="ajax-indicator"> |
||||
<span>Loading...</span> |
||||
</div> |
||||
</div> |
||||
|
@ -0,0 +1,59 @@ |
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2014 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. |
||||
#++ |
||||
|
||||
require File.expand_path('../../../../../spec_helper', __FILE__) |
||||
|
||||
describe 'api/v3/groups/index.api.rabl' do |
||||
before do |
||||
params[:format] = 'json' |
||||
|
||||
assign(:groups, groups) |
||||
render |
||||
end |
||||
|
||||
subject { response.body } |
||||
|
||||
describe 'with no groups available' do |
||||
let(:groups) { [] } |
||||
|
||||
it { should have_json_path('groups') } |
||||
it { should have_json_size(0).at_path('groups') } |
||||
end |
||||
|
||||
describe 'with 2 groups available' do |
||||
let(:groups) { [ |
||||
FactoryGirl.build(:group), FactoryGirl.build(:group) |
||||
] } |
||||
|
||||
it { should have_json_path('groups') } |
||||
it { should have_json_size(2).at_path('groups') } |
||||
|
||||
it { should have_json_type(Object).at_path('groups/1') } |
||||
it { should have_json_path('groups/1/name') } |
||||
end |
||||
end |
@ -0,0 +1,89 @@ |
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2014 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. |
||||
#++ |
||||
|
||||
require File.expand_path('../../../../../spec_helper', __FILE__) |
||||
|
||||
describe 'api/v3/queries/available_columns.api.rabl' do |
||||
before do |
||||
params[:format] = 'json' |
||||
|
||||
assign(:available_columns, available_columns) |
||||
render |
||||
end |
||||
|
||||
subject { response.body } |
||||
|
||||
describe 'with no available columns' do |
||||
let(:available_columns) { [] } |
||||
|
||||
it { should have_json_path('available_columns') } |
||||
it { should have_json_size(0).at_path('available_columns') } |
||||
end |
||||
|
||||
describe 'with 2 available columns' do |
||||
let(:available_columns) { |
||||
[ |
||||
{ |
||||
name: "project", |
||||
title: "Project", |
||||
sortable: "projects.name", |
||||
groupable:"project", |
||||
custom_field: false, |
||||
meta_data: { |
||||
data_type: "object", |
||||
link: { |
||||
display: true, |
||||
model_type: "project" |
||||
} |
||||
} |
||||
}, { |
||||
name: "status", |
||||
title: "Status", |
||||
sortable: "statuses.name", |
||||
groupable:"status", |
||||
custom_field: false, |
||||
meta_data: { |
||||
data_type: "object", |
||||
link: { |
||||
display: false, |
||||
model_type: "project" |
||||
} |
||||
} |
||||
} |
||||
] |
||||
} |
||||
|
||||
it { should have_json_path('available_columns') } |
||||
it { should have_json_size(2).at_path('available_columns') } |
||||
|
||||
it { should have_json_type(FalseClass).at_path('available_columns/1/custom_field') } |
||||
it { should have_json_type(Object).at_path('available_columns/1/meta_data') } |
||||
it { should have_json_type(String).at_path('available_columns/1/meta_data/link/model_type') } |
||||
end |
||||
|
||||
end |
@ -0,0 +1,59 @@ |
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2014 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. |
||||
#++ |
||||
|
||||
require File.expand_path('../../../../../spec_helper', __FILE__) |
||||
|
||||
describe 'api/v3/roles/index.api.rabl' do |
||||
before do |
||||
params[:format] = 'json' |
||||
|
||||
assign(:roles, roles) |
||||
render |
||||
end |
||||
|
||||
subject { response.body } |
||||
|
||||
describe 'with no roles available' do |
||||
let(:roles) { [] } |
||||
|
||||
it { should have_json_path('roles') } |
||||
it { should have_json_size(0).at_path('roles') } |
||||
end |
||||
|
||||
describe 'with 2 roles available' do |
||||
let(:roles) { [ |
||||
FactoryGirl.build(:role), FactoryGirl.build(:role) |
||||
] } |
||||
|
||||
it { should have_json_path('roles') } |
||||
it { should have_json_size(2).at_path('roles') } |
||||
|
||||
it { should have_json_type(Object).at_path('roles/1') } |
||||
it { should have_json_path('roles/1/name') } |
||||
end |
||||
end |
@ -0,0 +1,59 @@ |
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2014 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. |
||||
#++ |
||||
|
||||
require File.expand_path('../../../../../spec_helper', __FILE__) |
||||
|
||||
describe 'api/v3/versions/index.api.rabl' do |
||||
before do |
||||
params[:format] = 'json' |
||||
|
||||
assign(:versions, versions) |
||||
render |
||||
end |
||||
|
||||
subject { response.body } |
||||
|
||||
describe 'with no versions available' do |
||||
let(:versions) { [] } |
||||
|
||||
it { should have_json_path('versions') } |
||||
it { should have_json_size(0).at_path('versions') } |
||||
end |
||||
|
||||
describe 'with 2 versions available' do |
||||
let(:versions) { [ |
||||
FactoryGirl.build(:version), FactoryGirl.build(:version) |
||||
] } |
||||
|
||||
it { should have_json_path('versions') } |
||||
it { should have_json_size(2).at_path('versions') } |
||||
|
||||
it { should have_json_type(Object).at_path('versions/1') } |
||||
it { should have_json_path('versions/1/name') } |
||||
end |
||||
end |
@ -0,0 +1,56 @@ |
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2014 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. |
||||
#++ |
||||
|
||||
require File.expand_path('../../../../../spec_helper', __FILE__) |
||||
|
||||
describe 'api/v3/work_packages/column_data.api.rabl' do |
||||
before do |
||||
params[:format] = 'json' |
||||
|
||||
assign(:columns_data, columns_data) |
||||
render |
||||
end |
||||
|
||||
subject { response.body } |
||||
|
||||
describe 'with no column data' do |
||||
let(:columns_data) { [] } |
||||
|
||||
it { should have_json_path('columns_data') } |
||||
it { should have_json_size(0).at_path('columns_data') } |
||||
end |
||||
|
||||
describe 'with column data' do |
||||
let(:columns_data) { [[{ id: 1, name: 'Dairy Queen' }, { id: 2, name: 'Baskin Robbins' }]] } |
||||
|
||||
it { should have_json_path('columns_data') } |
||||
it { should have_json_type(Array).at_path('columns_data') } |
||||
it { should have_json_type(Array).at_path('columns_data/0') } |
||||
it { should have_json_type(Object).at_path('columns_data/0/0') } |
||||
end |
||||
end |
@ -0,0 +1,57 @@ |
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2014 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. |
||||
#++ |
||||
|
||||
require File.expand_path('../../../../../spec_helper', __FILE__) |
||||
|
||||
describe 'api/v3/work_packages/column_sums.api.rabl' do |
||||
before do |
||||
params[:format] = 'json' |
||||
|
||||
assign(:column_sums, column_sums) |
||||
render |
||||
end |
||||
|
||||
subject { response.body } |
||||
|
||||
describe 'with no summed columns' do |
||||
let(:column_sums) { [] } |
||||
|
||||
it { should have_json_path('column_sums') } |
||||
it { should have_json_size(0).at_path('column_sums') } |
||||
end |
||||
|
||||
describe 'with 4 summed columns' do |
||||
let(:column_sums) { [45, 67, 12.99, 44444444444] } |
||||
|
||||
it { should have_json_path('column_sums') } |
||||
it { should have_json_size(4).at_path('column_sums') } |
||||
|
||||
it { should have_json_type(Float).at_path('column_sums/2') } |
||||
it { should have_json_type(Integer).at_path('column_sums/3') } |
||||
end |
||||
end |
@ -0,0 +1,83 @@ |
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2014 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. |
||||
#++ |
||||
|
||||
require File.expand_path('../../../../../spec_helper', __FILE__) |
||||
|
||||
describe 'api/v3/work_packages/index.api.rabl' do |
||||
before do |
||||
params[:format] = 'json' |
||||
|
||||
assign(:work_packages, work_packages) |
||||
assign(:column_names, column_names) |
||||
assign(:custom_field_column_names, custom_field_column_names) |
||||
render |
||||
end |
||||
|
||||
subject { response.body } |
||||
|
||||
describe 'with no work packages available' do |
||||
let(:work_packages) { [] } |
||||
let(:column_names) { [] } |
||||
let(:custom_field_column_names) { [] } |
||||
|
||||
it { should have_json_path('work_packages') } |
||||
it { should have_json_size(0).at_path('work_packages') } |
||||
end |
||||
|
||||
describe 'with 3 work packages but no columns' do |
||||
let(:work_packages) { [ |
||||
FactoryGirl.build(:work_package), |
||||
FactoryGirl.build(:work_package), |
||||
FactoryGirl.build(:work_package) |
||||
] } |
||||
let(:column_names) { [] } |
||||
let(:custom_field_column_names) { [] } |
||||
|
||||
it { should have_json_path('work_packages') } |
||||
it { should have_json_size(3).at_path('work_packages') } |
||||
|
||||
it { should have_json_type(Object).at_path('work_packages/2') } |
||||
end |
||||
|
||||
describe 'with 2 work packages and columns' do |
||||
let(:work_packages) { [ |
||||
FactoryGirl.build(:work_package), |
||||
FactoryGirl.build(:work_package) |
||||
] } |
||||
let(:column_names) { %w(subject description due_date) } |
||||
let(:custom_field_column_names) { [] } |
||||
|
||||
it { should have_json_path('work_packages') } |
||||
it { should have_json_size(2).at_path('work_packages') } |
||||
|
||||
it { should have_json_type(Object).at_path('work_packages/1') } |
||||
it { should have_json_path('work_packages/1/subject') } |
||||
it { should have_json_path('work_packages/1/description') } |
||||
it { should have_json_path('work_packages/1/due_date') } |
||||
end |
||||
end |
Loading…
Reference in new issue