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.sasspull/1446/head
commit
b2ff8f8586
@ -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)); |
||||
}; |
||||
} |
||||
}; |
||||
}]); |
@ -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; |
||||
} |
||||
} |
||||
|
||||
} |
||||
}; |
||||
}]); |
@ -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; |
||||
} |
||||
} |
||||
|
||||
}]); |
@ -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> |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue