Skip to content

Commit

Permalink
Add relation support to client
Browse files Browse the repository at this point in the history
Summary:
- Add relation support to form stage editor
- Add relation input
- Very rough relation output

Test Plan:
Add a relation field to a post type
Edit a post, search for another post
Select and save
View the post and see a link to the related post

Reviewers: lkamau, jasonmule, will

Subscribers: jasonmule, will, rjmackay, lkamau

Maniphest Tasks: T1442

Differential Revision: https://phabricator.ushahidi.com/D891
  • Loading branch information
rjmackay committed Jul 23, 2015
1 parent d601507 commit f87826a
Show file tree
Hide file tree
Showing 11 changed files with 134 additions and 14 deletions.
2 changes: 2 additions & 0 deletions app/common/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"add_field_instructions_info": "These instructions will be presented as a tooltip to a user when filling in this field.",
"add_field_instructions_placeholder": "Instructions for field",
"add_new_step": "Add New Step",
"field_allowed_relation_post_type": "Allowed post types",
"currently_disabled": "This post type is currently disabled.",
"custom_structure": "Custom Structure",
"default_date_placeholder": "Default date",
Expand Down Expand Up @@ -148,6 +149,7 @@
"role" : "Role",
"roles" : "Roles",
"saved_searches" : "Saved Searches",
"search" : "Search",
"select_all" : "Select All",
"settings" : "Settings",
"tags" : "Categories",
Expand Down
3 changes: 3 additions & 0 deletions app/post/directives/post-editor-directive.js
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,9 @@ function (
$scope.isRadio = function (attr) {
return attr.input === 'radio';
};
$scope.isRelation = function (attr) {
return attr.input === 'relation';
};

// Can more values be added for this attribute?
$scope.canAddValue = function (attr) {
Expand Down
55 changes: 55 additions & 0 deletions app/post/directives/post-relation-directive.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
module.exports = [
'PostEndpoint',
'_',
function (
PostEndpoint,
_
) {

return {
restrict: 'E',
replace: true,
scope: {
id: '@',
name: '@',
model: '=',
required: '=',
attribute: '='
},
templateUrl: 'templates/posts/relation.html',
link: function ($scope) {
$scope.$watch(function () {
return $scope.model;
}, function (newValue, oldValue) {
if (!$scope.selectedPost || $scope.selectedPost.id !== newValue) {
$scope.selectedPost = PostEndpoint.get({ id: $scope.model });
}
});

$scope.search = function (event) {
event.preventDefault();
var query = { q : $scope.searchTerm };

if ($scope.attribute.config.input && $scope.attribute.config.input.form) {
query.form = $scope.attribute.config.input.form.join(',');
}

PostEndpoint.query(query).$promise.then(function (response) {
$scope.results = response.results;
});
};

$scope.selectPost = function (post) {
$scope.model = post.id;
$scope.selectedPost = post;
$scope.results = null;
};

$scope.clearPost = function () {
$scope.model = null
$scope.selectedPost = null;
};
}
};

}];
11 changes: 9 additions & 2 deletions app/post/directives/post-value-directive.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module.exports = [function () {
module.exports = ['PostEndpoint', function (PostEndpoint) {
return {
restrict: 'E',
replace: true,
Expand All @@ -7,6 +7,13 @@ module.exports = [function () {
value: '=',
attribute: '='
},
templateUrl: 'templates/partials/post-detail-value.html'
templateUrl: 'templates/partials/post-detail-value.html',
link: function ($scope) {
if ($scope.attribute.type === 'relation') {
$scope.value = $scope.value.map(function (entry) {
return PostEndpoint.get({ id : entry });
});
}
}
};
}];
1 change: 1 addition & 0 deletions app/post/post-module.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ angular.module('ushahidi.posts', [])
.directive('postPreview', require('./directives/post-preview-directive.js'))
.directive('postValue', require('./directives/post-value-directive.js'))
.directive('postLocation', require('./directives/post-location-directive.js'))
.directive('postRelation', require('./directives/post-relation-directive.js'))
// Post editing workflows
.directive('postEditor', require('./directives/post-editor-directive.js'))
.directive('postChooseForm', require('./directives/post-choose-form-directive.js'))
Expand Down
26 changes: 15 additions & 11 deletions app/post/services/endpoints/post-endpoint.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,30 @@ module.exports = [
'$resource',
'$rootScope',
'Util',
'_',
function (
$resource,
$rootScope,
Util
Util,
_
) {

var PostEndpoint = $resource(Util.apiUrl('/posts/:id/:extra'), {
id: '@id'
}, {
query: {
method: 'GET',
isArray: false,
isArray: false
},
get: {
method: 'GET',
transformResponse: function (data /*, header*/) {
return angular.fromJson(data);
data = angular.fromJson(data);
// Ensure values is always an object
if (_.isArray(data.values)) {
data.values = _.object(data.values);
}
return data;
}
},
update: {
Expand All @@ -27,18 +37,12 @@ function (
geojson: {
method: 'GET',
url: Util.apiUrl('/posts/:id/geojson'),
isArray: false,
transformResponse: function (data /*, header*/) {
return angular.fromJson(data);
}
isArray: false
},
stats: {
method: 'GET',
url: Util.apiUrl('/posts/:id/stats'),
isArray: false,
transformResponse: function (data /*, header*/) {
return angular.fromJson(data);
}
isArray: false
}
});

Expand Down
12 changes: 12 additions & 0 deletions app/setting/directives/setting-form-stage-editor-directive.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,12 @@ function (
$scope.currentStageId = currentStageId;
});

// Load available forms for relation fields
$scope.availableForms = FormEndpoint.query();
$scope.filterNotCurrentForm = function (form) {
return form.id !== $attrs.formId;
};

// Manage stage settings
$scope.isSettingsOpen = false;
$scope.openSettings = function () {
Expand Down Expand Up @@ -150,6 +156,11 @@ function (
label: 'Checkbox',
type: 'varchar',
input: 'checkbox'
},
{
label: 'Related Post',
type: 'relation',
input: 'relation'
}
];
$scope.isNewAttributeOpen = false;
Expand All @@ -166,6 +177,7 @@ function (
label: 'New field',
required: false,
options: [],
config: {},
form_stage_id: $scope.currentStageId
};

Expand Down
11 changes: 11 additions & 0 deletions server/www/templates/partials/form-stage-editor.html
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,17 @@ <h3><a ng-model="attribute.label" dropdown-toggle>{{ attribute.label }}</a></h3>
</div>
<button type="button" class="button-secondary alt" ng-click="addOption(attribute)"><i class="fa fa-plus"></i> <span translate>form.field_add_option</span></button>
</div>
<div ng-if="attribute.input === 'relation'">
<label class="input-label" translate>form.field_allowed_relation_post_type</label>
<ul name="visible-to">
<li ng-repeat="relationForm in availableForms | filter : filterNotCurrentForm">
<label>
<input type="checkbox" checklist-model="attribute.config.input.form" checklist-value="relationForm.id" />
{{relationForm.name}}
</label>
</li>
</ul>
</div>
<!--
<div class="select-inline">
<label class="input-label">{{ 'form.visible_to'|translate }}:</label>
Expand Down
5 changes: 4 additions & 1 deletion server/www/templates/partials/post-detail-value.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ <h3 class="value-label">
</h3>

<ul class="list-unstyled">
<li ng-repeat="entry in value">
<li ng-repeat="entry in value" ng-if="attribute.type === 'relation'">
<a ng-href="/posts/{{entry.id}}">{{entry.title}}</a>
</li>
<li ng-repeat="entry in value" ng-if="attribute.type !== 'relation'">
{{entry}}
</li>
</ul>
Expand Down
10 changes: 10 additions & 0 deletions server/www/templates/posts/post-editor.html
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,16 @@ <h1 translate translate-values="{ type: activeForm.name, title: post.title }" ng
ng-class="{ 'error': form['values_' + attribute.key].$invalid && form['values_' + attribute.key].$dirty }"
>

<!-- type: relation -->
<post-relation
attribute="attribute"
key="key"
id="values[{{attribute.key}}][{{key}}]"
name="values_{{attribute.key}}"
model="post.values[attribute.key][key]"
required="attribute.required"
ng-if="isRelation(attribute)"></post-relation>

<!-- type: textarea -->
<textarea
rows="10"
Expand Down
12 changes: 12 additions & 0 deletions server/www/templates/posts/relation.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<form name="relation-search-form" class="input-relation">
<p ng-if="model">{{ selectedPost.title }} ({{ model }}) <button class="button-secondary icon-only alt trash" type="button" ng-click="clearPost()" translate></button></p>
<div class="input-inline">
<input class="form-control" type="text" placeholder="Search.." ng-model="searchTerm">
<button class="btn btn-info" type="button" ng-click="search($event)" translate>nav.search</button>
</div>
<ul>
<li ng-repeat="post in results">
<button type="button" class="button-secondary icon-only check" ng-click="selectPost(post)" translate></button> {{ post.id }} : {{ post.title }}
</li>
</ul>
</form>

0 comments on commit f87826a

Please sign in to comment.