OpenProject is the leading open source project management software.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
openproject/frontend/app/work_packages/controllers/details-tab-overview-contro...

342 lines
11 KiB

//-- copyright
// OpenProject is a project management system.
// Copyright (C) 2012-2015 the OpenProject Foundation (OPF)
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License version 3.
//
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
// Copyright (C) 2006-2013 Jean-Philippe Lang
// Copyright (C) 2010-2013 the ChiliProject Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// See doc/COPYRIGHT.rdoc for more details.
//++
module.exports = function($scope,
I18n,
WorkPackagesOverviewService,
TEXT_TYPE,
STATUS_TYPE,
VERSION_TYPE,
CATEGORY_TYPE,
PRIORITY_TYPE,
USER_TYPE,
TIME_ENTRY_TYPE,
USER_FIELDS,
CustomFieldHelper,
WorkPackagesHelper,
AuthorisationService,
PathHelper,
UserService,
VersionService,
HookService,
OverviewTabInplaceEditorConfig,
$q) {
$scope.inplaceProperties = OverviewTabInplaceEditorConfig.getInplaceProperties();
$scope.userPath = PathHelper.staticUserPath;
AuthorisationService.initModelAuth('work_package' + $scope.workPackage.id,
$scope.workPackage.links);
function can(action) {
return AuthorisationService.can('work_package' + $scope.workPackage.id, action);
}
function getPropertyValue(property, format) {
switch(format) {
case STATUS_TYPE:
case VERSION_TYPE:
case USER_TYPE:
case CATEGORY_TYPE:
10 years ago
case PRIORITY_TYPE:
return $scope.workPackage.embedded[property];
case TIME_ENTRY_TYPE:
return getLinkedTimeEntryValue(property);
default:
return getFormattedPropertyValue(property);
}
}
function getLinkedTimeEntryValue(property) {
var hasLink = !!$scope.workPackage.links.timeEntries,
link = '',
value = 0;
if (hasLink) {
link = $scope.workPackage.links.timeEntries.href;
}
if (hasLink && $scope.workPackage.props.spentTime !== undefined) {
value = $scope.workPackage.props.spentTime;
}
var formattedValue = WorkPackagesHelper.formatWorkPackageProperty(value, property);
return {href: link, title: formattedValue, viewable: link !== ''};
}
function getFormattedPropertyValue(property) {
if (property === 'date') {
return getDateProperty();
} else {
return WorkPackagesHelper.formatWorkPackageProperty($scope.workPackage.props[property], property);
}
}
function getDateProperty() {
if ($scope.workPackage.props.startDate || $scope.workPackage.props.dueDate) {
var displayedStartDate = WorkPackagesHelper.formatWorkPackageProperty($scope.workPackage.props.startDate, 'startDate') || I18n.t('js.label_no_start_date'),
displayedEndDate = WorkPackagesHelper.formatWorkPackageProperty($scope.workPackage.props.dueDate, 'dueDate') || I18n.t('js.label_no_due_date');
return displayedStartDate + ' - ' + displayedEndDate;
}
}
$scope.groupedAttributes = WorkPackagesOverviewService.getGroupedWorkPackageOverviewAttributes();
(function filterUnallowedAttributes() {
var attributes = $scope.groupedAttributes;
angular.forEach(attributes, function(attributesGroup) {
angular.forEach(attributesGroup.attributes, function(attribute) {
if (!isAllowedProperty(attribute)) {
var index = attributesGroup.attributes.indexOf(attribute);
attributesGroup.attributes.splice(index, 1);
}
});
});
return attributes;
})();
function isAllowedProperty(property) {
switch (property) {
case 'spentTime':
return can('timeEntries');
default:
return true;
}
}
(function setupWorkPackageProperties() {
var otherAttributes = WorkPackagesOverviewService.getGroupAttributesForGroupedAttributes('other', $scope.groupedAttributes);
function getFormat(workPackage, prop, propName) {
return workPackage.props[propName] ?
workPackage.props[propName].format :
prop.type.toLowerCase();
}
function getValue(workPackage, propName) {
if (workPackage.props[propName]) {
return workPackage.props[propName].raw;
}
if (workPackage.embedded[propName]) {
return workPackage.embedded[propName].props.id;
}
return null;
}
function getCustomProperties(workPackage) {
return _.compact(_.map(workPackage.schema.props, function(prop, propName) {
if (propName.match(/^customField/)) {
return {
name: prop.name,
format: getFormat(workPackage, prop, propName),
value: getValue(workPackage, propName)
};
}
return false;
}));
}
angular.forEach(getCustomProperties($scope.workPackage), function(customProperty) {
this.push(customProperty);
}, otherAttributes);
angular.forEach($scope.groupedAttributes, function(group) {
var attributesWithValues = [];
angular.forEach(group.attributes, function(attribute) {
if (typeof attribute == 'string') {
this.push(getWorkPackageProperty(attribute));
} else {
this.push(getWorkPackageCustomProperty(attribute));
}
}, attributesWithValues);
group.attributes = attributesWithValues;
});
// The loops before overwrite the attributes array of group 'other'. Thus,
// to get the current values of that array, I need to get that array again.
otherAttributes = WorkPackagesOverviewService.getGroupAttributesForGroupedAttributes('other', $scope.groupedAttributes);
// Sorting the 'other' group is an acutal requirement. So, check if the
// requirement has changed before removing this code!
otherAttributes.sort(function(a, b) {
return a.label.toLowerCase().localeCompare(b.label.toLowerCase());
});
})();
function getWorkPackageProperty(property) {
var label = I18n.t('js.work_packages.properties.' + property),
format = getPropertyFormat(property),
value = getPropertyValue(property, format);
if (!(value === null || value === undefined)) {
return getFormattedValueToPresentProperties(property, label, value, format);
} else {
var plugInValues = HookService.call('workPackageOverviewAttributes',
{ type: property,
workPackage: $scope.workPackage });
if (plugInValues.length == 0) {
return getFormattedValueToPresentProperties(property, label, null, format);
} else {
for (var x = 0; x < plugInValues.length; x++) {
return getFormattedValueToPresentProperties(property, label, plugInValues[x], 'dynamic');
}
}
}
}
function getWorkPackageCustomProperty(property) {
var label = property.name,
value = (property.value) ? getCustomPropertyValue(property) : null,
format = property.format;
return getFormattedValueToPresentProperties(property.name, label, value, format);
}
function getPropertyFormat(property) {
switch(property) {
case 'status':
return STATUS_TYPE;
case 'version':
return VERSION_TYPE;
case 'category':
return CATEGORY_TYPE;
case 'priority':
return PRIORITY_TYPE;
case 'spentTime':
return TIME_ENTRY_TYPE;
default:
return USER_FIELDS.indexOf(property) === -1 ? TEXT_TYPE : USER_TYPE;
}
}
function getCustomPropertyValue(property) {
switch(property.format) {
case USER_TYPE:
return getCustomPropertyUserValue(property);
case VERSION_TYPE:
return getCustomPropertyVersionValue(property);
default:
return CustomFieldHelper.formatCustomFieldValue(property.value, property.format);
}
}
function getFormattedValueToPresentProperties(property, label, value, format) {
var propertyData = {
property: property,
label: label,
format: format,
value: null
};
$q.when(value).then(function(value) {
propertyData.value = value;
});
return propertyData;
}
function getCustomPropertyVersionValue(property) {
var versionHref = PathHelper.staticBase + PathHelper.versionPath(property.value);
var versionTitle = I18n.t('js.error_could_not_resolve_version_name');
var projectId = $scope.workPackage.embedded.project.props.id;
var versions = VersionService.getVersions(projectId);
var promise = $q.when(versions).then(function(value) {
var version = _.find(value, function(version) {
if (version.id) {
return version.id.toString() == property.value;
}
});
if (version) {
versionTitle = version.name;
}
return { href: versionHref, title: versionTitle, viewable: true };
}, function(reason) {
return { href: versionHref, title: versionTitle, viewable: true };
});
return promise;
}
function getCustomPropertyUserValue(property) {
var userHref = PathHelper.staticBase + PathHelper.userPath(property.value);
var userTitle = I18n.t('js.error_could_not_resolve_user_name');
var user = UserService.getUser(property.value);
var promise = $q.when(user).then(function(value) {
userTitle = value.props.name;
return { href: userHref, title: userTitle, viewable: true };
}, function() {
return { href: userHref, title: userTitle, viewable: true };
});
return promise;
}
// toggles
$scope.toggleStates = {
hideFullDescription: true,
hideAllAttributes: true
};
$scope.isGroupEmpty = function(group) {
return _.every(group.attributes, function(element) {
return $scope.isPropertyEmpty(element.value);
});
};
$scope.anyEmptyWorkPackageValue = function() {
return _.any($scope.groupedAttributes, function(element) {
return $scope.anyEmptyPropertyInGroup(element);
});
};
$scope.anyEmptyPropertyInGroup = function(group) {
return _.any(group.attributes, function(element) {
return $scope.isPropertyEmpty(element.value);
});
};
$scope.isPropertyEmpty = function(property) {
return property === undefined || property === null;
};
};