diff --git a/app/controllers/api/experimental/concerns/v3_naming.rb b/app/controllers/api/experimental/concerns/v3_naming.rb index 4e6bfb95d4..6bde94b1e7 100644 --- a/app/controllers/api/experimental/concerns/v3_naming.rb +++ b/app/controllers/api/experimental/concerns/v3_naming.rb @@ -57,18 +57,27 @@ module Api::Experimental::Concerns::V3Naming "#{v3_to_internal_name(criteria.first, append_id: false)}:#{criteria.last}" }.join(',') end if params[:sort] + params[:group_by] = params.delete(:groupBy) + params[:project_id] = params.delete(:projectId) + params[:display_sums] = params.delete(:displaySums) + params[:is_public] = params.delete(:isPublic) + params[:user_id] = params.delete(:userId) end def json_query_as_v3(json_query) - json_query['column_names'] = (json_query['column_names'] || []).map { |column| + json_query['columnNames'] = (json_query.delete('column_names') || [] ).map { |column| internal_to_v3_name(column) } - json_query['sort_criteria'] = (json_query['sort_criteria'] || []).map { |criteria| + json_query['sortCriteria'] = (json_query.delete('sort_criteria') || [] ).map { |criteria| [internal_to_v3_name(criteria.first), criteria.last] } - json_query['group_by'] = internal_to_v3_name(json_query['group_by']) + json_query['groupBy'] = internal_to_v3_name(json_query.delete('group_by')) + json_query['projectId'] = json_query.delete('project_id') + json_query['displaySums'] = json_query.delete('display_sums') + json_query['isPublic'] = json_query.delete('is_public') + json_query['userId'] = json_query.delete('user_id') json_query['filters'].each do |filter| filter[:name] = internal_to_v3_name(filter[:name]) diff --git a/frontend/app/components/api/api-work-packages/api-work-packages.service.ts b/frontend/app/components/api/api-work-packages/api-work-packages.service.ts index d20637397a..2383502829 100644 --- a/frontend/app/components/api/api-work-packages/api-work-packages.service.ts +++ b/frontend/app/components/api/api-work-packages/api-work-packages.service.ts @@ -36,8 +36,8 @@ export class ApiWorkPackagesService { public list(offset:number, pageSize:number, query:api.ex.Query) { var workPackages; - if (query.project_id) { - workPackages = this.apiV3.service('work_packages', this.apiV3.one('projects', query.project_id)); + if (query.projectId) { + workPackages = this.apiV3.service('work_packages', this.apiV3.one('projects', query.projectId)); } else { workPackages = this.apiV3.service('work_packages'); @@ -60,25 +60,16 @@ export class ApiWorkPackagesService { filters: [v3Filters] }; - if (query.group_by) { - params.groupBy = query.group_by; - } - if (query.groupBy) { params.groupBy = query.groupBy; } - // TODO: why is it display_sums sometimes and displaySums at other times - if (query.display_sums) { - params.showSums = query.display_sums; - } - if (query.displaySums) { params.showSums = query.displaySums; } - if (query.sort_criteria) { - params.sortBy = [query.sort_criteria]; + if (query.sortCriteria) { + params.sortBy = [query.sortCriteria]; } return params; diff --git a/frontend/app/components/query/query-service.service.test.js b/frontend/app/components/query/query-service.service.test.js index 1ccbeb64f4..7a6682c643 100644 --- a/frontend/app/components/query/query-service.service.test.js +++ b/frontend/app/components/query/query-service.service.test.js @@ -57,10 +57,10 @@ describe('QueryService', function() { beforeEach(function() { queryData = { - group_by: 'type', - display_sums: 1, + groupBy: 'type', + displaySums: 1, filters: { - type_id: { + type: { operator: '~', values: ['Bug', 'Feature'] } @@ -71,11 +71,11 @@ describe('QueryService', function() { }); it('should set query.groupBy', function() { - expect(query.groupBy).to.equal(queryData.group_by); + expect(query.groupBy).to.equal(queryData.groupBy); }); it('should set query.displaySums', function() { - expect(query.displaySums).to.equal(queryData.display_sums); + expect(query.displaySums).to.equal(queryData.displaySums); }); describe('filters', function() { @@ -92,7 +92,7 @@ describe('QueryService', function() { var spy; beforeEach(function() { spy = sinon.spy($rootScope, '$broadcast'); - queryData = { name: '_', 'project_id': 1 }; + queryData = { name: '_', 'projectId': 1 }; QueryService.initQuery(1, queryData); var path = PathHelper.apiProjectQueryPath(1, 1); $httpBackend.when('DELETE', new RegExp(path + '*')).respond(200, []); diff --git a/frontend/app/components/query/query-service.service.ts b/frontend/app/components/query/query-service.service.ts index 79fd969a2d..0a06fd05b2 100644 --- a/frontend/app/components/query/query-service.service.ts +++ b/frontend/app/components/query/query-service.service.ts @@ -61,20 +61,20 @@ function QueryService(Query, query = new Query({ id: queryId, name: queryData.name, - project_id: queryData.project_id, - displaySums: queryData.display_sums, - groupSums: queryData.group_sums, + projectId: queryData.projectId, + displaySums: queryData.displaySums, + groupSums: queryData.groupSums, sums: queryData.sums, columns: selectedColumns, - groupBy: queryData.group_by, - isPublic: queryData.is_public, + groupBy: queryData.groupBy, + isPublic: queryData.isPublic, exportFormats: exportFormats, starred: queryData.starred, links: queryData._links }); - query.setSortation(queryData.sort_criteria); + query.setSortation(queryData.sortCriteria); - QueryService.getAvailableFilters(query.project_id) + QueryService.getAvailableFilters(query.projectId) .then(function(availableFilters) { query.setAvailableWorkPackageFilters(availableFilters); if (query.isDefault()) { @@ -94,21 +94,21 @@ function QueryService(Query, updateQuery: function(values, afterUpdate) { var queryData = { }; - if(!!values.display_sums) { - queryData.displaySums = values.display_sums; + if(!!values.displaySums) { + queryData.displaySums = values.displaySums; } if(!!values.columns) { queryData.columns = values.columns; } - if(!!values.group_by) { - queryData.groupBy = values.group_by; + if(!!values.groupBy) { + queryData.groupBy = values.groupBy; } - if(!!values.sort_criteria) { - queryData.sortCriteria = values.sort_criteria; + if(!!values.sortCriteria) { + queryData.sortCriteria = values.sortCriteria; } query.update(queryData); - QueryService.getAvailableFilters(query.project_id) + QueryService.getAvailableFilters(query.projectId) .then(function(availableFilters) { query.setAvailableWorkPackageFilters(availableFilters); if(queryData.filters && queryData.filters.length) { @@ -335,11 +335,11 @@ function QueryService(Query, // synchronization saveQuery: function() { - var url = query.project_id ? PathHelper.apiProjectQueryPath(query.project_id, query.id) : PathHelper.apiQueryPath(query.id); + var url = query.projectId ? PathHelper.apiProjectQueryPath(query.projectId, query.id) : PathHelper.apiQueryPath(query.id); return QueryService.doQuery(url, query.toUpdateParams(), 'PUT', function(response) { query.dirty = false; - QueryService.fetchAvailableGroupedQueries(query.project_id); + QueryService.fetchAvailableGroupedQueries(query.projectId); return angular.extend(response.data, { status: { text: I18n.t('js.notice_successful_update') }} ); }); @@ -347,11 +347,11 @@ function QueryService(Query, saveQueryAs: function(name) { query.setName(name); - var url = query.project_id ? PathHelper.apiProjectQueriesPath(query.project_id) : PathHelper.apiQueriesPath(); + var url = query.projectId ? PathHelper.apiProjectQueriesPath(query.projectId) : PathHelper.apiQueriesPath(); return QueryService.doQuery(url, query.toParams(), 'POST', function(response){ query.save(response.data.query); - QueryService.fetchAvailableGroupedQueries(query.project_id); + QueryService.fetchAvailableGroupedQueries(query.projectId); // The starred-state does not get saved via the API. So we manually // set it, if the old query was starred. @@ -365,13 +365,13 @@ function QueryService(Query, deleteQuery: function() { var url; - if(_.isNull(query.project_id)) { + if(_.isNull(query.projectId)) { url = PathHelper.apiQueryPath(query.id); } else { - url = PathHelper.apiProjectQueryPath(query.project_id, query.id); + url = PathHelper.apiProjectQueryPath(query.projectId, query.id); } return QueryService.doQuery(url, query.toUpdateParams(), 'DELETE', function(response){ - QueryService.fetchAvailableGroupedQueries(query.project_id); + QueryService.fetchAvailableGroupedQueries(query.projectId); $rootScope.$broadcast('openproject.layout.removeMenuItem', { itemType: QUERY_MENU_ITEM_TYPE, @@ -382,8 +382,8 @@ function QueryService(Query, }, getQueryPath: function(query) { - if (query.project_id) { - return PathHelper.projectWorkPackagesPath(query.project_id) + '?query_id=' + query.id; + if (query.projectId) { + return PathHelper.projectWorkPackagesPath(query.projectId) + '?query_id=' + query.id; } else { return PathHelper.workPackagesPath() + '?query_id=' + query.id; } diff --git a/frontend/app/components/query/query.service.js b/frontend/app/components/query/query.service.js index 740d9e9053..936fbee3bb 100644 --- a/frontend/app/components/query/query.service.js +++ b/frontend/app/components/query/query.service.js @@ -62,11 +62,11 @@ function QueryConstructorService(Filter, Sortation, UrlParamsHelper, INITIALLY_S { 'f[]': this.getFilterNames(this.getActiveConfiguredFilters()), 'c[]': this.getParamColumns(), - 'group_by': this.groupBy, + 'groupBy': this.groupBy, 'sort': this.getEncodedSortation(), - 'display_sums': this.displaySums, + 'displaySums': this.displaySums, 'name': this.name, - 'is_public': this.isPublic, + 'isPublic': this.isPublic, 'accept_empty_query_fields': this.isDirty(), }].concat(this.getActiveConfiguredFilters().map(function(filter) { return filter.toParams(); @@ -78,14 +78,14 @@ function QueryConstructorService(Filter, Sortation, UrlParamsHelper, INITIALLY_S return angular.extend.apply(this, [ { 'id': this.id, - 'query_id': this.id, + 'queryId': this.id, 'f[]': this.getFilterNames(this.getActiveConfiguredFilters()), 'c[]': this.getParamColumns(), - 'group_by': this.groupBy, + 'groupBy': this.groupBy, 'sort': this.getEncodedSortation(), - 'display_sums': this.displaySums, + 'displaySums': this.displaySums, 'name': this.name, - 'is_public': this.isPublic, + 'isPublic': this.isPublic, 'accept_empty_query_fields': this.isDirty() }].concat(this.getActiveConfiguredFilters().map(function(filter) { return filter.toParams(); @@ -158,10 +158,10 @@ function QueryConstructorService(Filter, Sortation, UrlParamsHelper, INITIALLY_S setAvailableWorkPackageFilters: function(availableFilters) { this.availableWorkPackageFilters = availableFilters; - if (this.project_id){ - delete this.availableWorkPackageFilters["project_id"]; + if (this.projectId){ + delete this.availableWorkPackageFilters['project']; } else { - delete this.availableWorkPackageFilters["subproject_id"]; + delete this.availableWorkPackageFilters['subprojectId']; } // TODO RS: Need to assertain if there are any sub-projects and remove filter if not. // The project will have to be fetched prior to this. @@ -224,7 +224,7 @@ function QueryConstructorService(Filter, Sortation, UrlParamsHelper, INITIALLY_S * @returns {boolean} default */ isGlobal: function() { - return !this.project_id; + return !this.projectId; }, /** diff --git a/frontend/app/components/work-packages/work-package.service.js b/frontend/app/components/work-packages/work-package.service.js index 645b1e5519..a9a9c03bc7 100644 --- a/frontend/app/components/work-packages/work-package.service.js +++ b/frontend/app/components/work-packages/work-package.service.js @@ -184,25 +184,6 @@ function WorkPackageService($http, PathHelper, UrlParamsHelper, WorkPackagesHelp return WorkPackageService.doQuery(url, params); }, - // Note: Should this be on a project-service? - getWorkPackagesSums: function(projectIdentifier, query, columns){ - var columnNames = columns.map(function(column){ - return column.name; - }); - - if (projectIdentifier){ - var url = PathHelper.apiProjectWorkPackagesSumsPath(projectIdentifier); - } else { - var url = PathHelper.apiWorkPackagesSumsPath(); - } - - var params = angular.extend(query.toParams(), { - 'column_names[]': columnNames - }); - - return WorkPackageService.doQuery(url, params); - }, - loadWorkPackageForm: function(workPackage) { if (this.authorizedFor(workPackage, 'update')) { var options = { ajax: { diff --git a/frontend/app/helpers/url-params-helper.js b/frontend/app/helpers/url-params-helper.js index 59daa2524c..c5143008d5 100644 --- a/frontend/app/helpers/url-params-helper.js +++ b/frontend/app/helpers/url-params-helper.js @@ -148,8 +148,8 @@ module.exports = function(I18n, PaginationService, PathHelper) { buildQueryExportOptions: function(query){ var relativeUrl; - if (query.project_id) { - relativeUrl = PathHelper.projectWorkPackagesPath(query.project_id); + if (query.projectId) { + relativeUrl = PathHelper.projectWorkPackagesPath(query.projectId); } else { relativeUrl = PathHelper.workPackagesPath(); } diff --git a/frontend/app/typings/open-project.typings.ts b/frontend/app/typings/open-project.typings.ts index aac1b59c04..6a4ad44927 100644 --- a/frontend/app/typings/open-project.typings.ts +++ b/frontend/app/typings/open-project.typings.ts @@ -113,16 +113,16 @@ declare namespace api { interface Query { _links:any; id:number; - column_names; - display_sums:boolean; + columnNames; + displaySums:boolean; filters; - group_by:string; - is_public:boolean; + groupBy:string; + isPublic:boolean; name:string; - project_id; - sort_criteria; + projectId:number; + sortCriteria; starred:boolean; - user_id:number; + userId:number; } interface Meta { diff --git a/frontend/tests/integration/mocks/work-packages.json b/frontend/tests/integration/mocks/work-packages.json index 868f346211..adc0415632 100644 --- a/frontend/tests/integration/mocks/work-packages.json +++ b/frontend/tests/integration/mocks/work-packages.json @@ -320,8 +320,8 @@ "_links": { "create": "/api/experimental/queries" }, - "column_names": null, - "display_sums": null, + "columnNames": null, + "displaySums": null, "filters": [ { "name": "status_id", @@ -331,472 +331,14 @@ ] } ], - "group_by": null, + "groupBy": null, "id": null, - "is_public": false, + "isPublic": false, "name": "_", - "project_id": 14, - "sort_criteria": [], + "projectId": 14, + "sortCriteria": [], "starred": false, - "user_id": 0 - }, - "sums": [ - null, - null, - null, - null - ], - "total_entries": 10, - "work_package_count_by_group": null - }, - "work_packages": [ - { - "_actions": [ - "edit", - "move", - "copy", - "duplicate", - "delete" - ], - "_links": { - "copy": "/work_packages/move/new?copy=true&ids%5B%5D=16923", - "delete": "/work_packages/bulk?ids%5B%5D=16923&method=delete", - "duplicate": "/projects/openproject/work_packages/new?copy_from=16923", - "edit": "/work_packages/16923/edit", - "move": "/work_packages/move/new?ids%5B%5D=16923" - }, - "assigned_to": { - "firstname": "Karol", - "id": 9248, - "name": "Karol Skolar" - }, - "created_at": "2014-10-22T13:25:56Z", - "custom_values": [], - "id": 16923, - "parent_id": null, - "status": { - "id": 1, - "name": "new" - }, - "subject": "INSTALAR DIMMER OMAR", - "type": { - "color_id": 8, - "created_at": "11/13/2013/ 13:11 PM", - "id": 4, - "in_aggregation": true, - "is_default": false, - "is_in_roadmap": false, - "is_milestone": false, - "is_standard": false, - "name": "Task", - "position": 2, - "updated_at": "05/13/2014/ 12:10 PM" - }, - "updated_at": "2014-10-22T13:25:56Z" - }, - { - "_actions": [ - "edit", - "move", - "copy", - "duplicate", - "delete" - ], - "_links": { - "copy": "/work_packages/move/new?copy=true&ids%5B%5D=16923", - "delete": "/work_packages/bulk?ids%5B%5D=16923&method=delete", - "duplicate": "/projects/openproject/work_packages/new?copy_from=16923", - "edit": "/work_packages/16923/edit", - "move": "/work_packages/move/new?ids%5B%5D=16923" - }, - "assigned_to": { - "firstname": "Karol", - "id": 9248, - "name": "Karol Skolar" - }, - "created_at": "2014-10-22T13:25:56Z", - "custom_values": [], - "id": 820, - "parent_id": null, - "status": { - "id": 1, - "name": "new" - }, - "subject": "The other work package (820.json)", - "type": { - "color_id": 8, - "created_at": "11/13/2013/ 13:11 PM", - "id": 4, - "in_aggregation": true, - "is_default": false, - "is_in_roadmap": false, - "is_milestone": false, - "is_standard": false, - "name": "Task", - "position": 2, - "updated_at": "05/13/2014/ 12:10 PM" - }, - "updated_at": "2014-10-22T13:25:56Z" - }, - { - "_actions": [ - "edit", - "move", - "copy", - "duplicate", - "delete" - ], - "_links": { - "copy": "/work_packages/move/new?copy=true&ids%5B%5D=16914", - "delete": "/work_packages/bulk?ids%5B%5D=16914&method=delete", - "duplicate": "/projects/openproject/work_packages/new?copy_from=16914", - "edit": "/work_packages/16914/edit", - "move": "/work_packages/move/new?ids%5B%5D=16914" - }, - "assigned_to": null, - "created_at": "2014-10-22T09:50:40Z", - "custom_values": [], - "id": 16914, - "parent_id": null, - "status": { - "id": 1, - "name": "new" - }, - "subject": "ReffoTest", - "type": { - "color_id": 22, - "created_at": "02/19/2014/ 11:43 AM", - "id": 21, - "in_aggregation": true, - "is_default": false, - "is_in_roadmap": true, - "is_milestone": false, - "is_standard": false, - "name": "Idea", - "position": 7, - "updated_at": "04/22/2014/ 06:56 AM" - }, - "updated_at": "2014-10-22T10:08:35Z" - }, - { - "_actions": [ - "edit", - "move", - "copy", - "duplicate", - "delete" - ], - "_links": { - "copy": "/work_packages/move/new?copy=true&ids%5B%5D=16912", - "delete": "/work_packages/bulk?ids%5B%5D=16912&method=delete", - "duplicate": "/projects/openproject/work_packages/new?copy_from=16912", - "edit": "/work_packages/16912/edit", - "move": "/work_packages/move/new?ids%5B%5D=16912" - }, - "assigned_to": null, - "created_at": "2014-10-22T09:29:12Z", - "custom_values": [], - "id": 16912, - "parent_id": null, - "status": { - "id": 1, - "name": "new" - }, - "subject": "Tab order on 'New Work Package' page could be optimized", - "type": { - "color_id": 14, - "created_at": "11/13/2013/ 13:11 PM", - "id": 6, - "in_aggregation": true, - "is_default": false, - "is_in_roadmap": true, - "is_milestone": false, - "is_standard": false, - "name": "User Story", - "position": 5, - "updated_at": "05/13/2014/ 12:11 PM" - }, - "updated_at": "2014-10-22T09:29:12Z" - }, - { - "_actions": [ - "edit", - "move", - "copy", - "duplicate", - "delete" - ], - "_links": { - "copy": "/work_packages/move/new?copy=true&ids%5B%5D=16905", - "delete": "/work_packages/bulk?ids%5B%5D=16905&method=delete", - "duplicate": "/projects/openproject/work_packages/new?copy_from=16905", - "edit": "/work_packages/16905/edit", - "move": "/work_packages/move/new?ids%5B%5D=16905" - }, - "assigned_to": null, - "created_at": "2014-10-22T05:09:18Z", - "custom_values": [], - "id": 16905, - "parent_id": null, - "status": { - "id": 1, - "name": "new" - }, - "subject": "Rubber recycling in South Africa", - "type": { - "color_id": 22, - "created_at": "02/19/2014/ 11:43 AM", - "id": 21, - "in_aggregation": true, - "is_default": false, - "is_in_roadmap": true, - "is_milestone": false, - "is_standard": false, - "name": "Idea", - "position": 7, - "updated_at": "04/22/2014/ 06:56 AM" - }, - "updated_at": "2014-10-22T05:09:19Z" - }, - { - "_actions": [ - "edit", - "move", - "copy", - "duplicate", - "delete" - ], - "_links": { - "copy": "/work_packages/move/new?copy=true&ids%5B%5D=16904", - "delete": "/work_packages/bulk?ids%5B%5D=16904&method=delete", - "duplicate": "/projects/openproject/work_packages/new?copy_from=16904", - "edit": "/work_packages/16904/edit", - "move": "/work_packages/move/new?ids%5B%5D=16904" - }, - "assigned_to": null, - "created_at": "2014-10-21T20:55:10Z", - "custom_values": [], - "id": 16904, - "parent_id": null, - "status": { - "id": 1, - "name": "new" - }, - "subject": "Traject Sylvia van der Stam - Leliveld", - "type": { - "color_id": 8, - "created_at": "11/13/2013/ 13:11 PM", - "id": 4, - "in_aggregation": true, - "is_default": false, - "is_in_roadmap": false, - "is_milestone": false, - "is_standard": false, - "name": "Task", - "position": 2, - "updated_at": "05/13/2014/ 12:10 PM" - }, - "updated_at": "2014-10-21T20:55:11Z" - }, - { - "_actions": [ - "edit", - "move", - "copy", - "duplicate", - "delete" - ], - "_links": { - "copy": "/work_packages/move/new?copy=true&ids%5B%5D=16902", - "delete": "/work_packages/bulk?ids%5B%5D=16902&method=delete", - "duplicate": "/projects/openproject/work_packages/new?copy_from=16902", - "edit": "/work_packages/16902/edit", - "move": "/work_packages/move/new?ids%5B%5D=16902" - }, - "assigned_to": null, - "created_at": "2014-10-21T18:06:54Z", - "custom_values": [], - "id": 16902, - "parent_id": null, - "status": { - "id": 1, - "name": "new" - }, - "subject": "Parque T\u00e9cnol\u00f3gico", - "type": { - "color_id": 8, - "created_at": "11/13/2013/ 13:11 PM", - "id": 4, - "in_aggregation": true, - "is_default": false, - "is_in_roadmap": false, - "is_milestone": false, - "is_standard": false, - "name": "Task", - "position": 2, - "updated_at": "05/13/2014/ 12:10 PM" - }, - "updated_at": "2014-10-21T18:14:21Z" - }, - { - "_actions": [ - "edit", - "move", - "copy", - "duplicate", - "delete" - ], - "_links": { - "copy": "/work_packages/move/new?copy=true&ids%5B%5D=16899", - "delete": "/work_packages/bulk?ids%5B%5D=16899&method=delete", - "duplicate": "/projects/openproject/work_packages/new?copy_from=16899", - "edit": "/work_packages/16899/edit", - "move": "/work_packages/move/new?ids%5B%5D=16899" - }, - "assigned_to": null, - "created_at": "2014-10-21T15:30:28Z", - "custom_values": [], - "id": 16899, - "parent_id": null, - "status": { - "id": 1, - "name": "new" - }, - "subject": "PDF export fails if there is U+FFFD in issue data or journals", - "type": { - "color_id": 17, - "created_at": "11/13/2013/ 13:11 PM", - "id": 1, - "in_aggregation": true, - "is_default": false, - "is_in_roadmap": true, - "is_milestone": false, - "is_standard": false, - "name": "Bug", - "position": 4, - "updated_at": "05/13/2014/ 12:10 PM" - }, - "updated_at": "2014-10-21T15:31:25Z" - }, - { - "_actions": [ - "edit", - "move", - "copy", - "duplicate", - "delete" - ], - "_links": { - "copy": "/work_packages/move/new?copy=true&ids%5B%5D=16893", - "delete": "/work_packages/bulk?ids%5B%5D=16893&method=delete", - "duplicate": "/projects/openproject/work_packages/new?copy_from=16893", - "edit": "/work_packages/16893/edit", - "move": "/work_packages/move/new?ids%5B%5D=16893" - }, - "assigned_to": null, - "created_at": "2014-10-21T13:49:42Z", - "custom_values": [], - "id": 16893, - "parent_id": null, - "status": { - "id": 1, - "name": "new" - }, - "subject": "A thaliana", - "type": { - "color_id": 8, - "created_at": "11/13/2013/ 13:11 PM", - "id": 4, - "in_aggregation": true, - "is_default": false, - "is_in_roadmap": false, - "is_milestone": false, - "is_standard": false, - "name": "Task", - "position": 2, - "updated_at": "05/13/2014/ 12:10 PM" - }, - "updated_at": "2014-10-21T13:49:42Z" - }, - { - "_actions": [ - "edit", - "move", - "copy", - "duplicate", - "delete" - ], - "_links": { - "copy": "/work_packages/move/new?copy=true&ids%5B%5D=16879", - "delete": "/work_packages/bulk?ids%5B%5D=16879&method=delete", - "duplicate": "/projects/openproject/work_packages/new?copy_from=16879", - "edit": "/work_packages/16879/edit", - "move": "/work_packages/move/new?ids%5B%5D=16879" - }, - "assigned_to": null, - "created_at": "2014-10-20T15:03:40Z", - "custom_values": [], - "id": 16879, - "parent_id": null, - "status": { - "id": 1, - "name": "new" - }, - "subject": "500 on Workpackage update", - "type": { - "color_id": 17, - "created_at": "11/13/2013/ 13:11 PM", - "id": 1, - "in_aggregation": true, - "is_default": false, - "is_in_roadmap": true, - "is_milestone": false, - "is_standard": false, - "name": "Bug", - "position": 4, - "updated_at": "05/13/2014/ 12:10 PM" - }, - "updated_at": "2014-10-20T15:29:06Z" - }, - { - "_actions": [ - "edit", - "move", - "copy", - "duplicate", - "delete" - ], - "_links": { - "copy": "/work_packages/move/new?copy=true&ids%5B%5D=16877", - "delete": "/work_packages/bulk?ids%5B%5D=16877&method=delete", - "duplicate": "/projects/openproject/work_packages/new?copy_from=16877", - "edit": "/work_packages/16877/edit", - "move": "/work_packages/move/new?ids%5B%5D=16877" - }, - "assigned_to": null, - "created_at": "2014-10-20T14:33:15Z", - "custom_values": [], - "id": 16877, - "parent_id": null, - "status": { - "id": 7, - "name": "confirmed" - }, - "subject": "[Emails] In work package create / update, closed work packages are not striked through", - "type": { - "color_id": 17, - "created_at": "11/13/2013/ 13:11 PM", - "id": 1, - "in_aggregation": true, - "is_default": false, - "is_in_roadmap": true, - "is_milestone": false, - "is_standard": false, - "name": "Bug", - "position": 4, - "updated_at": "05/13/2014/ 12:10 PM" - }, - "updated_at": "2014-10-20T14:33:16Z" + "userId": 0 } - ] + } }