Merge branch 'feature/ui-component-table-widgets-merged' into feature/ui-components-test-architecture-bower
commit
67ee568721
@ -0,0 +1,24 @@ |
||||
// TODO move to UI components
|
||||
angular.module('openproject.uiComponents') |
||||
|
||||
.directive('progressBar', [function() { |
||||
return { |
||||
restrict: 'EA', |
||||
replace: true, |
||||
scope: { |
||||
progress: '=', |
||||
width: '@', |
||||
legend: '@' |
||||
}, |
||||
templateUrl: '/templates/components/progress_bar.html', |
||||
link: function(scope) { |
||||
// apply defaults
|
||||
scope.progress = scope.progress || 0; |
||||
scope.width = scope.width || '100px'; |
||||
scope.legend = scope.legend || ''; |
||||
|
||||
scope.scaleLength = 100; |
||||
scope.progress = Math.round(scope.progress); |
||||
} |
||||
}; |
||||
}]); |
@ -1,52 +0,0 @@ |
||||
// TODO move to UI components
|
||||
angular.module('openproject.uiComponents') |
||||
|
||||
.directive('workPackageColumn', ['PathHelper', 'WorkPackagesHelper', function(PathHelper, WorkPackagesHelper){ |
||||
return { |
||||
restrict: 'EA', |
||||
replace: true, |
||||
scope: { |
||||
workPackage: '=', |
||||
column: '=' |
||||
}, |
||||
templateUrl: '/templates/components/work_package_column.html', |
||||
link: function(scope, element, attributes) { |
||||
var defaultText = ''; |
||||
var defaultType = 'text'; |
||||
|
||||
// Set text to be displayed
|
||||
scope.$watch('workPackage', updateColumnData, true); |
||||
|
||||
function updateColumnData() { |
||||
scope.displayText = WorkPackagesHelper.getColumnValue(scope.workPackage, scope.column) || defaultText; |
||||
scope.displayType = defaultType; |
||||
|
||||
// Example of how we can look to the provided meta data to format the column
|
||||
// This relies on the meta being sent from the server
|
||||
if (scope.column.meta_data.link.display) { |
||||
scope.displayType = 'link'; |
||||
scope.url = getLinkFor(scope.column.meta_data.link); |
||||
} |
||||
|
||||
} |
||||
|
||||
function getLinkFor(link_meta){ |
||||
switch (link_meta.model_type){ |
||||
case 'work_package': |
||||
url = PathHelper.workPackagePath(scope.workPackage.id); |
||||
break; |
||||
case 'user': |
||||
if (scope.workPackage[scope.column.name]) url = PathHelper.userPath(scope.workPackage[scope.column.name].id); |
||||
break; |
||||
case 'project': |
||||
if (scope.workPackage.project) url = PathHelper.projectPath(scope.workPackage.project.identifier); |
||||
break; |
||||
default: |
||||
url = ""; |
||||
}; |
||||
return url; |
||||
} |
||||
|
||||
} |
||||
}; |
||||
}]); |
@ -0,0 +1,73 @@ |
||||
// TODO move to UI components
|
||||
angular.module('openproject.workPackages.directives') |
||||
|
||||
.directive('workPackageColumn', ['PathHelper', 'WorkPackagesHelper', 'UserService', function(PathHelper, WorkPackagesHelper, UserService){ |
||||
return { |
||||
restrict: 'EA', |
||||
replace: true, |
||||
scope: { |
||||
workPackage: '=', |
||||
column: '=', |
||||
displayType: '@' |
||||
}, |
||||
templateUrl: '/templates/work_packages/work_package_column.html', |
||||
link: function(scope, element, attributes) { |
||||
scope.displayType = scope.displayType || 'text'; |
||||
|
||||
// custom display types
|
||||
if (scope.column.name === 'done_ratio') { |
||||
scope.displayType = 'progress_bar'; |
||||
} |
||||
|
||||
// Set text to be displayed
|
||||
scope.$watch('workPackage', setColumnData, true); |
||||
|
||||
function setColumnData() { |
||||
// retrieve column value from work package
|
||||
scope.displayText = WorkPackagesHelper.getFormattedColumnValue(scope.workPackage, scope.column) || ''; |
||||
|
||||
if (scope.column.meta_data.data_type === 'user') loadUserName(); |
||||
|
||||
// Example of how we can look to the provided meta data to format the column
|
||||
// This relies on the meta being sent from the server
|
||||
if (scope.column.meta_data.link.display) { |
||||
scope.displayType = 'link'; |
||||
scope.url = getLinkFor(scope.column.meta_data.link); |
||||
} |
||||
} |
||||
|
||||
function loadUserName() { |
||||
var userId = scope.displayText; |
||||
|
||||
if(userId) { |
||||
scope.user = UserService.registerUserId(userId); |
||||
|
||||
scope.$watch('user.name', function(userName) { |
||||
// triggered when user data is loaded
|
||||
// TODO replace watcher as soon as data is loaded via a promise chain
|
||||
scope.displayText = userName; |
||||
}); |
||||
} |
||||
} |
||||
|
||||
function getLinkFor(link_meta){ |
||||
if (link_meta.model_type === 'work_package') { |
||||
return PathHelper.workPackagePath(scope.workPackage.id); |
||||
} else if (scope.workPackage[scope.column.name]) { |
||||
switch (link_meta.model_type) { |
||||
case 'user': |
||||
return PathHelper.userPath(scope.workPackage[scope.column.name].id); |
||||
case 'version': |
||||
return PathHelper.versionPath(scope.workPackage[scope.column.name].id); |
||||
case 'project': |
||||
return PathHelper.projectPath(scope.workPackage.project.identifier); |
||||
default: |
||||
return ''; |
||||
} |
||||
|
||||
} |
||||
} |
||||
|
||||
} |
||||
}; |
||||
}]); |
@ -0,0 +1,18 @@ |
||||
// TODO move to UI components
|
||||
angular.module('openproject.helpers') |
||||
|
||||
.service('FunctionDecorators', ['$timeout', function($timeout) { |
||||
var currentRun; |
||||
|
||||
return { |
||||
withDelay: function(delay, callback, params) { |
||||
$timeout.cancel(currentRun); |
||||
|
||||
currentRun = $timeout(function() { |
||||
return callback.apply(this, params); |
||||
}, delay); |
||||
|
||||
return currentRun; |
||||
} |
||||
}; |
||||
}]); |
@ -0,0 +1,44 @@ |
||||
angular.module('openproject.services') |
||||
|
||||
.service('UserService', ['$http', 'PathHelper', 'FunctionDecorators', function($http, PathHelper, FunctionDecorators) { |
||||
var registeredUserIds = [], cachedUsers = {}; |
||||
|
||||
UserService = { |
||||
registerUserId: function(id) { |
||||
var user = cachedUsers[id]; |
||||
if (user) return user; |
||||
|
||||
registeredUserIds.push(id); |
||||
cachedUsers[id] = { name: '', firstname: '', lastname: '' }; // create an empty object and fill its values on load
|
||||
|
||||
FunctionDecorators.withDelay(10, UserService.loadRegisteredUsers); // HACK
|
||||
// TODO hook into a given promise chain to post-load user data, or if ngView is used trigger load on $viewContentLoaded
|
||||
|
||||
return cachedUsers[id]; |
||||
}, |
||||
|
||||
loadRegisteredUsers: function() { |
||||
if (registeredUserIds.length > 0) { |
||||
return $http.get(PathHelper.apiPrefix + PathHelper.usersPath(), { |
||||
params: { 'ids[]': registeredUserIds } |
||||
}).then(function(response){ |
||||
UserService.storeUsers(response.data.users); |
||||
return cachedUsers; |
||||
}); |
||||
} |
||||
}, |
||||
|
||||
storeUsers: function(users) { |
||||
// writes user data to object stubs providing a mechanism for wiring up user data to the scope
|
||||
angular.forEach(users, function(user) { |
||||
var cachedUser = cachedUsers[user.id]; |
||||
|
||||
cachedUser.firstname = user.firstname; |
||||
cachedUser.lastname = user.lastname; |
||||
cachedUser.name = user.name; |
||||
}); |
||||
} |
||||
}; |
||||
|
||||
return UserService; |
||||
}]); |
@ -0,0 +1,38 @@ |
||||
#-- encoding: UTF-8 |
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2014 the OpenProject Foundation (OPF) |
||||
# |
||||
# This program is free software; you can redistribute it and/or |
||||
# modify it under the terms of the GNU General Public License version 3. |
||||
# |
||||
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: |
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang |
||||
# Copyright (C) 2010-2013 the ChiliProject Team |
||||
# |
||||
# This program is free software; you can redistribute it and/or |
||||
# modify it under the terms of the GNU General Public License |
||||
# as published by the Free Software Foundation; either version 2 |
||||
# of the License, or (at your option) any later version. |
||||
# |
||||
# This program is distributed in the hope that it will be useful, |
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
# GNU General Public License for more details. |
||||
# |
||||
# You should have received a copy of the GNU General Public License |
||||
# along with this program; if not, write to the Free Software |
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||
# |
||||
# See doc/COPYRIGHT.rdoc for more details. |
||||
#++ |
||||
|
||||
class FixCustomizableJournalValueColumn < ActiveRecord::Migration |
||||
def up |
||||
change_column :customizable_journals, :value, :text |
||||
end |
||||
|
||||
def down |
||||
change_column :customizable_journals, :value, :string |
||||
end |
||||
end |
@ -0,0 +1,34 @@ |
||||
#-- encoding: UTF-8 |
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2014 the OpenProject Foundation (OPF) |
||||
# |
||||
# This program is free software; you can redistribute it and/or |
||||
# modify it under the terms of the GNU General Public License version 3. |
||||
# |
||||
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: |
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang |
||||
# Copyright (C) 2010-2013 the ChiliProject Team |
||||
# |
||||
# This program is free software; you can redistribute it and/or |
||||
# modify it under the terms of the GNU General Public License |
||||
# as published by the Free Software Foundation; either version 2 |
||||
# of the License, or (at your option) any later version. |
||||
# |
||||
# This program is distributed in the hope that it will be useful, |
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
# GNU General Public License for more details. |
||||
# |
||||
# You should have received a copy of the GNU General Public License |
||||
# along with this program; if not, write to the Free Software |
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||
# |
||||
# See doc/COPYRIGHT.rdoc for more details. |
||||
#++ |
||||
|
||||
class AddStickedOnFieldToMessages < ActiveRecord::Migration |
||||
def change |
||||
add_column :messages, :sticked_on, :datetime, default: nil, null: true |
||||
end |
||||
end |
@ -0,0 +1,11 @@ |
||||
<div> |
||||
<table class="progress" ng-style="{width: width}"> |
||||
<tbody> |
||||
<tr> |
||||
<td class="closed" ng-if="progress > 0" ng-style="{width: progress + '%'}"></td> |
||||
<td class="todo" ng-style="{width: (scaleLength - progress) + '%'}"></td> |
||||
</tr> |
||||
</tbody> |
||||
</table> |
||||
<p class="progress-bar-legend">{{legend}} Total progress</p> |
||||
</div> |
@ -1,6 +0,0 @@ |
||||
<span ng-switch="displayType"> |
||||
<span ng-switch-when="text"> |
||||
{{ displayText }} |
||||
</span> |
||||
<a ng-switch-when="link" href="{{ url }}">{{ displayText }}</a> |
||||
</span> |
@ -0,0 +1,12 @@ |
||||
<span ng-switch="displayType"> |
||||
<progress-bar ng-switch-when="progress_bar" |
||||
progress="displayText" |
||||
width="80px"> |
||||
</progress-bar> |
||||
|
||||
<a ng-switch-when="link" href="{{ url }}">{{ displayText }}</a> |
||||
|
||||
<span ng-switch-default> |
||||
{{ displayText }} |
||||
</span> |
||||
</span> |
Loading…
Reference in new issue