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
|
// TODO move to UI components
|
||||||
angular.module('openproject.uiComponents') |
angular.module('openproject.uiComponents') |
||||||
|
|
||||||
.directive('iconWrapper', ['I18n', function(I18n){ |
.directive('iconWrapper', [function(){ |
||||||
return { |
return { |
||||||
restrict: 'EA', |
restrict: 'EA', |
||||||
replace: true, |
replace: true, |
||||||
scope: { iconName: '@', title: '=iconTitle' }, |
scope: { iconName: '@', title: '@iconTitle' }, |
||||||
templateUrl: '/templates/components/icon_wrapper.html' |
templateUrl: '/templates/components/icon_wrapper.html' |
||||||
}; |
}; |
||||||
}]); |
}]); |
||||||
|
@ -1,22 +1,28 @@ |
|||||||
// TODO move to UI components
|
// TODO move to UI components
|
||||||
angular.module('openproject.uiComponents') |
angular.module('openproject.uiComponents') |
||||||
|
|
||||||
.directive('toggledMultiselect', ['WorkPackagesHelper', function(WorkPackagesHelper){ |
.directive('toggledMultiselect', ['WorkPackagesHelper', 'I18n', function(WorkPackagesHelper, I18n){ |
||||||
return { |
return { |
||||||
restrict: 'EA', |
restrict: 'EA', |
||||||
replace: true, |
replace: true, |
||||||
scope: { |
scope: { |
||||||
name: '=', |
name: '=', |
||||||
values: '=', |
values: '=', |
||||||
availableFilterValues: '=', |
availableOptions: '=' |
||||||
}, |
}, |
||||||
templateUrl: '/templates/components/toggled_multiselect.html', |
templateUrl: '/templates/components/toggled_multiselect.html', |
||||||
link: function(scope, element, attributes){ |
link: function(scope, element, attributes){ |
||||||
|
scope.I18n = I18n; |
||||||
|
|
||||||
scope.toggleMultiselect = function(){ |
scope.toggleMultiselect = function(){ |
||||||
scope.isMultiselect = !scope.isMultiselect; |
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="icon-context icon-button icon-{{iconName}}" title="{{title}}"> |
||||||
<span class="hidden-for-sighted"></span> |
<span class="hidden-for-sighted">{{title}}</span> |
||||||
</span> |
</span> |
||||||
|
@ -1,4 +1,4 @@ |
|||||||
<div ng-if="loading" |
<div ng-if="isLoading" |
||||||
id="ajax-indicator"> |
id="ajax-indicator"> |
||||||
<span>Loading...</span> |
<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