finishing post submit form refactoring

This commit is contained in:
Sacha Greif 2014-11-28 15:18:55 +09:00
parent 672be96c9b
commit 0031d07468
9 changed files with 185 additions and 133 deletions

View file

@ -6,7 +6,7 @@
<textarea id="comment" rows="3" autofocus="autofocus"></textarea> <textarea id="comment" rows="3" autofocus="autofocus"></textarea>
</div> </div>
<div class="comment-submit"> <div class="comment-submit">
<input type="submit" class="button" value="{{_ "add_comment"}}" title="(⌘+enter)" /> <input type="submit" class="btn btn-primary" value="{{_ "add_comment"}}" title="(⌘+enter)" />
</div> </div>
</form> </form>
</div> </div>

View file

@ -1,3 +1,3 @@
<template name="afBootstrapDatepicker"> <template name="afBootstrapUrl">
<input type="text" value="" {{atts}}/> <input type="text" value="" {{atts}}/>
</template> </template>

View file

@ -0,0 +1,18 @@
AutoForm.addInputType("bootstrap-url", {
template: "afBootstrapUrl",
valueOut: function () {
var url = this.val();
if(!!url)
return (url.substring(0, 7) == "http://" || url.substring(0, 8) == "https://") ? url : "http://"+url;
}
});
Template.afBootstrapUrl.helpers({
atts: function addFormControlAtts() {
var atts = _.clone(this.atts);
// Add bootstrap class
atts = AutoForm.Utility.addClass(atts, "form-control");
return atts;
}
});

View file

@ -1,7 +1,7 @@
<template name="post_submit"> <template name="post_submit">
<div class="grid grid-module"> <div class="grid grid-module">
{{> quickForm collection="Posts" id="insertPostForm" type="insert" template="telescope" label-class="control-label" input-col-class="controls"}} {{> quickForm collection="Posts" id="insertPostForm" template="telescope" label-class="control-label" input-col-class="controls"}}
</div> </div>
<!-- <div class="grid submit"> <!-- <div class="grid submit">

View file

@ -1,43 +1,64 @@
AutoForm.debug() AutoForm.debug()
AutoForm.hooks({ AutoForm.hooks({
insertPostForm: { insertPostForm: {
before: {
insert: function(doc, template) {
console.log(doc)
},
update: function(docId, modifier, template) {},
"methodName": function(doc, template) {}
},
after: {
insert: function(error, result, template) {
console.log(error)
console.log(result)
},
update: function(error, result, template) {},
"methodName": function(error, result, template) {}
},
// Called when form does not have a `type` attribute
onSubmit: function(insertDoc, updateDoc, currentDoc) { onSubmit: function(insertDoc, updateDoc, currentDoc) {
console.log(insertDoc)
console.log(updateDoc) var properties = insertDoc;
console.log(currentDoc) var submit = this;
// ------------------------------ Checks ------------------------------ //
if (!Meteor.user()) {
throwError(i18n.t('you_must_be_logged_in'));
return false;
}
// ------------------------------ Callbacks ------------------------------ //
// run all post submit client callbacks on properties object successively
properties = postSubmitClientCallbacks.reduce(function(result, currentFunction) {
return currentFunction(result);
}, properties);
// console.log(properties)
// ------------------------------ Insert ------------------------------ //
if (properties) {
Meteor.call('post', properties, function(error, post) {
if(error){
submit.done(error);
}else{
// note: find a way to do this in onSuccess instead?
trackEvent("new post", {'postId': post._id});
if(post.status === STATUS_PENDING)
throwError('Thanks, your post is awaiting approval.');
Router.go('/posts/'+post._id);
submit.done();
}
});
}
return false
}, },
// Called when any operation succeeds, where operation will be
// "insert", "update", "submit", or the method name.
onSuccess: function(operation, result, template) { onSuccess: function(operation, result, template) {
console.log(operation) // not used right now because I can't find a way to pass the "post" object to this callback
console.log(result) // console.log(post)
// trackEvent("new post", {'postId': post._id});
// if(post.status === STATUS_PENDING)
// throwError('Thanks, your post is awaiting approval.');
// Router.go('/posts/'+post._id);
}, },
// Called when any operation fails, where operation will be
// "validation", "insert", "update", "submit", or the method name.
onError: function(operation, error, template) { onError: function(operation, error, template) {
console.log(operation) throwError(error.reason.split('|')[0]); // workaround because error.details returns undefined
console.log(error) clearSeenErrors();
// $(e.target).removeClass('disabled');
if (error.error == 603) {
var dupePostId = error.reason.split('|')[1];
Router.go('/posts/'+dupePostId);
}
} }
// formToDoc: function(doc, ss, formId) {},
// docToForm: function(doc, ss, formId) {},
// Called at the beginning and end of submission, respectively. // Called at the beginning and end of submission, respectively.
// This is the place to disable/enable buttons or the form, // This is the place to disable/enable buttons or the form,
@ -91,115 +112,115 @@ AutoForm.hooks({
// }; // };
// Template[getTemplate('post_submit')].events({ Template[getTemplate('post_submit')].events({
// 'change input[name=status]': function (e, i) { // 'change input[name=status]': function (e, i) {
// Session.set('currentPostStatus', e.currentTarget.value); // Session.set('currentPostStatus', e.currentTarget.value);
// }, // },
// 'click input[type=submit]': function(e, instance){ // 'click input[type=submit]': function(e, instance){
// e.preventDefault(); // e.preventDefault();
// $(e.target).addClass('disabled'); // $(e.target).addClass('disabled');
// // ------------------------------ Checks ------------------------------ // // // ------------------------------ Checks ------------------------------ //
// if(!Meteor.user()){ // if(!Meteor.user()){
// throwError(i18n.t('you_must_be_logged_in')); // throwError(i18n.t('you_must_be_logged_in'));
// return false; // return false;
// } // }
// // ------------------------------ Properties ------------------------------ // // // ------------------------------ Properties ------------------------------ //
// // Basic Properties // // Basic Properties
// var properties = { // var properties = {
// title: $('#title').val(), // title: $('#title').val(),
// body: instance.editor.exportFile(), // body: instance.editor.exportFile(),
// sticky: $('#sticky').is(':checked'), // sticky: $('#sticky').is(':checked'),
// userId: $('#postUser').val(), // userId: $('#postUser').val(),
// status: parseInt($('input[name=status]:checked').val()) // status: parseInt($('input[name=status]:checked').val())
// }; // };
// // PostedAt // // PostedAt
// var $postedAtDate = $('#postedAtDate'); // var $postedAtDate = $('#postedAtDate');
// var $postedAtTime = $('#postedAtTime'); // var $postedAtTime = $('#postedAtTime');
// var setPostedAt = false; // var setPostedAt = false;
// var postedAt = new Date(); // default to current browser date and time // var postedAt = new Date(); // default to current browser date and time
// var postedAtDate = $postedAtDate.datepicker('getDate'); // var postedAtDate = $postedAtDate.datepicker('getDate');
// var postedAtTime = $postedAtTime.val(); // var postedAtTime = $postedAtTime.val();
// if ($postedAtDate.exists() && postedAtDate != "Invalid Date"){ // if custom date is set, use it // if ($postedAtDate.exists() && postedAtDate != "Invalid Date"){ // if custom date is set, use it
// postedAt = postedAtDate; // postedAt = postedAtDate;
// setPostedAt = true; // setPostedAt = true;
// } // }
// if ($postedAtTime.exists() && postedAtTime.split(':').length==2){ // if custom time is set, use it // if ($postedAtTime.exists() && postedAtTime.split(':').length==2){ // if custom time is set, use it
// var hours = postedAtTime.split(':')[0]; // var hours = postedAtTime.split(':')[0];
// var minutes = postedAtTime.split(':')[1]; // var minutes = postedAtTime.split(':')[1];
// postedAt = moment(postedAt).hour(hours).minute(minutes).toDate(); // postedAt = moment(postedAt).hour(hours).minute(minutes).toDate();
// setPostedAt = true; // setPostedAt = true;
// } // }
// if(setPostedAt) // if either custom date or time has been set, pass result to properties // if(setPostedAt) // if either custom date or time has been set, pass result to properties
// properties.postedAt = postedAt; // properties.postedAt = postedAt;
// // URL // // URL
// var url = $('#url').val(); // var url = $('#url').val();
// if(!!url){ // if(!!url){
// var cleanUrl = (url.substring(0, 7) == "http://" || url.substring(0, 8) == "https://") ? url : "http://"+url; // var cleanUrl = (url.substring(0, 7) == "http://" || url.substring(0, 8) == "https://") ? url : "http://"+url;
// properties.url = cleanUrl; // properties.url = cleanUrl;
// } // }
// // ------------------------------ Callbacks ------------------------------ // // // ------------------------------ Callbacks ------------------------------ //
// // run all post submit client callbacks on properties object successively // // run all post submit client callbacks on properties object successively
// properties = postSubmitClientCallbacks.reduce(function(result, currentFunction) { // properties = postSubmitClientCallbacks.reduce(function(result, currentFunction) {
// return currentFunction(result); // return currentFunction(result);
// }, properties); // }, properties);
// // console.log(properties) // // console.log(properties)
// // ------------------------------ Insert ------------------------------ // // // ------------------------------ Insert ------------------------------ //
// if (properties) { // if (properties) {
// Meteor.call('post', properties, function(error, post) { // Meteor.call('post', properties, function(error, post) {
// if(error){ // if(error){
// throwError(error.reason); // throwError(error.reason);
// clearSeenErrors(); // clearSeenErrors();
// $(e.target).removeClass('disabled'); // $(e.target).removeClass('disabled');
// if(error.error == 603) // if(error.error == 603)
// Router.go('/posts/'+error.details); // Router.go('/posts/'+error.details);
// }else{ // }else{
// trackEvent("new post", {'postId': post._id}); // trackEvent("new post", {'postId': post._id});
// if(post.status === STATUS_PENDING) // if(post.status === STATUS_PENDING)
// throwError('Thanks, your post is awaiting approval.'); // throwError('Thanks, your post is awaiting approval.');
// Router.go('/posts/'+post._id); // Router.go('/posts/'+post._id);
// } // }
// }); // });
// } else { // } else {
// $(e.target).removeClass('disabled'); // $(e.target).removeClass('disabled');
// } // }
// }, // },
// 'click .get-title-link': function(e){ // 'click .get-title-link': function(e){
// e.preventDefault(); // e.preventDefault();
// var url=$("#url").val(); // var url=$("#url").val();
// var $getTitleLink = $(".get-title-link"); // var $getTitleLink = $(".get-title-link");
// $getTitleLink.addClass("loading"); // $getTitleLink.addClass("loading");
// if(url){ // if(url){
// $.get(url, function(response){ // $.get(url, function(response){
// if ((suggestedTitle=((/<title>(.*?)<\/title>/m).exec(response.responseText))) != null){ // if ((suggestedTitle=((/<title>(.*?)<\/title>/m).exec(response.responseText))) != null){
// $("#title").val(suggestedTitle[1]); // $("#title").val(suggestedTitle[1]);
// }else{ // }else{
// alert("Sorry, couldn't find a title..."); // alert("Sorry, couldn't find a title...");
// } // }
// $getTitleLink.removeClass("loading"); // $getTitleLink.removeClass("loading");
// }); // });
// }else{ // }else{
// alert("Please fill in an URL first!"); // alert("Please fill in an URL first!");
// $getTitleLink.removeClass("loading"); // $getTitleLink.removeClass("loading");
// } // }
// } // }
// }); });

View file

@ -27,6 +27,7 @@ postSchemaObject = {
}, },
title: { title: {
type: String, type: String,
optional: false,
label: "Title", label: "Title",
editable: true, editable: true,
autoform: { autoform: {
@ -39,7 +40,8 @@ postSchemaObject = {
optional: true, optional: true,
editable: true, editable: true,
autoform: { autoform: {
editable: true editable: true,
type: "bootstrap-url"
} }
}, },
body: { body: {
@ -164,6 +166,13 @@ postSchemaObject = {
omit: true omit: true
} }
}, },
author: {
type: String,
optional: true,
autoform: {
omit: true
}
},
userId: { userId: {
type: String, // XXX type: String, // XXX
optional: true, optional: true,
@ -286,7 +295,8 @@ Meteor.methods({
if(typeof postWithSameLink !== 'undefined'){ if(typeof postWithSameLink !== 'undefined'){
Meteor.call('upvotePost', postWithSameLink); Meteor.call('upvotePost', postWithSameLink);
throw new Meteor.Error(603, i18n.t('this_link_has_already_been_posted'), postWithSameLink._id); // note: error.details returns undefined on the client, so add post ID to reason
throw new Meteor.Error('603', i18n.t('this_link_has_already_been_posted') + '|' + postWithSameLink._id, postWithSameLink._id);
} }
} }

View file

@ -0,0 +1,3 @@
<template name="afBootstrapDateTimePicker">
<input type="text" value="" {{atts}}/>
</template>

View file

@ -1,5 +1,5 @@
AutoForm.addInputType("bootstrap-datetimepicker", { AutoForm.addInputType("bootstrap-datetimepicker", {
template: "afBootstrapDatepicker", template: "afBootstrapDateTimePicker",
valueOut: function () { valueOut: function () {
// var val = this.datepicker('getUTCDate'); // var val = this.datepicker('getUTCDate');
if (!!this.data("DateTimePicker").getDate()) { if (!!this.data("DateTimePicker").getDate()) {
@ -36,7 +36,7 @@ AutoForm.addInputType("bootstrap-datetimepicker", {
} }
}); });
Template.afBootstrapDatepicker.helpers({ Template.afBootstrapDateTimePicker.helpers({
atts: function addFormControlAtts() { atts: function addFormControlAtts() {
var atts = _.clone(this.atts); var atts = _.clone(this.atts);
// Add bootstrap class // Add bootstrap class
@ -45,7 +45,7 @@ Template.afBootstrapDatepicker.helpers({
} }
}); });
Template.afBootstrapDatepicker.rendered = function () { Template.afBootstrapDateTimePicker.rendered = function () {
var $input = this.$('input'); var $input = this.$('input');
var data = this.data; var data = this.data;
@ -84,9 +84,9 @@ Template.afBootstrapDatepicker.rendered = function () {
}; };
Template.afBootstrapDatepicker.destroyed = function () { Template.afBootstrapDateTimePicker.destroyed = function () {
// this.$('input').datepicker('remove'); // this.$('input').datepicker('remove');
this.data('DateTimePicker').destroy(); this.$('input').data('DateTimePicker').destroy();
}; };
function utcToLocal(utcDate) { function utcToLocal(utcDate) {

View file

@ -16,8 +16,8 @@ Package.onUse(function(api) {
api.addFiles([ api.addFiles([
'datetimepicker.scss', 'datetimepicker.scss',
'autoform-bs-datepicker.html', 'autoform-bs-datetimepicker.html',
'autoform-bs-datepicker.js', 'autoform-bs-datetimepicker.js',
'bootstrap-collapse-transitions.js', 'bootstrap-collapse-transitions.js',
'fonts/glyphicons-halflings-regular.eot', 'fonts/glyphicons-halflings-regular.eot',
'fonts/glyphicons-halflings-regular.svg', 'fonts/glyphicons-halflings-regular.svg',