Can't get meteor FileCollection package to work - events

I am (unfortunately) working on a Windows machine so I had to manually add the FileCollection package to my app, but when I run my app, I can access the file collection and file collection methods from the browser console. However, I can't seem to get the event listeners set up on an actual page. (FYI, I am using iron-router for my templating architecture.)
It seems like the code that needs to be called is just not coming in the right order, but I've experimented with where I place the code and nothing seems to make a difference.
The server side code:
// Create a file collection, and enable file upload and download using HTTP
Images = new fileCollection('images',
{ resumable: true, // Enable built-in resumable.js upload support
http: [
{ method: 'get',
path: '/:_id', // this will be at route "/gridfs/images/:_id"
lookup: function (params, query) { // uses express style url params
return { _id: params._id }; // a mongo query mapping url to myFiles
}
}
]
}
);
if (Meteor.isServer) {
// Only publish files owned by this userId, and ignore
// file chunks being used by Resumable.js for current uploads
Meteor.publish('myImages',
function () {
return Images.find({ 'metadata._Resumable': { $exists: false },
'metadata.owner': this.userId });
}
);
// Allow rules for security. Should look familiar!
// Without these, no file writes would be allowed
Images.allow({
remove: function (userId, file) {
// Only owners can delete
if (userId !== file.metadata.owner) {
return false;
} else {
return true;
}
},
// Client file document updates are all denied, implement Methods for that
// This rule secures the HTTP REST interfaces' PUT/POST
update: function (userId, file, fields) {
// Only owners can upload file data
if (userId !== file.metadata.owner) {
return false;
} else {
return true;
}
},
insert: function (userId, file) {
// Assign the proper owner when a file is created
file.metadata = file.metadata || {};
file.metadata.owner = userId;
return true;
}
});
}
The client side code (currently in main.js at the top level of the client dir):
if (Meteor.isClient) {
// This assigns a file upload drop zone to some DOM node
Images.resumable.assignDrop($(".fileDrop"));
// This assigns a browse action to a DOM node
Images.resumable.assignBrowse($(".fileBrowse"));
// When a file is added via drag and drop
Images.resumable.on('fileAdded', function(file) {
// Create a new file in the file collection to upload
Images.insert({
_id : file.uniqueIdentifier, // This is the ID resumable will use
filename : file.fileName,
contentType : file.file.type
}, function(err, _id) {// Callback to .insert
if (err) {throwError('Image upload failed');}
// Once the file exists on the server, start uploading
Images.resumable.upload();
});
});
Images.resumable.on('fileSuccess', function(file) {
var userId = Meteor.userId();
var url = '/gridfs/images/' + file._id;
Meteor.users.update(userId, {
$set : {
"profile.$.imageURL" : url
}
});
Session.set('uploading', false);
});
Images.resumable.on('fileProgress', function(file) {
Session.set('uploading', true);
});
}

I think the issue might be with using IronRouter. I'll assume you are using some layout.html via Iron router and inside it you've added your template for your file table to be shown. (I'm guessing your are following the sampleApp that came with fileCollection.). I had a problem when I did this and it had to do with where I had the code that attached the listeners. The problem is where you have the code "Images.resumable.assignDrop($(".fileDrop"));" in your client file. The way you have it now, that line of code is running before your template is rendered within the layout.html. So the code can not find the DOM element ".fileDrop". To fix this create a layout.js file and use the rendered method like this...
Template.layout.rendered = function(){
Images.resumable.assignDrop($(".fileDrop"));
}

Related

async update(params, data, { files } = {}) does not work

my project was created with Strapi 3.0.0-beta.18.6.
But in the service of the content type "Orders" the (new) "update" method does not work, only the (old) "edit" works.
Can someone give me a tip?
// ---------------- "update" does not work :( ------------------
async update(params, data, { files } = {}) {
const query = strapi.query('order');
const entry = await query.update(params, data);
if (files) {
// automatically uploads the files based on the entry and the model
await this.uploadFiles(entry, files, { model: strapi.models.order });
return this.findOne({ id: entry.id });
}
return entry;
},
by the way, query.update(params, data); cannot be executed, the process is canceled, but there is no error message.
// ---------------- old "edit" works ------------------
async edit (params, values) {
// Extract values related to relational data.
const relations = _.pick(values, Order.associations.map(ast => ast.alias));
const data = _.omit(values, Order.associations.map(ast => ast.alias));
// Create entry with no-relational data.
const entry = Order.forge(params).save(data);
// Create relational data and return the entry.
return Order.updateRelations(Object.assign(params, { values: relations }));
},
Thanks in advance!
Strapi generated controllers are based on the shadow core controller function.
If you want to customize the default function you can refer to this documentation : https://strapi.io/documentation/3.0.0-beta.x/concepts/controllers.html#core-controllers
I just tried it and it works fine.

Nativescript imagepicker .getImage() is not a function error

I have been trying to implement the answer to this question but keep getting the error "selected.getImage is not a function".
I have tried multiple different code examples at this point and I'm stumped. It seems like this is a type error, but I'm not sure where I can correct this.
I am looking to select a single image and return the path to that image in order to upload to the server. I don't need to display it on the device, though that is an option I suppose. Seems easy enough, but apparently I'm missing something.
I'm using v. 6.0.1 or the imagepicker plugin. I'd quote the code, but at this point I am using the exact example provided by Shiva Prasad in the above question.
Adding code per Max Vollmer:
var context = imagepickerModule.create({
mode: "single" // allow choosing single image
});
context
.authorize()
.then(function () {
return context.present();
})
.then(function (selection) {
console.log("Selection done:");
setTimeout(() => {
selection.forEach(function (selected) {
selected.getImage().then((source) => {
console.log(selected.fileUri); // this is the uri you need
});
});
}, 1000);
}).catch(function (e) {
console.log(e);
});
I was facing the exact same error yesterday.
I use the fromAsset function directly on the "selected" because apparently with the new version of this plugin, "selected" is an Asset. So you got an imageSource and you can use the "saveToFile" function that will copy the Asset into a new location (get this location using fileSystemModule from TNS). Use the path of this new location for your UI, and the image will appear. You can also create a file object from this location fileSystemModule.File.fromPath(path);, I use for upload.
context
.authorize()
.then(function () {
return context.present();
})
.then(function (selection) {
selection.forEach(function (selected) {
let file;
if (selected._android) {
file = fileSystemModule.File.fromPath(selected._android);
//viewModel.uploadFile(file);
}else{
imageSourceModule.fromAsset(selected).then((imageSource) => {
const folder = fileSystemModule.knownFolders.documents().path;
const fileName = "Photo.png";
const path = fileSystemModule.path.join(folder, fileName);
const saved = imageSource.saveToFile(path, "png");
if (saved) {
console.log("Image saved successfully!");
file = fileSystemModule.File.fromPath(path);
//viewModel.uploadFile(file);
}else{
console.log("Error! - image couldnt save.");
}
});
}
});
}).catch(function (e) {
console.log(e);
// process error
});
Explanation
The uncommented snippet (//viewModel.uploadFile(file);), viewModel reference (will be different on your app) and the function: uploadFile for example is where you would pass the file to upload it or set it to the image.src etc
Make sure to declare imageSourceModule at the top.
const imageSourceModule = require("tns-core-modules/image-source");

How to prevent validate function call while calling model.save in backbone JS

I have a backbone view where I call model.save to create/updated date submitted in the form. Before calling the save I explicitly call model.isValid(true) to validate the form fields then I process the form data to make it ready for API expected format (by adding or modifying additional fields) and then make call to mode.save function which is again triggering validate function where the validations are getting failed due to the modified data. As I have already called the isValid function explicitly, I want to prevent the call again during save. How can I do it in backbone. Here is sample code.
var data = Backbone.Syphon.serialize($(e.currentTarget).closest('form.my_form')[0]));
this.model.set(data);
if(this.model.isValid(true)) {
data['metas'] = this.context.metaData;
data['metas'][0]['locale'] = this.parentObj.model.get('locale');
data['metas'][0]['name'] = data['name'];
delete data['name'];
}
var tempDynAttrs = [];
if(data['dynamicAttributes']){
$.each(data['dynamicAttributes'], function(index,obj) {
if(obj['attributeValue'] !== null && obj['attributeValue'] !== undefined ) {
tempDynAttrs.push({
attributeName: obj['attributeName'],
attributeValue: [obj['attributeValue']],
locale: data['defaultLocale'],
status: 'active'
});
}
});
}
data['dynamicAttributes'] = tempDynAttrs;
this.model.save(data, {
url: this.model.url(),
patch: true,
success : function(model, response) {
$('#headerMessage').html('Data is updated successfully');
},
error : function(model, response) {
$('#headerMessage').html('Error updating data');
}
});
} else {
$('#formPanel').animate({
scrollTop: $('.has-error').first().offset().top-50
}, 100);
return false;
}
Try passing {validate:false} in the save options, like
book.save({author: "Teddy"}, {validate:false});
According to change log of version 0.9.10:
Model validation is now only enforced by default in Model#save and no longer enforced by default upon construction or in Model#set, unless the {validate:true} option is passed.
So passing {validate:false} should do the trick.

How to handle server side validation in Ember-Data 1.0.0

I'm using Ember 1.2.0 and the latest Ember Data Beta and wonder, how to handle server side errors (from API calls).
This question is quite similar, but it doesn't work.
At first, the becameInvalid method doesn't triggered. I'm using ember-validations (do I have to?)
My API sends an 422 status code and responses like that:
{"errors":{"name":["has already been taken"],"initial":["has already been taken"]}}
model.js
Docket.Customer = DS.Model.extend( Ember.Validations, {
name: DS.attr('string'),
initial: DS.attr('string'),
description: DS.attr('string'),
validations: {
name: {
presence: true
}
},
becameError: function() {
alert('there was an error!');
},
becameInvalid: function(errors) {
alert("Record was invalid because: " + errors);
}
});
controller.js
Docket.OrganizationCustomersController = Ember.ArrayController.extend({
actions: {
save: function () {
var customer = this.store.createRecord('customer');
customer.set('name', this.get('name'));
customer.set('initial', this.get('initial'));
customer.set('description', this.get('description'));
customer.save().then(function() {
console.log('jeah')
}, function() {
console.log('nooo')
});
}
}
});
The becameError method gets fired, but the becameInvalid method doesn't.
The second problem: even if the error is triggered, Ember.js adds the new record to the DOM. How can I prevent this behaviour?
Your errors json is ok, I think you are using the DS.RESTAdapter, and it doesn't implement the becameInvalid based in json with errors.
Just DS.ActiveModelAdapter have implemented in the moment, so I recommend you to change your adapter configuration to:
Docket.ApplicationAdapter = DS.ActiveModelAdapter;
In order to keep DS.RestAdapter, you can override its ajaxError method with the one from ActiveModelAdapter.
As for today the code, slightly adapted because some dependencies are needed, would be :
App.ApplicationAdapter = DS.RESTAdapter.extend({
// ... your own customizations,
ajaxError: function(jqXHR) {
var error = this._super(jqXHR);
if (jqXHR && jqXHR.status === 422) {
var response = Ember.$.parseJSON(jqXHR.responseText),
errors = {};
if (response.errors !== undefined) {
var jsonErrors = response.errors;
Ember.EnumerableUtils.forEach(Ember.keys(jsonErrors), function(key) {
errors[Ember.String.camelize(key)] = jsonErrors[key];
});
}
return new DS.InvalidError(errors);
} else {
return error;
}
}
});
Obviously you have a chance here to adapt to your backend specifics: HTTP code (422 is not a standard one) and format.
Source :
http://discuss.emberjs.com/t/how-to-handle-failure-to-save-on-server/3789

How can I can the scope which the onComplete function is called

I have created a wrapper for the FineUploaderBasic class in order to link it in with my existing system and when the onComplete function is called it is called in the scope of the FineUploaderBasic element and not the parent element.
How can I change this or access the parent of the FineUploaderBasic Instance?
I have written the code using ExtJs as Follow's and I am trying to trigger my own upload complete event once the FineUploader upload has been completed. but the "onUploadComplete" function is being called within the scope of the FineUploader Instance and I am not able to access my own object.
Ext.define('X4.Core.FileUploader', {
mixins: {
observable: 'Ext.util.Observable'
},
uploader: null,
constructor: function (config) {
this.initConfig(config);
this.mixins.observable.constructor.call(this, config);
this.addEvents({
/**
* Event which is triggered once the file upload has been completed successfully.
*
* #since X4 4.1.1
*/
"uploadcomplete": true
});
return this;
},
getUploader: function () {
var me = this;
if (me.uploader === null) {
me.uploader = new qq.FineUploaderBasic({
autoUpload: false,
request: {
endpoint: '/_system/x4/commands/file_uploader.ashx'
},
callbacks: {
onComplete: me.onUploadComplete
}
});
}
return me.uploader;
},
onUploadComplete: function(id, name, response) {
var me = this;
alert('upload complete ' + id + ' ' + name + ' ' + response);
me.fireEvent('uploadcomplete', me.callbackScope, id, name, response);
},
addFile: function (fileInput) {
var me = this;
return me.getUploader().addFiles(fileInput.extractFileInput());
},
upload: function () {
var me = this;
me.getUploader().uploadStoredFiles();
}
});
Since you haven't provided any specific information about your problem, I'm going to have to provide a very generic answer. Also, since you have not specified if you are using the jQuery plug-in or not, I'll have to assume that you are not.
So, the answer to your question really has nothing to do with Fine Uploader. Assuming you are using the no-dependency version, Fine Uploader sets the context of the call to each callback/event handler to the associated Fine Uploader instance. You are asking for the "parent" element, ostensibly the parent element of the value you have specified for the element option.
You can determine the parent of any element/node via the node's parentNode property.

Resources