Merge branch 'dev' into feature/new-export-modal-icons

Signed-off-by: Alex Coles <alex@alexbcoles.com>

Conflicts:
	app/assets/fonts/openproject_icon/openproject-icon-font.eot
	app/assets/fonts/openproject_icon/openproject-icon-font.svg
	app/assets/fonts/openproject_icon/openproject-icon-font.ttf
	app/assets/fonts/openproject_icon/openproject-icon-font.woff
	app/assets/stylesheets/fonts/_openproject_icon_font.md
	app/assets/stylesheets/fonts/_openproject_icon_font.sass
pull/1446/head
Alex Coles 11 years ago
commit b2ff8f8586
  1. 2
      app/assets/javascripts/angular/controllers/dialogs/settings.js
  2. 7
      app/assets/javascripts/angular/controllers/work-packages-controller.js
  3. 72
      app/assets/javascripts/angular/directives/work_packages/column-context-menu-directive.js
  4. 33
      app/assets/javascripts/angular/directives/work_packages/sort-header-directive.js
  5. 106
      app/assets/javascripts/angular/directives/work_packages/work-package-context-menu-directive.js
  6. 2
      app/assets/javascripts/angular/directives/work_packages/work-packages-table-directive.js
  7. 4
      app/assets/javascripts/angular/helpers/components/work-packages-helper.js
  8. 5
      app/assets/javascripts/angular/models/query.js
  9. 6
      app/assets/javascripts/angular/openproject-app.js
  10. 9
      app/assets/javascripts/angular/services/query-service.js
  11. 131
      app/assets/javascripts/angular/ui_components/has-dropdown-menu-directive.js
  12. 85
      app/assets/javascripts/angular/work_packages/column-context-menu.js
  13. 117
      app/assets/javascripts/angular/work_packages/work-package-context-menu.js
  14. 2
      app/assets/javascripts/application.js.erb
  15. 2
      app/assets/javascripts/autocompleter.js
  16. 1
      app/assets/javascripts/contextual_fieldset.js
  17. 2
      app/assets/javascripts/findDomElement.js
  18. 3
      app/assets/javascripts/members_select_boxes.js
  19. 4
      app/assets/javascripts/repository_navigation.js
  20. 1
      app/assets/javascripts/select_list_move.js
  21. 13
      app/assets/javascripts/timelines_select_boxes.js
  22. 2
      app/assets/javascripts/work_packages.js.erb
  23. 2
      app/assets/stylesheets/content/_action_menu_main.sass
  24. 1
      app/assets/stylesheets/content/_context_menu.sass
  25. 34
      app/assets/stylesheets/content/_forms.sass
  26. 1
      app/assets/stylesheets/content/_legacy_actions.sass
  27. 3
      app/assets/stylesheets/content/_modal.sass
  28. 30
      app/assets/stylesheets/content/_wiki.sass
  29. 13
      app/assets/stylesheets/default/main.css.erb
  30. 4
      app/assets/stylesheets/fonts/_openproject_icon_font.md
  31. 26
      app/assets/stylesheets/fonts/_openproject_icon_font.sass
  32. 20
      app/assets/stylesheets/layout/_drop_down.sass
  33. 10
      app/assets/stylesheets/layout/_toolbar.css.sass
  34. 1
      app/controllers/api/v2/planning_element_journals_controller.rb
  35. 10
      app/controllers/api/v3/queries_controller.rb
  36. 9
      app/controllers/api/v3/work_packages_controller.rb
  37. 2
      app/controllers/boards_controller.rb
  38. 2
      app/controllers/copy_projects_controller.rb
  39. 142
      app/controllers/query_menu_items_controller.rb
  40. 1
      app/controllers/work_packages/moves_controller.rb
  41. 2
      app/helpers/application_helper.rb
  42. 2
      app/helpers/query_menu_items_helper.rb
  43. 1
      app/helpers/sort_helper.rb
  44. 6
      app/helpers/timelog_helper.rb
  45. 2
      app/models/board.rb
  46. 6
      app/models/group.rb
  47. 2
      app/models/group_user.rb
  48. 1
      app/models/issue_priority_custom_field.rb
  49. 2
      app/models/menu_items/wiki_menu_item.rb
  50. 2
      app/models/notifier.rb
  51. 1
      app/models/query_custom_field_column.rb
  52. 18
      app/models/setting.rb
  53. 1
      app/models/time_entry_activity_custom_field.rb
  54. 1
      app/models/time_entry_custom_field.rb
  55. 2
      app/models/token.rb
  56. 1
      app/models/user_custom_field.rb
  57. 2
      app/models/work_package.rb
  58. 2
      app/models/work_package/scheduling_rules.rb
  59. 2
      app/models/work_package/status_transitions.rb
  60. 1
      app/models/work_package_custom_field.rb
  61. 2
      app/services/reports/assignee_report.rb
  62. 2
      app/services/reports/author_report.rb
  63. 2
      app/services/reports/category_report.rb
  64. 2
      app/services/reports/priority_report.rb
  65. 8
      app/services/reports/report.rb
  66. 2
      app/services/reports/subproject_report.rb
  67. 1
      app/services/reports/type_report.rb
  68. 2
      app/services/reports/version_report.rb
  69. 4
      app/views/admin/plugins.html.erb
  70. 8
      app/views/admin/projects.html.erb
  71. 2
      app/views/api/v3/work_packages/index.api.rabl
  72. 1
      app/views/auth_sources/edit.html.erb
  73. 10
      app/views/auth_sources/index.html.erb
  74. 37
      app/views/common/_error_base.html.erb
  75. 12
      app/views/common/_validation_error.html.erb
  76. 4
      app/views/common/error.html.erb
  77. 2
      app/views/common/list_attachments.json.erb
  78. 2
      app/views/copy_projects/copy_settings/_block_checkbox.html.erb
  79. 6
      app/views/custom_fields/_form.html.erb
  80. 26
      app/views/groups/_memberships.html.erb
  81. 44
      app/views/groups/_users.html.erb
  82. 2
      app/views/layouts/admin.html.erb
  83. 1
      app/views/members/_autocomplete_for_member.html.erb
  84. 6
      app/views/members/autocomplete_for_member.json.erb
  85. 2
      app/views/messages/_form.html.erb
  86. 30
      app/views/my/page_layout.html.erb
  87. 2
      app/views/projects/form/attributes/_project_type_id.html.erb
  88. 22
      app/views/projects/settings/_boards.html.erb
  89. 20
      app/views/projects/settings/_categories.html.erb
  90. 2
      app/views/queries/_filters.html.erb
  91. 26
      app/views/repositories/committers.html.erb
  92. 6
      app/views/settings/_mail_handler.html.erb
  93. 4
      app/views/settings/_projects.html.erb
  94. 8
      app/views/settings/_repositories.html.erb
  95. 1
      app/views/time_entries/reports/show.html.erb
  96. 2
      app/views/timelines/_custom_fields.html.erb
  97. 1
      app/views/timelines/_timeline.html.erb
  98. 2
      app/views/timelog/edit.html.erb
  99. 14
      app/views/types/_form.html.erb
  100. 2
      app/views/user_mailer/work_package_added.html.erb
  101. Some files were not shown because too many files have changed in this diff Show More

@ -37,7 +37,7 @@ angular.module('openproject.workPackages.controllers')
}])
.controller('SettingsModalController', ['$scope', 'settingsModal', 'QueryService',
function($scope, settingsModal, QueryService) {
function($scope, settingsModal, QueryService) {
this.name = 'Settings';
this.closeMe = settingsModal.deactivate;
$scope.query = QueryService.getQuery();

@ -52,6 +52,8 @@ angular.module('openproject.workPackages.controllers')
// Setup
function initialSetup() {
$scope.query_id = null;
QueryService.resetAll();
setupPageParamsFromUrl($window.location);
initProject();
@ -176,8 +178,8 @@ angular.module('openproject.workPackages.controllers')
$scope.availableOptions = QueryService.getAvailableOptions(); // maybe generalize this approach
$scope.$watch('availableOptions.availableGroupedQueries', function(availableQueries) {
if (availableQueries) {
$scope.groups = [{ name: 'CUSTOM QUERIES', models: availableQueries['user_queries']},
{ name: 'GLOBAL QUERIES', models: availableQueries['queries']}];
$scope.groups = [{ name: 'GLOBAL QUERIES', models: availableQueries['queries']},
{ name: 'CUSTOM QUERIES', models: availableQueries['user_queries']}];
}
});
}
@ -237,7 +239,6 @@ angular.module('openproject.workPackages.controllers')
});
$rootScope.$on('queryResetRequired', function(event, message) {
$scope.query_id = null;
initialSetup();
});

@ -1,72 +0,0 @@
angular.module('openproject.workPackages.directives')
.directive('columnContextMenu', [
'ContextMenuService',
'I18n',
'QueryService',
'WorkPackagesTableHelper',
'WorkPackagesTableService',
function(ContextMenuService, I18n, QueryService, WorkPackagesTableHelper, WorkPackagesTableService) {
return {
restrict: 'EA',
replace: true,
scope: {},
templateUrl: '/templates/work_packages/column_context_menu.html',
link: function(scope, element, attrs) {
var contextMenuName = 'columnContextMenu';
// Wire up context menu handlers
ContextMenuService.registerMenuElement(contextMenuName, element);
scope.contextMenu = ContextMenuService.getContextMenu();
scope.$watch('contextMenu.opened', function(opened) {
scope.opened = opened && scope.contextMenu.targetMenu === contextMenuName;
});
scope.$watch('contextMenu.targetMenu', function(target) {
scope.opened = scope.contextMenu.opened && target === contextMenuName;
});
// shared context information
scope.$watch('contextMenu.context.column', function(column) {
scope.column = column;
scope.isGroupable = WorkPackagesTableService.isGroupable(scope.column);
});
scope.$watch('contextMenu.context.columns', function(columns) {
scope.columns = columns;
});
scope.I18n = I18n;
// context menu actions
scope.groupBy = function(columnName) {
QueryService.getQuery().groupBy = columnName;
};
scope.sortAscending = function(columnName) {
WorkPackagesTableService.sortBy(columnName, 'asc');
};
scope.sortDescending = function(columnName) {
WorkPackagesTableService.sortBy(columnName, 'desc');
};
scope.moveLeft = function(columnName) {
WorkPackagesTableHelper.moveColumnBy(scope.columns, columnName, -1);
};
scope.moveRight = function(columnName) {
WorkPackagesTableHelper.moveColumnBy(scope.columns, columnName, 1);
};
scope.hideColumn = function(columnName) {
ContextMenuService.close();
QueryService.hideColumns(new Array(columnName));
};
}
};
}]);

@ -28,12 +28,13 @@
angular.module('openproject.workPackages.directives')
.directive('sortHeader', ['I18n', function(I18n){
.directive('sortHeader', [
'I18n',
function(I18n){
return {
restrict: 'A',
templateUrl: '/templates/work_packages/sort_header.html',
transclude: true,
scope: {
query: '=',
headerName: '=',
@ -41,7 +42,8 @@ angular.module('openproject.workPackages.directives')
sortable: '=',
locale: '='
},
link: function(scope, element, attributes) {
require: 'hasDropdownMenu',
link: function(scope, element, attributes, dropdownMenuCtrl) {
scope.$watch('query.sortation.sortElements', function(sortElements){
var latestSortElement = sortElements[0];
@ -54,17 +56,6 @@ angular.module('openproject.workPackages.directives')
setFullTitle();
}, true);
scope.$watch('currentSortDirection', function(sort) {
element.toggleClass('active-column', !!sort);
});
scope.performSort = function(){
var targetSortation = scope.query.sortation.getTargetSortationOfHeader(scope.headerName);
scope.query.setSortation(targetSortation);
scope.currentSortDirection = scope.query.sortation.getDisplayedSortDirectionOfHeader(scope.headerName);
};
function setFullTitle() {
if(!scope.sortable) scope.fullTitle = '';
@ -72,9 +63,21 @@ angular.module('openproject.workPackages.directives')
var sortDirectionText = (scope.currentSortDirection == 'asc') ? I18n.t('js.label_ascending') : I18n.t('js.label_descending');
scope.fullTitle = sortDirectionText + " " + I18n.t('js.label_sorted_by') + ' \"' + scope.headerTitle + '\"';
} else {
scope.fullTitle = (I18n.t('js.label_sort_by') + ' \"' + scope.headerTitle + '\"');
scope.fullTitle = I18n.t('js.label_open_menu');
}
}
// active-column class setting
function setActiveColumnClass() {
element.toggleClass('active-column', !!scope.currentSortDirection || scope.dropDownMenuOpened);
}
scope.$watch(dropdownMenuCtrl.opened, function(opened) {
scope.dropDownMenuOpened = opened;
setActiveColumnClass();
});
scope.$watch('currentSortDirection', setActiveColumnClass);
}
};
}]);

@ -1,106 +0,0 @@
angular.module('openproject.workPackages.directives')
.directive('workPackageContextMenu', [
'ContextMenuService',
'WorkPackagesTableHelper',
'WorkPackageContextMenuHelper',
'WorkPackageService',
'WorkPackagesTableService',
'I18n',
'$window',
function(ContextMenuService, WorkPackagesTableHelper, WorkPackageContextMenuHelper, WorkPackageService, WorkPackagesTableService, I18n, $window) {
return {
restrict: 'EA',
replace: true,
scope: {},
templateUrl: '/templates/work_packages/work_package_context_menu.html',
link: function(scope, element, attrs) {
var contextMenuName = 'workPackageContextMenu';
scope.I18n = I18n;
scope.hideResourceActions = true;
// wire up context menu event handler
ContextMenuService.registerMenuElement(contextMenuName, element);
scope.contextMenu = ContextMenuService.getContextMenu();
scope.$watch('contextMenu.opened', function(opened) {
scope.opened = opened && scope.contextMenu.targetMenu === contextMenuName;
});
scope.$watch('contextMenu.targetMenu', function(target) {
scope.opened = scope.contextMenu.opened && target === contextMenuName;
});
scope.$watch('contextMenu.context.row', function(row) {
if (row && scope.contextMenu.targetMenu === contextMenuName) {
updateContextMenu(getWorkPackagesFromContext(scope.contextMenu.context));
}
});
scope.triggerContextMenuAction = function(action, link) {
if (action === 'delete') {
deleteSelectedWorkPackages();
} else {
$window.location.href = link;
}
};
function deleteSelectedWorkPackages() {
if (!deleteConfirmed()) return;
var rows = WorkPackagesTableHelper.getSelectedRows(scope.contextMenu.context.rows);
WorkPackageService.performBulkDelete(getWorkPackagesFromContext(scope.contextMenu.context))
.success(function(data, status) {
// TODO wire up to API and processs API response
scope.$emit('flashMessage', {
isError: false,
text: I18n.t('js.work_packages.message_successful_bulk_delete')
});
WorkPackagesTableService.removeRows(rows);
})
.error(function(data, status) {
// TODO wire up to API and processs API response
scope.$emit('flashMessage', {
isError: true,
text: I18n.t('js.work_packages.message_error_during_bulk_delete')
});
});
}
function deleteConfirmed() {
return $window.confirm(I18n.t('js.text_work_packages_destroy_confirmation'));
}
function updateContextMenu(workPackages) {
scope.permittedActions = WorkPackageContextMenuHelper.getPermittedActions(workPackages);
}
function getWorkPackagesFromSelectedRows(rows) {
var selectedRows = WorkPackagesTableHelper.getSelectedRows(rows);
return WorkPackagesTableHelper.getWorkPackagesFromRows(selectedRows);
}
function getWorkPackagesFromContext(context) {
if (!context.row) return [];
context.row.checked = true;
var workPackagefromContext = context.row.object;
var workPackagesfromSelectedRows = getWorkPackagesFromSelectedRows(context.rows);
if (workPackagesfromSelectedRows.length === 0) {
return [workPackagefromContext];
} else if (workPackagesfromSelectedRows.indexOf(workPackagefromContext) === -1) {
return [workPackagefromContext].concat(workPackagesfromSelectedRows);
} else {
return workPackagesfromSelectedRows;
}
}
}
};
}]);

@ -57,7 +57,7 @@ angular.module('openproject.workPackages.directives')
scope.I18n = I18n;
scope.workPackagesTableData = WorkPackagesTableService.getWorkPackagesTableData();
var topMenuHeight = document.getElementById('top-menu').getHeight() || 0;
var topMenuHeight = angular.element('#top-menu').prop('offsetHeight') || 0;
scope.adaptVerticalPosition = function(event) {
event.pageY -= topMenuHeight;
};

@ -97,9 +97,9 @@ angular.module('openproject.workPackages.helpers')
formatValue: function(value, dataType) {
switch(dataType) {
case 'datetime':
return dateFilter(WorkPackagesHelper.parseDateTime(value), 'medium');
return value ? dateFilter(WorkPackagesHelper.parseDateTime(value), 'medium') : '';
case 'date':
return dateFilter(value, 'mediumDate');
return value ? dateFilter(WorkPackagesHelper.parseDateTime(value), 'mediumDate') : '';
case 'currency':
return currencyFilter(value, 'EUR ');
default:

@ -185,10 +185,7 @@ angular.module('openproject.models')
var selectedColumns = this.columns.map(function(column) {
return column.name;
});
// To be able to group the work packages we need to add in the group by column if it is not already in the selected columns
if(selectedColumns.indexOf(this.groupBy) == -1){
selectedColumns.push(this.groupBy);
}
return selectedColumns;
},

@ -67,7 +67,8 @@ angular.module('openproject.workPackages', [
'openproject.workPackages.controllers',
'openproject.workPackages.filters',
'openproject.workPackages.directives',
'openproject.uiComponents'
'openproject.uiComponents',
'ng-context-menu'
]);
angular.module('openproject.workPackages.services', []);
angular.module('openproject.workPackages.helpers', [
@ -88,8 +89,7 @@ angular.module('openproject.workPackages.controllers', [
angular.module('openproject.workPackages.directives', [
'openproject.uiComponents',
'openproject.services',
'openproject.workPackages.services',
'ng-context-menu'
'openproject.workPackages.services'
]);
// messages

@ -90,6 +90,15 @@ angular.module('openproject.services')
query = null;
},
resetAll: function(){
QueryService.resetQuery();
availableOptions = {};
availableColumns = [],
availableUnusedColumns = [],
availableFilterValues = {},
availableFilters = {};
},
getQuery: function() {
return query;
},

@ -0,0 +1,131 @@
angular.module('openproject.uiComponents')
.directive('hasDropdownMenu', [
'$injector',
'$window',
'$parse',
function($injector, $window, $parse) {
function getCssPositionProperties(dropdown, trigger) {
var hOffset = 0,
vOffset = 0;
// Styling logic taken from jQuery-dropdown plugin: https://github.com/plapier/jquery-dropdown
// (dual MIT/GPL-Licensed)
// Position the dropdown relative-to-parent or relative-to-document
if (dropdown.hasClass('dropdown-relative')) {
return {
left: dropdown.hasClass('dropdown-anchor-right') ?
trigger.position().left - (dropdown.outerWidth(true) - trigger.outerWidth(true)) - parseInt(trigger.css('margin-right')) + hOffset :
trigger.position().left + parseInt(trigger.css('margin-left')) + hOffset,
top: trigger.position().top + trigger.outerHeight(true) - parseInt(trigger.css('margin-top')) + vOffset
};
} else {
return {
left: dropdown.hasClass('dropdown-anchor-right') ?
trigger.offset().left - (dropdown.outerWidth() - trigger.outerWidth()) + hOffset : trigger.offset().left + hOffset,
top: trigger.offset().top + trigger.outerHeight() + vOffset
};
}
}
return {
restrict: 'A',
controller: [function() {
var dropDownMenuOpened = false;
this.open = function() {
dropDownMenuOpened = true;
};
this.close = function() {
dropDownMenuOpened = false;
};
this.opened = function() {
return dropDownMenuOpened;
};
}],
link: function(scope, element, attrs, ctrl) {
var contextMenu = $injector.get(attrs.target),
locals = {},
win = angular.element($window),
menuElement,
triggerOnEvent = attrs.triggerOnEvent || 'click';
/* contextMenu is a mandatory attribute and used to bind a specific context
menu to the trigger event
triggerOnEvent allows for binding the event for opening the menu to "click" */
// prepare locals, these define properties to be passed on to the context menu scope
var localKeys = attrs.locals.split(',').map(function(local) {
return local.trim();
});
angular.forEach(localKeys, function(key) {
locals[key] = scope[key];
});
function toggle() {
active() ? close() : open();
}
function active() {
return contextMenu.active() && ctrl.opened();
}
function open() {
ctrl.open();
contextMenu.open(locals)
.then(function(menuElement) {
menuElement.css(getCssPositionProperties(menuElement, element));
});
}
function close() {
ctrl.close();
contextMenu.close();
}
element.bind(triggerOnEvent, function(event) {
event.preventDefault();
event.stopPropagation();
scope.$apply(function() {
toggle();
});
scope.$root.$broadcast('openproject.markDropdownsAsClosed', element);
});
scope.$on('openproject.markDropdownsAsClosed', function(event, target) {
if (element !== target && ctrl.opened()) {
scope.$apply(ctrl.close);
}
});
win.bind('keyup', function(event) {
if (contextMenu.active() && event.keyCode === 27) {
scope.$apply(function() {
close();
});
}
});
function handleWindowClickEvent(event) {
if (contextMenu.active() && event.button !== 2) {
scope.$apply(function() {
close();
});
}
}
// Firefox treats a right-click as a click and a contextmenu event while other browsers
// just treat it as a contextmenu event
win.bind('click', handleWindowClickEvent);
win.bind(triggerOnEvent, handleWindowClickEvent);
}
};
}]);

@ -0,0 +1,85 @@
//-- 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.
//++
angular.module('openproject.workPackages')
.factory('ColumnContextMenu', [
'ngContextMenu',
function(ngContextMenu) {
return ngContextMenu({
controller: 'ColumnContextMenuController',
controllerAs: 'contextMenu',
templateUrl: '/templates/work_packages/column_context_menu.html'
});
}])
.controller('ColumnContextMenuController', [
'$scope',
'ColumnContextMenu',
'I18n',
'QueryService',
'WorkPackagesTableHelper',
'WorkPackagesTableService',
'columnsModal',
function($scope, ColumnContextMenu, I18n, QueryService, WorkPackagesTableHelper, WorkPackagesTableService, columnsModal) {
$scope.I18n = I18n;
$scope.isGroupable = WorkPackagesTableService.isGroupable($scope.column);
// context menu actions
$scope.groupBy = function(columnName) {
QueryService.getQuery().groupBy = columnName;
};
$scope.sortAscending = function(columnName) {
WorkPackagesTableService.sortBy(columnName || 'id', 'asc');
};
$scope.sortDescending = function(columnName) {
WorkPackagesTableService.sortBy(columnName || 'id', 'desc');
};
$scope.moveLeft = function(columnName) {
WorkPackagesTableHelper.moveColumnBy($scope.columns, columnName, -1);
};
$scope.moveRight = function(columnName) {
WorkPackagesTableHelper.moveColumnBy($scope.columns, columnName, 1);
};
$scope.hideColumn = function(columnName) {
ColumnContextMenu.close();
QueryService.hideColumns(new Array(columnName));
};
$scope.insertColumns = function() {
columnsModal.activate();
};
}]);

@ -0,0 +1,117 @@
//-- 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.
//++
angular.module('openproject.workPackages')
.factory('WorkPackageContextMenu', [
'ngContextMenu',
function(ngContextMenu) {
return ngContextMenu({
controller: 'WorkPackageContextMenuController',
controllerAs: 'contextMenu',
templateUrl: '/templates/work_packages/work_package_context_menu.html'
});
}])
.controller('WorkPackageContextMenuController', [
'$scope',
'WorkPackagesTableHelper',
'WorkPackageContextMenuHelper',
'WorkPackageService',
'WorkPackagesTableService',
'I18n',
'$window',
function($scope, WorkPackagesTableHelper, WorkPackageContextMenuHelper, WorkPackageService, WorkPackagesTableService, I18n, $window) {
$scope.I18n = I18n;
$scope.hideResourceActions = true;
$scope.$watch('row', function() {
$scope.row.checked = true;
$scope.permittedActions = WorkPackageContextMenuHelper.getPermittedActions(getSelectedWorkPackages());
});
$scope.triggerContextMenuAction = function(action, link) {
if (action === 'delete') {
deleteSelectedWorkPackages();
} else {
$window.location.href = link;
}
};
function deleteSelectedWorkPackages() {
if (!deleteConfirmed()) return;
var rows = WorkPackagesTableHelper.getSelectedRows($scope.rows);
WorkPackageService.performBulkDelete(getSelectedWorkPackages())
.success(function(data, status) {
// TODO wire up to API and processs API response
$scope.$emit('flashMessage', {
isError: false,
text: I18n.t('js.work_packages.message_successful_bulk_delete')
});
WorkPackagesTableService.removeRows(rows);
})
.error(function(data, status) {
// TODO wire up to API and processs API response
$scope.$emit('flashMessage', {
isError: true,
text: I18n.t('js.work_packages.message_error_during_bulk_delete')
});
});
}
function deleteConfirmed() {
return $window.confirm(I18n.t('js.text_work_packages_destroy_confirmation'));
}
function getWorkPackagesFromSelectedRows() {
var selectedRows = WorkPackagesTableHelper.getSelectedRows($scope.rows);
return WorkPackagesTableHelper.getWorkPackagesFromRows(selectedRows);
}
function getSelectedWorkPackages() {
var workPackagefromContext = $scope.row.object;
var workPackagesfromSelectedRows = getWorkPackagesFromSelectedRows();
if (workPackagesfromSelectedRows.length === 0) {
return [workPackagefromContext];
} else if (workPackagesfromSelectedRows.indexOf(workPackagefromContext) === -1) {
return [workPackagefromContext].concat(workPackagesfromSelectedRows);
} else {
return workPackagesfromSelectedRows;
}
}
}]);

@ -66,7 +66,7 @@
//= require angular-truncate
//= require angular-feature-flags/dist/featureFlags.js
//= require ng-context-menu
//= require angular-context-menu
//= require openproject-ui_components/app/assets/javascripts/angular/ui-components-app
//= require ./angular/openproject-app

@ -223,4 +223,4 @@
callback(data);
}
};
}(jQuery));
}(jQuery));

@ -32,4 +32,3 @@ jQuery(document).ready(function($) {
event.stopPropagation();
});
});

@ -59,4 +59,4 @@
}
};
})( jQuery );
})( jQuery );

@ -53,7 +53,7 @@ jQuery(document).ready(function($) {
formatItemSelection = function (item) {
return item.name;
};
$("#members_add_form select.select2-select").each(function (ix, elem){
if ($(elem).hasClass("remote") || $(elem).attr("data-ajaxURL") !== undefined) {
// remote loading
@ -110,4 +110,3 @@ jQuery(document).ready(function($) {
memberstab.click(init_members_cb);
}
});

@ -27,7 +27,7 @@
//++
Event.observe(window,'load',function() {
/*
/*
If we're viewing a tag or branch, don't display it in the
revision box
*/
@ -37,7 +37,7 @@ Event.observe(window,'load',function() {
$('rev').setValue('');
}
/*
/*
Copy the branch/tag value into the revision box, then disable
the dropdowns before submitting the form
*/

@ -64,4 +64,3 @@ function moveOptionDown(selectionId) {
function selectAllOptions(id) {
jQuery("#" + id + " option").attr('selected',true);
}

@ -39,7 +39,7 @@ jQuery(document).ready(function($) {
$("#timeline_options_grouping_two_sort"),
$("#timeline_options_planning_element_time_relative_one_unit"),
$("#timeline_options_planning_element_time_relative_two_unit")
].each(function (item) {
].forEach(function (item) {
$("input[name='" + $(item).attr("name")+"']").remove();
$(item).select2({
@ -69,7 +69,7 @@ jQuery(document).ready(function($) {
$("#timeline_options_planning_element_responsibles"),
$("#timeline_options_planning_element_assignee"),
$("#timeline_options_grouping_two_selection")
].each(function (item) {
].forEach(function (item) {
$(item).autocomplete({ multiple: true,
ajax: {null_element: {id: -1, name: I18n.t("js.filter.noneElement")}}
});
@ -79,7 +79,7 @@ jQuery(document).ready(function($) {
$("#timeline_options_planning_element_types"),
$("#timeline_options_planning_element_time_types"),
$("#timeline_options_planning_element_status")
].each(function (item) {
].forEach(function (item) {
$(item).autocomplete({
multiple: true
});
@ -94,7 +94,7 @@ jQuery(document).ready(function($) {
[
$("#reporting_reporting_to_project_id"),
$("#project_association_select_project_b_id")
].each(function (item) {
].forEach(function (item) {
// Stuff borrowed from Core application.js Project Jump Box
$(item).autocomplete({
multiple: false,
@ -112,7 +112,7 @@ jQuery(document).ready(function($) {
[
$("#timeline_options_grouping_one_selection")
].each(function (item) {
].forEach(function (item) {
// Stuff borrowed from Core application.js Project Jump Box
$(item).autocomplete({
multiple: true,
@ -131,7 +131,7 @@ jQuery(document).ready(function($) {
[
$("#timeline_options_parents")
].each(function (item) {
].forEach(function (item) {
// Stuff borrowed from Core application.js Project Jump Box
$(item).autocomplete({
multiple: true,
@ -168,4 +168,3 @@ jQuery(document).ready(function($) {
field.closest("fieldset").removeClass('collapsed').children("div").show();
}
});

@ -35,7 +35,7 @@ var WorkPackage = WorkPackage || {};
var init;
init = function () {
$.ajaxAppend({
trigger: '.action_menu_specific .edit',
indicator_class: 'ajax-indicator',

@ -30,7 +30,6 @@
ul
list-style-type: none
margin: 0
width: 200px
border: 1px solid #dddddd
box-shadow: 1px 1px 4px #cccccc
@ -41,6 +40,7 @@
padding: 4px 13px 4px 10px
&:hover
background: #f0f0f0
cursor: pointer
&.has-no-icon
padding: 4px 10px 4px 35px
&.dropdown-divider

@ -37,6 +37,7 @@
#work-package-context-menu, #column-context-menu
&.action-menu
position: absolute
z-index: 1000
.hascontextmenu
cursor: context-menu

@ -172,17 +172,6 @@ fieldset
margin-left: 0
font-weight: normal
input[type=checkbox]
border: 0
clip: rect(0 0 0 0)
height: 18px
margin: 0 -18px -18px 0
overflow: hidden
padding: 0
position: absolute
width: 18px
opacity: 0.001
.checkbox-label
position: relative
display: inline-block
@ -190,6 +179,22 @@ input[type=checkbox]
line-height: 18px
user-select: none
input[type=checkbox]
border: 0
clip: rect(0 0 0 0)
height: 18px
margin: 0 -18px -18px 0
overflow: hidden
padding: 0
position: absolute
width: 18px
opacity: 0.001
\:checked + .styled-checkbox:after
opacity: 1
\:focus + .styled-checkbox:before
.styled-checkbox
display: inline-block
vertical-align: top
@ -222,10 +227,3 @@ input[type=checkbox]
border-top: none
border-right: none
@include transform(rotate(-50deg))
\:checked + .styled-checkbox:after
opacity: 1
\:focus + .styled-checkbox:before

@ -83,4 +83,3 @@ ul.legacy-actions-more
.message-reply-menu
@include contextual(-39px)

@ -77,7 +77,6 @@ $ng-modal-image-width: $ng-modal-image-height
#modal-sorting
min-width: 900px
.select2-container
@media(max-width: 1800px)
width: 280px
@ -108,4 +107,4 @@ ul.export-options
label
display: block

@ -28,6 +28,11 @@
@import global/all
div.wiki
font-size: 14px
line-height: 1.6em
h1, h2
margin: 1em 0 1em 0
table
border: 1px solid #505050
border-collapse: collapse
@ -57,7 +62,6 @@ div.wiki
margin-right: 12px
margin-left: 0
display: table
font-size: 0.8em
&.right
float: right
margin-left: 12px
@ -76,13 +80,22 @@ div.wiki
padding-left: 16px
li
list-style-type: none
ul
margin: 0
padding: 0
ol, ul
padding: 0 0 0 2em
margin: 0.3em 0
li
list-style-position: outside
margin: 0
li li
margin-left: 1.5em
ol li
list-style-type: decimal
ul li
list-style-type: disc
fieldset legend
font-weight: bold
font-size: 10px
@ -103,6 +116,8 @@ h1:hover, h2:hover, h3:hover
color: #ddd
.wiki
p
margin-bottom: 1em
p, span
&.see-also, &.caution, &.important, &.info, &.tip, &.note
display: block
@ -162,6 +177,9 @@ h1:hover, h2:hover, h3:hover
background: url(image-path('wiki_styles/note_small.png')) 5px 4px no-repeat #F5FFFA
border: 1px solid #C7CFCA
.wiki-content
width: 700px
.controller-wiki
#content
overflow: visible

@ -1028,16 +1028,10 @@ table.files {
#content blockquote, .wiki ol, .wiki ul {
padding-left: 22px;
}
.wiki p {
margin-bottom: 5px;
}
blockquote {
font-style: italic;
background: url(<%= asset_path 'blockquote-bg.png' %>) no-repeat 5px 3px;
}
.wiki ul li {
list-style: disc inside none;
}
.file-thumbs {
margin: 20px 0 0;
overflow: hidden;
@ -1434,11 +1428,6 @@ tr.time-entry {
display: none;
}
/* comments */
.wiki ol li {
list-style: decimal inside;
}
/* scm */
#content table .changeset td.id a:hover {
text-decoration: underline;
@ -1703,7 +1692,7 @@ content {
padding-bottom: 11px;
}
#history .journal, #content .wiki-content p, #content .wiki-content li {
#history .journal {
width: 700px;
}

@ -243,5 +243,9 @@
<i class="icon-page-csv"></i>
<i class="icon-page-xls"></i>
<i class="icon-page-atom"></i>
<i class="icon-sort-by"></i>
<i class="icon-group-by"></i>
<i class="icon-filter-big"></i>
<i class="icon-group-by2"></i>
<i class="icon-sort-by2"></i>
```

@ -97,7 +97,7 @@
font-size: 15px
line-height: 5px
vertical-align: -40%
@mixin icon-big-rules
padding: 0 0 0 0
font-size: 50px
@ -154,7 +154,7 @@
[data-icon-sub-menu]:before
content: attr(data-icon-sub-menu)
@include icon-sub-menu-rules
[data-icon-big]:before
content: attr(data-icon-big)
@include icon-big-rules
@ -201,7 +201,7 @@
// used for icons in workpackage table
.icon-table:before
@include icon-table-rules
// used for very big icons
.icon-big:before
@include icon-big-rules
@ -925,22 +925,34 @@ dt > .icon-wiki-page:before,
.icon-toggle:before
content: "\e0e3"
.icon-sort-by:before
content: "\e0e4"
.icon-group-by:before
content: "\e0e5"
.icon-filter-big:before
content: "\e0e6"
.icon-page-pdf:before
content: "\e0e9"
.icon-page-csv:before
content: "\e0ea"
.icon-filter-big:before
content: "\e0e6"
.icon-page-xls:before
content: "\e019"
.icon-page-atom:before
content: "\e0a5"
.icon-group-by2:before
content: "\e0e7"
.icon-sort-by2:before
content: "\e0e8"
/* remove once all menu items have an icon */
.no-icon
margin-left: 15px

@ -36,6 +36,9 @@
#settingsDropdown, #tasksDropdown
margin: 10px 0 0 0
#column-context-menu
margin: 55px 0 0 0
.dropdown
position: absolute
z-index: 9999999
@ -43,16 +46,16 @@
.dropdown .dropdown-menu,
.dropdown .dropdown-panel
min-width: 160px
min-width: 200px
max-width: 360px
list-style: none
background: #FFF
border: solid 1px #DDD
border: solid 1px rgba(0, 0, 0, .2)
border-radius: 0px
box-shadow: 0 5px 10px rgba(0, 0, 0, .2)
box-shadow: 1px 1px 4px #cccccc
overflow: visible
padding: 4px 0
padding: 3px 0
margin: 0
.dropdown .dropdown-panel
@ -104,11 +107,11 @@
.dropdown .dropdown-menu LI > A,
.dropdown .dropdown-menu LABEL
display: block
color: #555
color: $main_menu_font_color
text-decoration: none
line-height: 18px
padding: 3px 32px
padding: 4px 13px 4px 10px
white-space: nowrap
font-weight: normal
.dropdown .dropdown-menu LI > A:hover,
.dropdown .dropdown-menu LABEL:hover
@ -120,9 +123,8 @@
.dropdown LI > A.dropdown-menu-hasicons
display: block
color: #555
color: $main_menu_font_color
text-decoration: none
line-height: 18px
padding: 3px 10px
white-space: nowrap
@ -131,7 +133,7 @@
font-size: 1px
border-top: solid 1px #E5E5E5
padding: 0
margin: 4px 0
margin: 3px 0
/* Icon Examples - icons courtesy of http://p.yusukekamiyamane.com/ */
.dropdown.has-icons LI > A

@ -58,6 +58,10 @@
li
float: none
.dropdown-scrollable
overflow-y: auto
max-height: 500px
#querySelectDropdown
min-width: 250px
border: 1px solid #dddddd
@ -69,11 +73,11 @@
clear: both
width: 100%
display: block
ul.query-menu
ul.query-menu
width: 100%
margin: 0 0 10px 0
float: left
li
li
padding: 4px 25px
display: block
&:hover
@ -85,7 +89,7 @@
&:hover
text-decoration: none
.search-query-wrapper
padding: 15px
padding: 15px
input
margin: 0 auto
width: 100%

@ -110,23 +110,23 @@ module Api::V3
def setup_query_for_create
@query = Query.new params[:query] ? permitted_params.query : nil
@query.project = @project unless params[:query_is_for_all]
prepare_query @query
prepare_query
@query.user = User.current
end
def setup_existing_query
@query = Query.find(params[:id])
prepare_query(@query)
prepare_query
end
# Note: Not dry - lifted straight from old queries controller
def prepare_query(query)
def prepare_query
@query.is_public = false unless User.current.allowed_to?(:manage_public_queries, @project) || User.current.admin?
view_context.add_filter_from_params if params[:fields] || params[:f]
@query.group_by ||= params[:group_by]
@query.group_by = params[:group_by] if params[:group_by].present?
@query.sort_criteria = prepare_sort_criteria if params[:sort]
@query.project = nil if params[:query_is_for_all]
@query.display_sums ||= params[:display_sums].present?
@query.display_sums = params[:display_sums] if params[:display_sums].present?
@query.column_names = params[:c] if params[:c]
@query.column_names = nil if params[:default_columns]
@query.name = params[:name] if params[:name]

@ -51,7 +51,14 @@ module Api
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
@column_names = [:id] | @query.columns.map(&:name) - @custom_field_column_names
if !@query.group_by.blank?
if @query.group_by =~ /cf_(.*)/
@custom_field_column_names << @query.group_by
else
@column_names << @query.group_by.to_sym
end
end
# determine what actions may be performed
@allowed_statuses = @work_packages.map do |i|

@ -52,7 +52,7 @@ class BoardsController < ApplicationController
def show
sort_init 'updated_on', 'desc'
sort_update 'created_on' => "#{Message.table_name}.created_on",
sort_update 'created_on' => "#{Message.table_name}.created_on",
'replies' => "#{Message.table_name}.replies_count",
'updated_on' => "#{Message.table_name}.updated_on"

@ -94,4 +94,4 @@ class CopyProjectsController < ApplicationController
end
true
end
end
end

@ -28,75 +28,75 @@
#++
class QueryMenuItemsController < ApplicationController
before_filter :load_project_and_query
before_filter :authorize
def create
@query_menu_item = MenuItems::QueryMenuItem.find_or_initialize_by_name_and_navigatable_id normalized_query_name, @query.id, title: @query.name
if @query_menu_item.save
flash[:notice] = l(:notice_successful_create)
else
flash[:error] = l(:error_menu_item_not_created)
end
redirect_to query_path
end
def update
@query_menu_item = MenuItems::QueryMenuItem.find params[:id]
if @query_menu_item.update_attributes query_menu_item_params
flash[:notice] = l(:notice_successful_update)
else
flash[:error] = l(:error_menu_item_not_saved)
end
redirect_to query_path
end
def destroy
@query_menu_item = MenuItems::QueryMenuItem.find params[:id]
@query_menu_item.destroy
flash[:notice] = l(:notice_successful_delete)
redirect_to query_path
end
def edit
@query_menu_item = MenuItems::QueryMenuItem.find params[:id]
end
private
def load_project_and_query
@project = Project.find params[:project_id]
@query = Query.find params[:query_id]
end
def query_path
project_work_packages_path(@project, :query_id => @query.id)
end
def normalized_query_name
@query.name.parameterize.underscore
end
# inherit permissions from queries where create and update are performed bei new and edit actions
def authorize(ctrl = 'queries', action = params[:action], global = false)
action = case action
when 'create'
'new'
when 'update'
'edit'
else
action
end
super
end
def query_menu_item_params
params.require(:menu_items_query_menu_item).permit(:name, :title, :navigatable_id, :parent_id)
end
before_filter :load_project_and_query
before_filter :authorize
def create
@query_menu_item = MenuItems::QueryMenuItem.find_or_initialize_by_name_and_navigatable_id normalized_query_name, @query.id, title: @query.name
if @query_menu_item.save
flash[:notice] = l(:notice_successful_create)
else
flash[:error] = l(:error_menu_item_not_created)
end
redirect_to query_path
end
def update
@query_menu_item = MenuItems::QueryMenuItem.find params[:id]
if @query_menu_item.update_attributes query_menu_item_params
flash[:notice] = l(:notice_successful_update)
else
flash[:error] = l(:error_menu_item_not_saved)
end
redirect_to query_path
end
def destroy
@query_menu_item = MenuItems::QueryMenuItem.find params[:id]
@query_menu_item.destroy
flash[:notice] = l(:notice_successful_delete)
redirect_to query_path
end
def edit
@query_menu_item = MenuItems::QueryMenuItem.find params[:id]
end
private
def load_project_and_query
@project = Project.find params[:project_id]
@query = Query.find params[:query_id]
end
def query_path
project_work_packages_path(@project, :query_id => @query.id)
end
def normalized_query_name
@query.name.parameterize.underscore
end
# inherit permissions from queries where create and update are performed bei new and edit actions
def authorize(ctrl = 'queries', action = params[:action], global = false)
action = case action
when 'create'
'new'
when 'update'
'edit'
else
action
end
super
end
def query_menu_item_params
params.require(:menu_items_query_menu_item).permit(:name, :title, :navigatable_id, :parent_id)
end
end

@ -112,4 +112,3 @@ class WorkPackages::MovesController < ApplicationController
end
end

@ -227,7 +227,7 @@ module ApplicationHelper
def format_version_name(version)
if version.project == @project
h(version)
h(version)
else
h("#{version.project} - #{version}")
end

@ -31,4 +31,4 @@ module QueryMenuItemsHelper
def update_query_menu_item_path(project, query_menu_item)
query_menu_item.persisted? ? query_menu_item_path(project, query_menu_item.query, query_menu_item) : query_menu_items_path(project, query_menu_item.query)
end
end
end

@ -265,4 +265,3 @@ module SortHelper
content_tag('th', sort_link(column, caption, default_order, :lang => lang), options)
end
end

@ -67,10 +67,10 @@ module TimelogHelper
end
def select_hours(data, criteria, value)
if value.to_s.empty?
data.select {|row| row[criteria].blank? }
if value.to_s.empty?
data.select {|row| row[criteria].blank? }
else
data.select {|row| row[criteria].to_s == value.to_s}
data.select {|row| row[criteria].to_s == value.to_s}
end
end

@ -36,7 +36,7 @@ class Board < ActiveRecord::Base
belongs_to :last_message, :class_name => 'Message', :foreign_key => :last_message_id
acts_as_list :scope => :project_id
acts_as_watchable
attr_protected :project_id
validates_presence_of :name, :description

@ -39,7 +39,7 @@ class Group < Principal
before_destroy :remove_references_before_destroy
alias_attribute(:groupname, :lastname)
validates_presence_of :groupname
validate :uniqueness_of_groupname
@ -109,8 +109,8 @@ class Group < Principal
Journal::WorkPackageJournal.update_all({ :assigned_to_id => deleted_user.id },
{ :assigned_to_id => id })
end
def uniqueness_of_groupname
groups_with_name = Group.where("lastname = ? AND id <> ?", groupname, id ? id : 0).count
if groups_with_name > 0

@ -30,6 +30,6 @@
class GroupUser < ActiveRecord::Base
belongs_to :group
belongs_to :user
validates_presence_of :group, :user
end

@ -32,4 +32,3 @@ class IssuePriorityCustomField < CustomField
:enumeration_work_package_priorities
end
end

@ -55,4 +55,4 @@ class MenuItems::WikiMenuItem < MenuItem
def new_wiki_page=(value)
options[:new_wiki_page] = value
end
end
end

@ -31,7 +31,7 @@ module Notifier
def self.notify?(event)
notified_events.include?(event.to_s)
end
def self.notified_events
Setting.notified_events.to_a
end

@ -52,4 +52,3 @@ class QueryCustomFieldColumn < QueryColumn
cv && @cf.cast_value(cv.value)
end
end

@ -30,15 +30,15 @@
class Setting < ActiveRecord::Base
DATE_FORMATS = [
'%Y-%m-%d',
'%d/%m/%Y',
'%d.%m.%Y',
'%d-%m-%Y',
'%m/%d/%Y',
'%d %b %Y',
'%d %B %Y',
'%b %d, %Y',
'%B %d, %Y'
'%Y-%m-%d',
'%d/%m/%Y',
'%d.%m.%Y',
'%d-%m-%Y',
'%m/%d/%Y',
'%d %b %Y',
'%d %B %Y',
'%b %d, %Y',
'%B %d, %Y'
]
TIME_FORMATS = [

@ -32,4 +32,3 @@ class TimeEntryActivityCustomField < CustomField
:enumeration_activities
end
end

@ -32,4 +32,3 @@ class TimeEntryCustomField < CustomField
:label_spent_time
end
end

@ -30,7 +30,7 @@
class Token < ActiveRecord::Base
belongs_to :user
validates_uniqueness_of :value
#attr_protected :user_id
before_create :delete_previous_tokens

@ -32,4 +32,3 @@ class UserCustomField < CustomField
:label_user_plural
end
end

@ -106,7 +106,7 @@ class WorkPackage < ActiveRecord::Base
scope :with_author, lambda { |author|
{:conditions => {:author_id => author.id}}
}
# <<< issues.rb <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
after_initialize :set_default_values

@ -64,4 +64,4 @@ module WorkPackage::SchedulingRules
1
end
end
end
end

@ -56,4 +56,4 @@ module WorkPackage::StatusTransitions
end
false
end
end
end

@ -38,4 +38,3 @@ class WorkPackageCustomField < CustomField
:label_work_package_plural
end
end

@ -49,4 +49,4 @@ class Reports::AssigneeReport < Reports::Report
@title ||= WorkPackage.human_attribute_name(:assigned_to)
end
end
end

@ -48,4 +48,4 @@ class Reports::AuthorReport < Reports::Report
def title
@title ||= WorkPackage.human_attribute_name(:author)
end
end
end

@ -48,4 +48,4 @@ class Reports::CategoryReport < Reports::Report
def title
@title ||= WorkPackage.human_attribute_name(:category)
end
end
end

@ -48,4 +48,4 @@ class Reports::PriorityReport < Reports::Report
def title
@title ||= WorkPackage.human_attribute_name(:priority)
end
end
end

@ -63,11 +63,3 @@ class Reports::Report
end
end

@ -48,4 +48,4 @@ class Reports::SubprojectReport < Reports::Report
def title
l(:label_subproject_plural)
end
end
end

@ -50,4 +50,3 @@ class Reports::TypeReport < Reports::Report
end
end

@ -49,4 +49,4 @@ class Reports::VersionReport < Reports::Report
@title ||= WorkPackage.human_attribute_name(:version)
end
end
end

@ -37,8 +37,8 @@ See doc/COPYRIGHT.rdoc for more details.
<tr class="<%= cycle('odd', 'even') %>">
<td><span class="name"><%=h plugin.name %></span>
<%= content_tag('span', h(plugin.description), :class => 'description') unless plugin.description.blank? %>
<%= content_tag('span', link_to(h(plugin.url), plugin.url), :class => 'url') unless plugin.url.blank? %>
</td>
<%= content_tag('span', link_to(h(plugin.url), plugin.url), :class => 'url') unless plugin.url.blank? %>
</td>
<td class="author"><%= plugin.author_url.blank? ? h(plugin.author) : link_to(h(plugin.author), plugin.author_url) %></td>
<td class="version"><%=h plugin.version %></td>
<td class="configure"><%= link_to(l(:button_configure), :controller => '/settings', :action => 'plugin', :id => plugin.id) if plugin.configurable? %></td>

@ -28,7 +28,7 @@ See doc/COPYRIGHT.rdoc for more details.
++#%>
<div id="admin-index">
<%= render :partial => 'no_data' if @no_configuration_data %>
<%= render :partial => 'no_data' if @no_configuration_data %>
</div>
<% content_for :action_menu_specific do %>
@ -64,9 +64,9 @@ See doc/COPYRIGHT.rdoc for more details.
<tbody>
<% project_tree(@projects) do |project, level| %>
<tr class="<%= cycle("odd", "even") %> <%= project.css_classes %> <%= level > 0 ? "idnt idnt-#{level}" : nil %>">
<td class="name"><span><%= link_to project, settings_project_path(project), :title => project.short_description %></span></td>
<td align="center"><%= checked_image project.is_public? %></td>
<td align="center"><%= format_date(project.created_on) %></td>
<td class="name"><span><%= link_to project, settings_project_path(project), :title => project.short_description %></span></td>
<td align="center"><%= checked_image project.is_public? %></td>
<td align="center"><%= format_date(project.created_on) %></td>
<td class="buttons">
<%= link_to(l(:button_archive),
archive_project_path(project, :status => params[:status]),

@ -45,7 +45,7 @@ child @work_packages => :work_packages do
when Version
wp.send(column_name).as_json(only: [:id, :name])
when WorkPackage
wp.send(column_name).as_json(only: [:id, :name])
wp.send(column_name).as_json(only: [:id, :subject])
else
wp.send(column_name)
end

@ -35,4 +35,3 @@ See doc/COPYRIGHT.rdoc for more details.
<%= render :partial => 'form', :locals => { :f => f } %>
<%= submit_tag l(:button_save) %>
<% end %>

@ -39,11 +39,11 @@ See doc/COPYRIGHT.rdoc for more details.
<table class="list">
<thead><tr>
<th><%= AuthSource.human_attribute_name(:name) %></th>
<th><%= AuthSource.human_attribute_name(:type) %></th>
<th><%= AuthSource.human_attribute_name(:host) %></th>
<th><%= l(:label_user_plural)%></th>
<th></th>
<th><%= AuthSource.human_attribute_name(:name) %></th>
<th><%= AuthSource.human_attribute_name(:type) %></th>
<th><%= AuthSource.human_attribute_name(:host) %></th>
<th><%= l(:label_user_plural)%></th>
<th></th>
</tr></thead>
<tbody>
<% for source in @auth_sources %>

@ -0,0 +1,37 @@
<%#-- 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.
++#%>
<div class="errorExplanation" id="errorExplanation" role="alert">
<% if content_for?(:error_details) %>
<h2><%= error_message %></h2>
<%= content_for :error_details %>
<% else %>
<%= error_message %>
<% end %>
</div>

@ -27,12 +27,18 @@ See doc/COPYRIGHT.rdoc for more details.
++#%>
<div class="errorExplanation" id="errorExplanation" role="alert">
<h2><%= l("activerecord.errors.template.header.#{(error_messages.count == 1) ? 'one' : 'other'}", count: error_messages.count, model: object_name) %></h2>
<% error_message = l("activerecord.errors.template.header.#{(error_messages.count == 1) ? 'one' : 'other'}",
count: error_messages.count,
model: object_name)
%>
<% content_for :error_details do %>
<p><%= l("errors.header_invalid_fields") %></p>
<ul>
<% error_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<%= render partial: "common/error_base", locals: { error_message: error_message } %>

@ -28,8 +28,8 @@ See doc/COPYRIGHT.rdoc for more details.
++#%>
<h2><%=h @status %></h2>
<p id="errorExplanation"><%=h @message %></p>
<%= render partial: "common/error_base", locals: { error_message: (h @message) } %>
<%= call_hook(:view_common_error_details, { params: params, project: ((defined? @project) ? @project : nil) }) %>
<p><a href="javascript:history.back()">Back</a></p>
<% html_title h(@status) %>

@ -34,4 +34,4 @@ See doc/COPYRIGHT.rdoc for more details.
:url => url_for(:controller => '/attachments', :action => 'show', :id => a, :filename => a.filename),
:is_image => !!a.image? # doing the !! as image? for whatever reason returns null or a number
}
}.to_json.html_safe %>
}.to_json.html_safe %>

@ -31,4 +31,4 @@ See doc/COPYRIGHT.rdoc for more details.
<%= check_box_tag 'only[]', name, checked, :id => "only_#{name}" %>
<%= "#{label} (#{count})" %>
</label>
<% end %>
<% end %>

@ -95,14 +95,14 @@ function toggle_custom_field_format() {
if (p_searchable) Element.hide(p_searchable.parentNode);
hide_and_disable(p_values);
break;
case "user":
case "user":
case "version":
Element.hide(p_length.parentNode);
Element.hide(p_regexp.parentNode);
if (p_searchable) Element.hide(p_searchable.parentNode);
hide_and_disable(p_values);
Element.hide(p_default_value);
break;
break;
default:
Element.show(p_length.parentNode);
Element.show(p_regexp.parentNode);
@ -206,7 +206,7 @@ jQuery(".locale_selector").each(function (index) {
<%= check_box_tag "custom_field[type_ids][]", type.id, (@custom_field.types.include? type), :id => "custom_field_type_ids_#{type.id}" %>
<%= content_tag :label, (type.is_standard) ? l(:label_custom_field_default_type) : h(type), :class => "no-css", :for => "custom_field_type_ids_#{type.id}" %>
<% end %>
<%= hidden_field_tag "custom_field[type_ids][]", '' %>
<%= hidden_field_tag "custom_field[type_ids][]", '' %>
</fieldset>
&nbsp;
<p><%= f.check_box :is_required %></p>

@ -33,16 +33,16 @@ See doc/COPYRIGHT.rdoc for more details.
<div class="splitcontentleft">
<% if @group.memberships.any? %>
<table class="list memberships">
<thead><tr>
<th><%= Project.model_name.human %></th>
<th><%= l(:label_role_plural) %></th>
<th style="width:15%"></th>
</tr></thead>
<tbody>
<% @group.memberships.each do |membership| %>
<% next if membership.new_record? %>
<tr id="member-<%= membership.id %>" class="<%= cycle 'odd', 'even' %> class">
<td class="project"><%=h membership.project %></td>
<thead><tr>
<th><%= Project.model_name.human %></th>
<th><%= l(:label_role_plural) %></th>
<th style="width:15%"></th>
</tr></thead>
<tbody>
<% @group.memberships.each do |membership| %>
<% next if membership.new_record? %>
<tr id="member-<%= membership.id %>" class="<%= cycle 'odd', 'even' %> class">
<td class="project"><%=h membership.project %></td>
<td class="roles">
<span id="member-<%= membership.id %>-roles"><%=h membership.roles.sort.collect(&:to_s).join(', ') %></span>
<%= form_tag(membership_of_group_path(@group, membership),
@ -50,7 +50,7 @@ See doc/COPYRIGHT.rdoc for more details.
:remote => true,
:id => "member-#{membership.id}-roles-form",
:style => 'display:none;') do %>
<p><% roles.each do |role| %>
<p><% roles.each do |role| %>
<label><%= check_box_tag 'membership[role_ids][]', role.id, membership.roles.include?(role) %> <%=h role %></label><br />
<% end %></p>
<p><%= submit_tag l(:button_change) %>
@ -64,8 +64,8 @@ See doc/COPYRIGHT.rdoc for more details.
:remote => true,
:class => 'icon icon-delete' %>
</td>
</tr>
</tbody>
</tr>
</tbody>
<% end; reset_cycle %>
</table>
<% else %>

@ -29,28 +29,28 @@ See doc/COPYRIGHT.rdoc for more details.
<div class="splitcontentleft">
<% if @group.users.any? %>
<table class="list users">
<thead><tr>
<th><%= User.model_name.human %></th>
<th style="width:15%"></th>
</tr></thead>
<tbody>
<% @group.users.sort.each do |user| %>
<tr id="user-<%= user.id %>" class="<%= cycle 'odd', 'even' %>">
<td class="user"><%= link_to_user user %></td>
<td class="buttons">
<table class="list users">
<thead><tr>
<th><%= User.model_name.human %></th>
<th style="width:15%"></th>
</tr></thead>
<tbody>
<% @group.users.sort.each do |user| %>
<tr id="user-<%= user.id %>" class="<%= cycle 'odd', 'even' %>">
<td class="user"><%= link_to_user user %></td>
<td class="buttons">
<%= link_to l(:button_delete), member_of_group_path(@group, user),
:method => :delete,
:remote => :true,
:class => 'icon icon-delete' %>
</td>
</tr>
<% end %>
</tbody>
</table>
</td>
</tr>
<% end %>
</tbody>
</table>
<% else %>
<p class="nodata"><%= l(:label_no_data) %></p>
<p class="nodata"><%= l(:label_no_data) %></p>
<% end %>
</div>
@ -60,8 +60,8 @@ See doc/COPYRIGHT.rdoc for more details.
<%= form_tag(members_of_group_path(@group), :method => :post, :remote => true) do |f| %>
<fieldset><legend><%=l(:label_user_new)%></legend>
<p><%= label_tag "user_search", l(:label_user_search) %><%= text_field_tag 'user_search', nil %></p>
<%= observe_field(:user_search,
<p><%= label_tag "user_search", l(:label_user_search) %><%= text_field_tag 'user_search', nil %></p>
<%= observe_field(:user_search,
:frequency => 0.5,
:update => :users,
:url => { :controller => '/groups', :action => 'autocomplete_for_user', :id => @group },
@ -69,12 +69,12 @@ See doc/COPYRIGHT.rdoc for more details.
:method => :get)
%>
<div id="users">
<%= principals_check_box_tags 'user_ids[]', users %>
</div>
<div id="users">
<%= principals_check_box_tags 'user_ids[]', users %>
</div>
<p><%= submit_tag l(:button_add) %></p>
</fieldset>
</fieldset>
<% end %>
<% end %>

@ -31,7 +31,7 @@ See doc/COPYRIGHT.rdoc for more details.
default_breadcrumb) %>
<% @page_header_title = l(:label_administration) %>
<% content_for :main_menu do %>
<%= render :partial => 'admin/menu' %>
<%= render :partial => 'admin/menu' %>
<% end %>
<%= render :file => "layouts/base" %>

@ -56,4 +56,3 @@ See doc/COPYRIGHT.rdoc for more details.
</div>
<p><%= submit_tag l(:button_add), :id => 'member-add-submit' %></p>
<% end %>

@ -31,12 +31,12 @@ See doc/COPYRIGHT.rdoc for more details.
"results":
{
"items":[
<% @principals.each_with_index do |principal, ix| %>
<% @principals.each_with_index do |principal, ix| %>
{
"id": <%= principal.id.to_json.html_safe %>,
"name": <%= principal.name.to_json.html_safe %>
} <%= "," unless ix == @principals.length - 1 %>
<% end %> ],
} <%= "," unless ix == @principals.length - 1 %>
<% end %> ],
"total": <%= @total ? @total : @principals.size %>,
"more": <%= @more ? @more : 0 %>
}

@ -46,7 +46,7 @@ See doc/COPYRIGHT.rdoc for more details.
</p>
<% if !replying && !@message.new_record? && User.current.allowed_to?(:edit_messages, @project) %>
<p><label><%= Board.name.humanize %></label><br />
<p><label><%= Board.name.humanize %></label><br />
<%= f.select :board_id, @project.boards.collect {|b| [b.name, b.id]} %></p>
<% end %>

@ -34,9 +34,9 @@ function recreateSortables() {
Sortable.destroy('list-left');
Sortable.destroy('list-right');
Sortable.create("list-top", {constraint:false, containment:['list-top','list-left','list-right'], dropOnEmpty:true, handle:'handle', onUpdate:function(){new Ajax.Request('<%= url_for(:controller => '/my', :action => 'order_blocks', :group => 'top') %>', {asynchronous:true, evalScripts:true, parameters:Sortable.serialize("list-top")})}, only:'mypage-box', tag:'div'})
Sortable.create("list-left", {constraint:false, containment:['list-top','list-left','list-right'], dropOnEmpty:true, handle:'handle', onUpdate:function(){new Ajax.Request('<%= url_for(:controller => '/my', :action => 'order_blocks', :group => 'left') %>', {asynchronous:true, evalScripts:true, parameters:Sortable.serialize("list-left")})}, only:'mypage-box', tag:'div'})
Sortable.create("list-right", {constraint:false, containment:['list-top','list-left','list-right'], dropOnEmpty:true, handle:'handle', onUpdate:function(){new Ajax.Request('<%= url_for(:controller => '/my', :action => 'order_blocks', :group => 'right') %>', {asynchronous:true, evalScripts:true, parameters:Sortable.serialize("list-right")})}, only:'mypage-box', tag:'div'})
Sortable.create("list-top", {constraint:false, containment:['list-top','list-left','list-right'], dropOnEmpty:true, handle:'handle', onUpdate:function(){new Ajax.Request('<%= url_for(:controller => '/my', :action => 'order_blocks', :group => 'top') %>', {asynchronous:true, evalScripts:true, parameters:Sortable.serialize("list-top")})}, only:'mypage-box', tag:'div'})
Sortable.create("list-left", {constraint:false, containment:['list-top','list-left','list-right'], dropOnEmpty:true, handle:'handle', onUpdate:function(){new Ajax.Request('<%= url_for(:controller => '/my', :action => 'order_blocks', :group => 'left') %>', {asynchronous:true, evalScripts:true, parameters:Sortable.serialize("list-left")})}, only:'mypage-box', tag:'div'})
Sortable.create("list-right", {constraint:false, containment:['list-top','list-left','list-right'], dropOnEmpty:true, handle:'handle', onUpdate:function(){new Ajax.Request('<%= url_for(:controller => '/my', :action => 'order_blocks', :group => 'right') %>', {asynchronous:true, evalScripts:true, parameters:Sortable.serialize("list-right")})}, only:'mypage-box', tag:'div'})
}
function updateSelect() {
@ -87,24 +87,24 @@ function removeBlock(block) {
<%= render :partial => 'layouts/action_menu_specific' %>
<div id="list-top" class="block-receiver">
<% @blocks['top'].each do |b|
next unless MyController.available_blocks.keys.include? b %>
<%= render :partial => 'block', :locals => {:user => @user, :block_name => b} %>
<% end if @blocks['top'] %>
<% @blocks['top'].each do |b|
next unless MyController.available_blocks.keys.include? b %>
<%= render :partial => 'block', :locals => {:user => @user, :block_name => b} %>
<% end if @blocks['top'] %>
</div>
<div id="list-left" class="splitcontentleft block-receiver">
<% @blocks['left'].each do |b|
next unless MyController.available_blocks.keys.include? b %>
<%= render :partial => 'block', :locals => {:user => @user, :block_name => b} %>
<% end if @blocks['left'] %>
<% @blocks['left'].each do |b|
next unless MyController.available_blocks.keys.include? b %>
<%= render :partial => 'block', :locals => {:user => @user, :block_name => b} %>
<% end if @blocks['left'] %>
</div>
<div id="list-right" class="splitcontentright block-receiver">
<% @blocks['right'].each do |b|
next unless MyController.available_blocks.keys.include? b %>
<%= render :partial => 'block', :locals => {:user => @user, :block_name => b} %>
<% end if @blocks['right'] %>
<% @blocks['right'].each do |b|
next unless MyController.available_blocks.keys.include? b %>
<%= render :partial => 'block', :locals => {:user => @user, :block_name => b} %>
<% end if @blocks['right'] %>
</div>
<%= sortable_element 'list-top',

@ -27,4 +27,4 @@ See doc/COPYRIGHT.rdoc for more details.
++#%>
<p><%= form.select :project_type_id, options_for_project_types, :include_blank => true %></p>
<p><%= form.select :project_type_id, options_for_project_types, :include_blank => true %></p>

@ -29,16 +29,16 @@ See doc/COPYRIGHT.rdoc for more details.
<% if @project.boards.any? %>
<table class="list">
<thead><tr>
<th><%= Board.model_name.human %></th>
<th><%= Board.human_attribute_name(:description) %></th>
<th></th>
<th></th>
</tr></thead>
<tbody>
<thead><tr>
<th><%= Board.model_name.human %></th>
<th><%= Board.human_attribute_name(:description) %></th>
<th></th>
<th></th>
</tr></thead>
<tbody>
<% @project.boards.each do |board|
next if board.new_record? %>
<tr class="<%= cycle 'odd', 'even' %>">
next if board.new_record? %>
<tr class="<%= cycle 'odd', 'even' %>">
<td><%=h board.name %></td>
<td><%=h board.description %></td>
<td class="small-icons" align="center">
@ -50,9 +50,9 @@ See doc/COPYRIGHT.rdoc for more details.
<%= link_to_if_authorized l(:button_edit), {:controller => '/boards', :action => 'edit', :project_id => @project, :id => board}, :class => 'icon icon-edit' %>
<%= link_to_if_authorized l(:button_delete), {:controller => '/boards', :action => 'destroy', :project_id => @project, :id => board}, :confirm => l(:text_are_you_sure), :method => :delete, :class => 'icon icon-delete' %>
</td>
</tr>
</tr>
<% end %>
</tbody>
</tbody>
</table>
<% else %>
<p class="nodata"><%= l(:label_no_data) %></p>

@ -29,15 +29,15 @@ See doc/COPYRIGHT.rdoc for more details.
<% if @project.categories.any? %>
<table class="list">
<thead><tr>
<th><%= Category.model_name.human %></th>
<th><%= Category.human_attribute_name(:assigned_to) %></th>
<th></th>
</tr></thead>
<tbody>
<thead><tr>
<th><%= Category.model_name.human %></th>
<th><%= Category.human_attribute_name(:assigned_to) %></th>
<th></th>
</tr></thead>
<tbody>
<% for category in @project.categories %>
<% unless category.new_record? %>
<tr class="<%= cycle 'odd', 'even' %>">
<% unless category.new_record? %>
<tr class="<%= cycle 'odd', 'even' %>">
<td><%=h(category.name) %></td>
<td><%=h(category.assigned_to.name) if category.assigned_to %></td>
<td class="buttons">
@ -50,8 +50,8 @@ See doc/COPYRIGHT.rdoc for more details.
:confirm => l(:text_are_you_sure),
:class => 'icon icon-delete' %>
</td>
</tr>
<% end %>
</tr>
<% end %>
<% end %>
</tbody>
</table>

@ -52,7 +52,7 @@ function toggle_filter(field) {
if (check_box.checked) {
Element.show("operators_" + field);
Form.Element.enable("operators_" + field);
Form.Element.enable("operators_" + field);
Form.Element.enable("values_" + field);
toggle_operator(field);
} else {

@ -38,26 +38,26 @@ See doc/COPYRIGHT.rdoc for more details.
<%= form_tag({}) do %>
<table class="list">
<thead>
<tr>
<th><%= User.human_attribute_name(:login) %></th>
<th><%= User.model_name.human %></th>
</tr>
<tr>
<th><%= User.human_attribute_name(:login) %></th>
<th><%= User.model_name.human %></th>
</tr>
</thead>
<tbody>
<% i = 0 -%>
<% @committers.each do |committer, user_id| -%>
<tr class="<%= cycle 'odd', 'even' %>">
<td><%=h committer %></td>
<td>
<%= hidden_field_tag "committers[#{i}][]", committer %>
<%= select_tag "committers[#{i}][]", content_tag('option', "-- #{l :actionview_instancetag_blank_option} --", :value => '') + options_from_collection_for_select(@users, 'id', 'name', user_id.to_i) %>
</td>
</tr>
<% i += 1 -%>
<tr class="<%= cycle 'odd', 'even' %>">
<td><%=h committer %></td>
<td>
<%= hidden_field_tag "committers[#{i}][]", committer %>
<%= select_tag "committers[#{i}][]", content_tag('option', "-- #{l :actionview_instancetag_blank_option} --", :value => '') + options_from_collection_for_select(@users, 'id', 'name', user_id.to_i) %>
</td>
</tr>
<% i += 1 -%>
<% end -%>
</tbody>
</table>
<p><%= submit_tag(l(:button_update)) %></p>
<% end %>
<% end %>
<% end %>

@ -38,11 +38,11 @@ See doc/COPYRIGHT.rdoc for more details.
<div class="box tabular settings">
<p><%= setting_check_box :mail_handler_api_enabled,
:onclick => "if (this.checked) { Form.Element.enable('settings_mail_handler_api_key'); } else { Form.Element.disable('settings_mail_handler_api_key'); }"%></p>
:onclick => "if (this.checked) { Form.Element.enable('settings_mail_handler_api_key'); } else { Form.Element.disable('settings_mail_handler_api_key'); }"%></p>
<p><%= setting_text_field :mail_handler_api_key, :size => 30,
:id => 'settings_mail_handler_api_key',
:disabled => !Setting.mail_handler_api_enabled? %>
:id => 'settings_mail_handler_api_key',
:disabled => !Setting.mail_handler_api_enabled? %>
<%= link_to_function l(:label_generate_key), "if ($('settings_mail_handler_api_key').disabled == false) { $('settings_mail_handler_api_key').value = randomKey(20) }" %>
</p>
</div>

@ -38,8 +38,8 @@ See doc/COPYRIGHT.rdoc for more details.
<p><%= setting_check_box :sequential_project_identifiers %></p>
<p><%= setting_select :new_project_user_role_id,
Role.find_all_givable.collect {|r| [r.name, r.id.to_s]},
:blank => "--- #{l(:actionview_instancetag_blank_option)} ---" %></p>
Role.find_all_givable.collect {|r| [r.name, r.id.to_s]},
:blank => "--- #{l(:actionview_instancetag_blank_option)} ---" %></p>
</div>
<%= submit_tag l(:button_save) %>

@ -33,12 +33,12 @@ See doc/COPYRIGHT.rdoc for more details.
<p><%= setting_check_box :autofetch_changesets %></p>
<p><%= setting_check_box :sys_api_enabled,
:onclick => "if (this.checked) { Form.Element.enable('settings_sys_api_key'); } else { Form.Element.disable('settings_sys_api_key'); }" %></p>
:onclick => "if (this.checked) { Form.Element.enable('settings_sys_api_key'); } else { Form.Element.disable('settings_sys_api_key'); }" %></p>
<p><%= setting_text_field :sys_api_key, :size => 30,
:id => 'settings_sys_api_key',
:disabled => !Setting.sys_api_enabled?,
:label => :setting_mail_handler_api_key %>
:id => 'settings_sys_api_key',
:disabled => !Setting.sys_api_enabled?,
:label => :setting_mail_handler_api_key %>
<%= link_to_function l(:label_generate_key), "if ($('settings_sys_api_key').disabled == false) { $('settings_sys_api_key').value = randomKey(20) }" %>
</p>

@ -102,4 +102,3 @@ See doc/COPYRIGHT.rdoc for more details.
<% end %>
<% html_title l(:label_spent_time), l(:label_report) %>

@ -60,4 +60,4 @@ custom_fields.each do |custom_field|
<%
end
end
%>
%>

@ -67,4 +67,3 @@ See doc/COPYRIGHT.rdoc for more details.
<% @timeline_header_included = true %>
<% end %>
<% end %>

@ -40,7 +40,7 @@ See doc/COPYRIGHT.rdoc for more details.
<p><%= f.text_field :comments, :size => 100 %></p>
<p><%= f.select :activity_id, activity_collection_for_select_options(@time_entry), :required => true %></p>
<% @time_entry.custom_field_values.each do |value| %>
<p><%= custom_field_tag_with_label :time_entry, value %></p>
<p><%= custom_field_tag_with_label :time_entry, value %></p>
<% end %>
<%= call_hook(:view_timelog_edit_form_bottom, { :time_entry => @time_entry, :form => f }) %>
</div>

@ -41,13 +41,13 @@ See doc/COPYRIGHT.rdoc for more details.
<% if WorkPackageCustomField.all.any? %>
<p>
<label><%= l(:label_custom_field_plural) %></label>
<% WorkPackageCustomField.all.each do |field| %>
<label class="block">
<%= check_box_tag 'type[custom_field_ids][]',field.id, @type.custom_fields.include?(field) %>
<%= field.name %>
</label>
<% end %>
<label><%= l(:label_custom_field_plural) %></label>
<% WorkPackageCustomField.all.each do |field| %>
<label class="block">
<%= check_box_tag 'type[custom_field_ids][]',field.id, @type.custom_fields.include?(field) %>
<%= field.name %>
</label>
<% end %>
</p>
<%= hidden_field_tag 'type[custom_field_ids][]', '' %>
<% end %>

@ -30,5 +30,3 @@ See doc/COPYRIGHT.rdoc for more details.
<%= t(:text_work_package_added, :id => "##{@issue.id}", :author => @issue.author) %>
<hr />
<%= render :partial => 'issue_details', :locals => { :issue => @issue } %>

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save