Skip to content

Commit

Permalink
Added Data Configure screen, refactored Post Edit to split into sub d…
Browse files Browse the repository at this point in the history
…irectives and PostEditService, added mode functionality for post edit to allow bulk data import mode
  • Loading branch information
willdoran committed May 1, 2016
1 parent a10ed67 commit 0d9214d
Show file tree
Hide file tree
Showing 8 changed files with 168 additions and 186 deletions.
59 changes: 26 additions & 33 deletions app/post/directives/post-editor-directive.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ function (
'$translate',
'PostEntity',
'PostEndpoint',
'PostEditService',
'FormEndpoint',
'FormStageEndpoint',
'FormAttributeEndpoint',
Expand All @@ -20,6 +21,7 @@ function (
$translate,
postEntity,
PostEndpoint,
PostEditService,
FormEndpoint,
FormStageEndpoint,
FormAttributeEndpoint,
Expand All @@ -32,6 +34,14 @@ function (
$scope.isEdit = !!$scope.post.id;
$scope.validationErrors = [];
$scope.visibleStage = 1;
$scope.enableTitle = true;

// Set bulk data import mode params
if ($scope.postMode === 'bulk_data_import') {
if (_.contains($scope.attributesToIgnore, 'title')) {
$scope.enableTitle = false;
}
}

$scope.goBack = function () {
$scope.post.form = null;
Expand All @@ -43,8 +53,17 @@ function (

$scope.fetchAttributes = function (formId) {
FormAttributeEndpoint.query({formId: formId}).$promise.then(function (attrs) {
// If attributesToIgnore is set, remove those attributes from set of fields to display
var attributes = [];
_.each(attrs, function (attr) {
if (!_.contains($scope.attributesToIgnore, attr.key)) {
attributes.push(attr);
}
});
attributes = (attributes.length) ? attributes : attrs;

// Initialize values on post (helps avoid madness in the template)
attrs.map(function (attr) {
attributes.map(function (attr) {
if (!$scope.post.values[attr.key]) {
if (attr.input === 'location') {
$scope.post.values[attr.key] = [null];
Expand All @@ -55,7 +74,7 @@ function (
}
}
});
$scope.attributes = attrs;
$scope.attributes = attributes;
});
};

Expand Down Expand Up @@ -98,26 +117,7 @@ function (
};

$scope.canSavePost = function () {
var valid = true;
if ($scope.post.status === 'published') {
// first check if stages required have been marked complete
var requiredStages = _.where($scope.stages, {required: true}) ;

valid = _.reduce(requiredStages, function (isValid, stage) {
// if this stage isn't complete, add to errors
if (_.indexOf($scope.post.completed_stages, stage.id) === -1) {
return false;
}

return isValid;
}, valid);

valid = _.reduce($scope.post.completed_stages, function (isValid, stageId) {
return $scope.isStageValid(stageId) && isValid;
}, valid);
}

return valid;
return PostEditService.canSavePost($scope.post, $scope.form, $scope.stages, $scope.attributes);
};

$scope.savePost = function () {
Expand All @@ -128,17 +128,8 @@ function (
$scope.saving_post = true;

// Avoid messing with original object
var post = angular.copy($scope.post);

// Clean up post values object
_.each(post.values, function (value, key) {
// Strip out empty values
post.values[key] = _.filter(value);
// Remove entirely if no values are left
if (!post.values[key].length) {
delete post.values[key];
}
});
var post = PostEditService.cleanPostValues(angular.copy($scope.post));

var request;
if (post.id) {
Expand Down Expand Up @@ -196,7 +187,9 @@ function (
restrict: 'E',
scope: {
post: '=',
activeForm: '='
activeForm: '=',
attributesToIgnore: '=',
postMode: '='
},
templateUrl: 'templates/posts/post-editor.html',
controller: controller
Expand Down
52 changes: 4 additions & 48 deletions app/post/directives/post-stages-directive.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ module.exports = [
'FormEndpoint',
'FormStageEndpoint',
'FormAttributeEndpoint',
'PostEditService',
'TagEndpoint',
'_',
function (
FormEndpoint,
FormStageEndpoint,
FormAttributeEndpoint,
PostEditService,
TagEndpoint,
_
) {
Expand Down Expand Up @@ -36,57 +38,11 @@ function (
$scope.setVisibleStage($scope.visibleStage);

$scope.isFirstStage = function (stageId) {

if (!_.isEmpty($scope.stages)) {
return stageId === $scope.stages[0].id;
}
return false;

return PostEditService.isFirstStage($scope.stages, stageId);
};

$scope.isStageValid = function (stageId) {

if ($scope.isFirstStage(stageId)) {

// The first stage is assumed to contain the title, content, and the tags
// - these are not stored in attributes and do not have a 'required' field
// thus, if any of these are invalid, the first stage is not ready to complete

// Return if form isn't initialized yet
if (!$scope.form) {
return false;
}

if ($scope.form.title.$invalid || $scope.form.content.$invalid) {
return false;
}

if ($scope.form.tags && $scope.form.tags.$invalid) {
return false;
}
}
// now checking all other post attributes that are required
return _.chain($scope.attributes)
.where({form_stage_id : stageId, required: true})
.reduce(function (isValid, attr) {
// checkbox validity needs to be handled differently
// because it has multiple inputs identified via the options
if (attr.input === 'checkbox') {
var checkboxValidity = false;
_.each(attr.options, function (option) {
if (!_.isUndefined($scope.form['values_' + attr.key + '_' + option]) && !$scope.form['values_' + attr.key + '_' + option].$invalid) {
checkboxValidity = isValid;
}
});
return checkboxValidity;
} else {
if (_.isUndefined($scope.form['values_' + attr.key]) || $scope.form['values_' + attr.key].$invalid) {
return false;
}
return isValid;
}
}, true)
.value();
return PostEditService.isStageValid(stageId, $scope.form, $scope.stages, $scope.attributes);
};

$scope.stageIsComplete = function (stageId) {
Expand Down
2 changes: 2 additions & 0 deletions app/post/post-module.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ angular.module('ushahidi.posts', [])
.service('PostEndpoint', require('./services/endpoints/post-endpoint.js'))
.service('PostEntity', require('./services/entities/post-entity.js'))

.service('PostEditService', require('./services/post-edit-service.js'))

.config(require('./post-routes.js'))

.run(['$window', function ($window) {
Expand Down
93 changes: 93 additions & 0 deletions app/post/services/post-edit-service.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
module.exports = [
'_',
'Util',
function (
_,
Util
) {
var PostEditService = {
cleanPostValues: function (post) {
_.each(post.values, function (value, key) {
// Strip out empty values
post.values[key] = _.filter(value);
// Remove entirely if no values are left
if (!post.values[key].length) {
delete post.values[key];
}
});
return post;
},
canSavePost: function (post, form, stages, attributes) {
var valid = true;
if (post.status === 'published') {
// first check if stages required have been marked complete
var requiredStages = _.where(stages, {required: true}) ;

valid = _.reduce(requiredStages, function (isValid, stage) {
// if this stage isn't complete, add to errors
if (_.indexOf(post.completed_stages, stage.id) === -1) {
return false;
}
return isValid;
}, valid);

valid = _.reduce(post.completed_stages, function (isValid, stageId) {
return this.isStageValid(stageId, form, stages, attributes) && isValid;
}, valid);
}

return valid;
},
isFirstStage: function (stages, stageId) {
if (!_.isEmpty(stages)) {
return stageId === stages[0].id;
}
return false;
},
isStageValid: function (stageId, form, stages, attributes) {
if (this.isFirstStage(stages, stageId)) {

// The first stage is assumed to contain the title, content, and the tags
// - these are not stored in attributes and do not have a 'required' field
// thus, if any of these are invalid, the first stage is not ready to complete

// Return if form isn't initialized yet
if (!form) {
return false;
}

if (form.title.$invalid || form.content.$invalid) {
return false;
}

if (form.tags && form.tags.$invalid) {
return false;
}
}
// now checking all other post attributes that are required
return _.chain(attributes)
.where({form_stage_id : stageId, required: true})
.reduce(function (isValid, attr) {
// checkbox validity needs to be handled differently
// because it has multiple inputs identified via the options
if (attr.input === 'checkbox') {
var checkboxValidity = false;
_.each(attr.options, function (option) {
if (!_.isUndefined(form['values_' + attr.key + '_' + option]) && !form['values_' + attr.key + '_' + option].$invalid) {
checkboxValidity = isValid;
}
});
return checkboxValidity;
} else {
if (_.isUndefined(form['values_' + attr.key]) || form['values_' + attr.key].$invalid) {
return false;
}
return isValid;
}
}, true)
.value();
}
};

return Util.bindAllFunctionsToSelf(PostEditService);
}];

0 comments on commit 0d9214d

Please sign in to comment.