Normalize the relation type depending on direction

The frontend needs to normalize the relationType retrieved from the API
to either that, or reverseType when the shown work package is the `to`
link.

This PR also extends the relations spec to test exactly that.
pull/4994/head
Oliver Günther 8 years ago
parent 4ccc57279f
commit e265af85f9
No known key found for this signature in database
GPG Key ID: 88872239EB414F99
  1. 9
      frontend/app/components/api/api-v3/hal-resources/relation-resource.service.ts
  2. 14
      frontend/app/components/wp-relations/wp-relation-row/wp-relation-row.directive.ts
  3. 9
      frontend/app/components/wp-relations/wp-relation-row/wp-relation-row.template.html
  4. 4
      frontend/app/components/wp-relations/wp-relations-create/dynamic-relation-types.template.html
  5. 3
      frontend/app/components/wp-relations/wp-relations-group/wp-relations-group.template.html
  6. 52
      spec/features/work_packages/details/details_relations_spec.rb

@ -65,12 +65,21 @@ export class RelationResource extends HalResource {
public description:string|null;
public name:string;
public type:string;
public reverseType:string;
// Links
public $links: RelationResourceLinks;
public to:WorkPackageResource;
public from:WorkPackageResource;
public normalizedType(workPackage:WorkPackageResource) {
if (this.to.href === workPackage.href) {
return this.reverseType;
}
return this.type;
}
public updateDescription(description) {
return this.$links.updateImmediately({ description: description });
}

@ -2,6 +2,7 @@ import {wpDirectivesModule} from '../../../angular-modules';
import {RelatedWorkPackage} from '../wp-relations.interfaces';
import {WorkPackageCacheService} from '../../work-packages/work-package-cache.service';
import {WorkPackageNotificationService} from '../../wp-edit/wp-notification.service';
import {WorkPackageResourceInterface} from '../../api/api-v3/hal-resources/work-package-resource.service';
import {WorkPackageRelationsService} from '../wp-relations.service';
import {
RelationResourceInterface,
@ -9,6 +10,7 @@ import {
} from '../../api/api-v3/hal-resources/relation-resource.service';
class WpRelationRowDirectiveController {
public workPackage: WorkPackageResourceInterface;
public relatedWorkPackage: RelatedWorkPackage;
public relationType: string;
public showRelationInfo:boolean = false;
@ -42,6 +44,15 @@ class WpRelationRowDirectiveController {
this.selectedRelationType = _.find(this.availableRelationTypes, {'name': this.relation.type});
};
/**
* Return the normalized relation type for the work package we're viewing.
* That is, normalize `precedes` where the work package is the `to` link.
*/
public get normalizedRelationType() {
var type = this.relation.normalizedType(this.workPackage);
return this.I18n.t('js.relation_labels.' + type);
}
public get relationReady() {
return this.relatedWorkPackage && this.relatedWorkPackage.$loaded;
}
@ -90,7 +101,8 @@ function WpRelationRowDirective() {
restrict:'E',
templateUrl:'/components/wp-relations/wp-relation-row/wp-relation-row.template.html',
scope:{
relatedWorkPackage:'='
workPackage: '=',
relatedWorkPackage: '='
},
controller:WpRelationRowDirectiveController,
controllerAs:'$ctrl',

@ -1,12 +1,14 @@
<div class="relation-row"
ng-class="['relation-row-{{ $ctrl.relatedWorkPackage.id }}']"
ng-mouseover="$ctrl.showRelationControls = true"
ng-mouseleave="$ctrl.showRelationControls = false">
<div class="grid-block hierarchy-item">
<div class="grid-content medium-3 collapse" aria-hidden="true">
<span ng-click="$ctrl.userInputs.showRelationTypesForm = true"
<span class="relation-row--type"
ng-click="$ctrl.userInputs.showRelationTypesForm = true"
ng-if="!$ctrl.userInputs.showRelationTypesForm">
{{ $ctrl.relation.type }}
{{ $ctrl.normalizedRelationType }}
</span>
<div class="wp-edit-field inplace-edit" ng-if="$ctrl.userInputs.showRelationTypesForm">
<select class="wp-inline-edit--field form--select"
@ -20,7 +22,7 @@
ng-if="$ctrl.relatedWorkPackage">
<a href="{{ singleRelationCtrl.workPackagePath($ctrl.relatedWorkPackage.id) }}"
class="wp-relations--subject-field"
aria-label="{{ $ctrl.relation.type + ' ' + singleRelationCtrl.getFullIdentifier($ctrl.relatedWorkPackage, true) }}">
aria-label="{{ $ctrl.normalizedRelationType + ' ' + singleRelationCtrl.getFullIdentifier($ctrl.relatedWorkPackage, true) }}">
{{ singleRelationCtrl.getFullIdentifier($ctrl.relatedWorkPackage, true) }}
</a>
</div>
@ -42,6 +44,7 @@
ng-if="$ctrl.relation.delete"
execute="$ctrl.removeRelation($ctrl.relation)"
aria-hidden="false"
link-class="relation-row--remove-btn"
class="-shown-in-accessibility-mode">
<icon-wrapper icon-name="remove"
icon-title="{{ ::$ctrl.text.removeButton }}">

@ -13,7 +13,7 @@
</div>
</div>
</div>
<div class="grid-block v-align" ng-if="$ctrl.showRelationsCreateForm">
<div class="grid-block v-align wp-relations-create--form" ng-if="$ctrl.showRelationsCreateForm">
<div class="grid-content collapse medium-3">
<label class="hidden-for-sighted" for="relation-type--select">{{ ::$ctrl.text.relationType }}</label>
<select class="form--select relationTypeSelect"
@ -33,6 +33,7 @@
<div class="grid-content medium-2 collapse wp-relations-controls-section relation-row">
<accessible-by-keyboard
execute="$ctrl.createRelation()"
link-class="wp-create-relation--save"
aria-hidden="false">
<icon-wrapper icon-name="checkmark"
icon-title="{{ ::$ctrl.text.save }}">
@ -40,6 +41,7 @@
</accessible-by-keyboard>
<accessible-by-keyboard
execute="$ctrl.toggleRelationsCreateForm()"
link-class="wp-create-relation--cancel"
aria-hidden="false">
<icon-wrapper icon-name="remove"
icon-title="{{ ::$ctrl.text.abort }}">

@ -1,7 +1,7 @@
<div class="attributes-group">
<div class="attributes-group--header">
<div class="attributes-group--header-container">
<h3 class="attributes-group--header-text">
<h3 class="attributes-group--header-text relation-group--header">
{{ $ctrl.wpType }}
</h3>
</div>
@ -9,6 +9,7 @@
<div class="content" ng-if="$ctrl.relatedWorkPackages">
<wp-relation-row
work-package="$ctrl.workPackage"
related-work-package="relatedWorkPackage"
ng-repeat="relatedWorkPackage in $ctrl.relatedWorkPackages"></wp-relation-row>
</div>

@ -150,7 +150,57 @@ describe 'Work package relations tab', js: true, selenium: true do
end
context 'with relations permissions' do
it 'should allow to create relations' do
let(:permissions) do
%i(view_work_packages add_work_packages manage_subtasks manage_work_package_relations)
end
let!(:relatable) { FactoryGirl.create(:work_package, project: project) }
it 'should allow to manage relations' do
# Open create form
find('#relation--add-relation').click
# Select relation type
container = find('.wp-relations-create--form', wait: 10)
# Labels to expect
follows_label = I18n.t('js.relation_labels.follows')
type_upcase = work_package.type.name.upcase
select follows_label, from: 'relation-type--select'
# Enter the query and select the child
typeahead = container.find(".wp-relations--autocomplete")
select_typeahead(typeahead, query: relatable.subject, select_text: relatable.subject)
container.find('.wp-create-relation--save').click
expect(page).to have_selector('.relation-group--header',
text: type_upcase,
wait: 10)
expect(page).to have_selector('.relation-row--type', text: follows_label)
expect(page).to have_selector('.wp-relations--subject-field', text: relatable.subject)
## Test if relation exist
work_package.reload
relation = work_package.relations.first
expect(relation.relation_type).to eq('precedes')
expect(relation.from_id).to eq(relatable.id)
expect(relation.to_id).to eq(work_package.id)
## Delete relation
created_row = find(".relation-row-#{relatable.id}")
# Hover row to expose button
created_row.hover
created_row.find('.relation-row--remove-btn').click
expect(page).to have_no_selector('.relation-group--header', text: type_upcase)
expect(page).to have_no_selector('.wp-relations--subject-field', text: relatable.subject)
work_package.reload
expect(work_package.relations).to be_empty
end
end
end

Loading…
Cancel
Save