Adding Multiple attachments using yogiben - meteor

i am changing the question because i have decided to work with yogiben package..i want to include multiple attachment in my web app..following is my schema for attachment...
attachments:{
type: [Object],
optional: true,
autoform:{
afFieldInput: {
type: 'fileUpload',
collection: 'Images',
label: 'Choose file',
}
}
},
"attachments.$.id":{
type:String,
autoform:{
afFieldInput: {
type: 'fileUpload',
collection: 'Images',
label: 'Choose file',
}
}
},
and this is the FScollection i used
var imageStore = new FS.Store.GridFS("images",{});
Images = new FS.Collection("images", {
stores: [imageStore],
filter: {
maxSize: 10000000, // in bytes
allow: {
contentTypes: ``````````````['image/*','text/plain','application/vnd.openxmlformats- officedocument.presentationml.presentation','application/pdf','application/msword','application/vnd.openxmlformats-officedocument.wordprocessingml.document','application/vnd.openxmlformats-officedocument.spreadsheetml.sheet','application/vnd.ms-excel','application/xls','application/x-xls','application/zip','application/octet-stream','application/x-compressed','application/x-zip','application/x-zip-compressed'],
extensions: ['png','tif','pptx','jpeg','jpg','doc','docx','pdf','xlsx','xls','txt','gif','zip']
},
onInvalid: function (message) {
Materialize.toast(message,4000,'alert-failure');;
}
}
});

yogiben:autoform-file is the one I use, but you can find a nice amount of other packages here.
https://atmospherejs.com/packages/File%20Upload

You can also use collection FS.
They also provided a good documentation.
Here is Link

Related

Method to update users role is giving an error when using Collection2 package

Here is my method:
removeRole: function(role) {
check(role, String);
var user = Meteor.user();
if (!user || ! AccountsAdmin.checkForAdminAuthentication(user))
throw new Meteor.Error(401, "You need to be an authenticated admin");
// handle non-existing role
if (Meteor.roles.find({name: role}).count() < 1 )
throw new Meteor.Error(422, 'Role ' + role + ' does not exist.');
if (role === 'admin')
throw new Meteor.Error(422, 'Cannot delete role admin');
// remove the role from all users who currently have the role
// if successfull remove the role
Meteor.users.update(
{roles: role },
{$pull: {roles: role }},
{multi: true},
function(error) {
if (error) {
throw new Meteor.Error(422, error);
} else {
Roles.deleteRole(role);
}
}
);
},
Here is the error I receive when looking at the call in Kadira:
message: After filtering out keys not in the schema, your modifier is now empty
stack:
Error: After filtering out keys not in the schema, your modifier is now empty
at [object Object].doValidate (packages/aldeed_collection2-core/lib/collection2.js:282:1)
at [object Object]._.each.Mongo.Collection.(anonymous function) [as update] (packages/aldeed_collection2-core/lib/collection2.js:83:1)
at [object Object].Meteor.methods.removeRole (packages/accounts-admin-ui-bootstrap-3/server/methods.js:86:1)
Line 86 of that methods.js is "Meteor.users.update" in the code above. When trying to debug this using breakpoints it appears this is where the error is happening as well.
I am using this package to help with the user management UI that I am creating, although I have did some customizing to it. I have also tested this on a different version of my project for troubleshooting and I have found that it works when I don't use the Collection2 package.
Here is my custom schema setup:
Schema = {};
Schema.UserProfile = new SimpleSchema({
userProfile: {
type: Object
},
'userProfile.firstName': {
type: String,
optional: true,
label: "First Name"
},
'userProfile.lastName': {
type: String,
optional: true,
label: "Last Name"
},
'userProfile.birthday': {
type: Date,
optional: true,
label: "Date of Birth"
},
'userProfile.contactEmail': {
type: String,
optional: true,
label: "Email"
},
'userProfile.gender': {
type: String,
allowedValues: ['Male', 'Female'],
optional: true,
label: "Gender"
},
'userProfile.address': {
type: String,
optional: true,
label: "Address"
},
'userProfile.city': {
type: String,
optional: true,
label: "City"
},
'userProfile.stateProvince': {
type: String,
optional: true,
label: "State/Province"
},
'userProfile.postalCode': {
type: String,
optional: true,
label: "Postal Code"
},
'userProfile.phoneNumber': {
type: String,
optional: true,
label: "Phone Number"
},
userProfilePayment: {
type: Object
},
'userProfilePayment.paymentEmail': {
type: String,
optional: true,
label: "Payment Email"
},
'userProfilePayment.address': {
type: String,
optional: true,
label: "Address"
},
'userProfilePayment.city': {
type: String,
optional: true,
label: "City"
},
'userProfilePayment.stateProvince': {
type: String,
optional: true,
label: "State/Province"
},
'userProfilePayment.postalCode': {
type: String,
optional: true,
label: "Postal Code"
},
'userProfilePayment.phoneNumber': {
type: String,
optional: true,
label: "Phone Number"
},
});
Schema.User = new SimpleSchema({
username: {
type: String,
// For accounts-password, either emails or username is required, but not both. It is OK to make this
// optional here because the accounts-password package does its own validation.
// Third-party login packages may not require either. Adjust this schema as necessary for your usage.
optional: true
},
emails: {
type: Array,
// For accounts-password, either emails or username is required, but not both. It is OK to make this
// optional here because the accounts-password package does its own validation.
// Third-party login packages may not require either. Adjust this schema as necessary for your usage.
optional: true
},
"emails.$": {
type: Object
},
"emails.$.address": {
type: String,
regEx: SimpleSchema.RegEx.Email
},
"emails.$.verified": {
type: Boolean
},
createdAt: {
type: Date
},
profile: {
type: Schema.UserProfile,
optional: true
},
// Make sure this services field is in your schema if you're using any of the accounts packages
services: {
type: Object,
optional: true,
blackbox: true
},
// Add `roles` to your schema if you use the meteor-roles package.
// Option 1: Object type
// If you specify that type as Object, you must also specify the
// `Roles.GLOBAL_GROUP` group whenever you add a user to a role.
// Example:
// Roles.addUsersToRoles(userId, ["admin"], Roles.GLOBAL_GROUP);
// You can't mix and match adding with and without a group since
// you will fail validation in some cases.
roles: {
type: Object,
optional: true,
blackbox: true
},
// In order to avoid an 'Exception in setInterval callback' from Meteor
heartbeat: {
type: Date,
optional: true
},
// Added to work with mizzao:user-status
status: {
type: Object,
optional: true,
blackbox: true
}
});
Meteor.users.attachSchema(Schema.User);
Meteor.users.allow({
// NOTE: The client should not be allowed to add users directly!
insert: function(userId, doc) {
// only allow posting if you are logged in
console.log("doc: " + doc + " userId: " + userId);
return !! userId;
},
update: function(userId, doc, fieldNames) {
// only allow updating if you are logged in
console.log("doc: " + doc + " userId: " + userId);
// NOTE: a user can only update his own user doc and only the 'userProfile' and 'userProfilePayment' field
return !! userId && userId === doc._id && _.isEmpty(_.difference(fieldNames, ['userProfile, userProfilePayment']));
},
/* NOTE: The client should not generally be able to remove users
remove: function(userID, doc) {
//only allow deleting if you are owner
return doc.submittedById === Meteor.userId();
}
*/
});
To remove a key in a mongodb update you want to use the $unset operator:
Meteor.users.update({ roles: role },{ $unset: { roles: 1 }}, { multi: true })
It's just a bit unusual that in your model a user can only have a single role.

How to set a unique id for an embedded document in Meteor?

I have setup my collections like this using Simple Schema :
SubLinkSchema = new SimpleSchema({
name: {
type: String,
label: 'Link Name',
unique: false
},
link: {
type: String,
regEx: SimpleSchema.RegEx.Url,
label: 'Custom Link',
optional: true,
autoform: {
class: 'sub-custom-link'
}
}
});
LinkSchema = new SimpleSchema({
name: {
type: String,
label: 'Link Name',
unique: false
},
link: {
type: String,
regEx: SimpleSchema.RegEx.Url,
label: 'Custom Link',
optional: true,
autoform: {
class: 'main-custom-link'
}
},
subLinks: {
optional: true,
label: 'Sub Links',
unique: false,
type: [SubLinkSchema]
}
});
In here, the problem is, the sublinks do not get an ID. Its hard to update them without an id. So, how can I generate a unique ID per sublink (embedded document)?
use an autovalue field in the SimpleSchema
see ref here:
https://github.com/aldeed/meteor-collection2#autovalue
and example:
subLinkID: {
type: String,
autoValue: function() {
return Meteor.uuid();
}
}
It should go with the
Meteor.uuid()

How should I insert into Meteor collection using autoform/collection2?

I'm trying to do the autoform books example using Meteor. How exactly should I do the Books.insert ?
I see the example:
Books.insert({title: "Ulysses", author: "James Joyce"}, function(error, result) {
//The insert will fail, error will be set,
//and result will be undefined or false because "copies" is required.
//
//The list of errors is available on
//`error.invalidKeys` or by calling
Books.simpleSchema().namedContext().invalidKeys()
});
I'm not entirely sure how I should hook this up with the rest of my code:
if (Meteor.isClient) {
Books = new Meteor.Collection("books");
var Schemas = {};
Schemas.Book = new SimpleSchema({
title: {
type: String,
label: "Title",
max: 200,
optional: true
},
author: {
type: String,
label: "Author",
optional: true
},
copies: {
type: Number,
label: "Number of copies",
min: 0,
optional: true
},
lastCheckedOut: {
type: Date,
label: "Last date this book was checked out",
optional: true
},
summary: {
type: String,
label: "Brief summary",
optional: true,
max: 1000
}
});
Books.attachSchema(Schemas.Book);
}
Can anyone give me any advice on this?
I'm thinking that I would need something like this:
Template.bookform.events({
'click btn.submit': function () {
var form = document.getElementById("formID").value;
Books.insert(form);
}
});
Thanks in advance! :)
I have never used autoform but in the documentation it says that it already gives you "automatic insert and update events, and automatic reactive validation".
So there should be no need to specify your own event handler.
In the docs you will also find the books example. I am just copying from there:
JS
Books = new Meteor.Collection("books", {
schema: {
title: {
type: String,
label: "Title",
max: 200
},
author: {
type: String,
label: "Author"
},
copies: {
type: Number,
label: "Number of copies",
min: 0
},
lastCheckedOut: {
type: Date,
label: "Last date this book was checked out",
optional: true
},
summary: {
type: String,
label: "Brief summary",
optional: true,
max: 1000
}
}
});
if (Meteor.isClient) {
Meteor.subscribe("books");
}
if (Meteor.isServer) {
Meteor.publish("books", function () {
return Books.find();
});
}
HTML
<head>
<title>Book example</title>
</head>
<body>
{{> insertBookForm}}
</body>
<template name="insertBookForm">
{{> quickForm collection="Books" id="insertBookForm" type="insert"}}
</template>

ExtJS4.2 Grid Filter Leaves empty Rows with Paging - NewbieQ

I have tried various ways to refresh the grid but everything I try doesn't work. Do I refresh the Grid or do I load the store??? You can see that the paging tool bar is still showing 50 pages after the filtering. If there are no dates on a given pag and it is empty then it will disable the tool bar and paging doesn't work after that page un less you refresh the browser and skip over the empty page. So, in my case page 15 has no rows so it breaks when u hit next and get that page. If you type in the page number 16 then all is good until you hit another's empty page.
My datepicker is in my viewport below and I have tried refreshing the gird and loading the store as well as other things which mostly result in undefined error. Not sure where to start with this one so I will show my code and screen shots below:
BEFORE DATE SELECTION:
AFTER DATE SELECTION:
STORE:
Ext.define('AM.store.Users', {
extend: 'Ext.data.Store',
model: 'AM.model.User',
autoLoad: true,
autoSync:true,
pageSize:50,
proxy:
{
type: 'ajax',
//extraParams :{limit:1000},
api:
{
read: 'http://192.168.0.103/testit/dao_2.cfc?method=getContent',
update: 'http://192.168.0.103/testit/dao_2-post.cfc?method=postContent'
},
reader:
{
type: 'json',
root: 'data',
successProperty: 'success',
totalProperty : 'dataset',
remoteFilter : true
},
listeners:
{
// stuff goes here maybe??
}
}
});
GRID PANEL:
Ext.define('AM.view.user.List' ,{
extend: 'Ext.grid.Panel',
alias: 'widget.userlist',
title: 'All Users',
store: 'Users',
//buffered: true,
plugins:[Ext.create('Ext.grid.plugin.RowEditing', {clicksToEdit: 2})],
dockedItems: [{ xtype: 'pagingtoolbar',
store: 'Users',
dock: 'bottom',
displayMsg: 'Displaying Records {0} - {1} of {2}',
displayInfo: true}],
initComponent: function() {
this.columns = [
Ext.create('Ext.grid.RowNumberer',
{
resizable: true,
resizeHandles:'all',
align: 'center',
minWidth: 35,
maxWidth:50
}),
{
header: 'Name',
dataIndex: 'message_id',
flex: 1,
editor:'textfield',
allowBlank: false,
menuDisabled:true
},
{
header: 'Email',
dataIndex: 'recip_email',
flex: 1,
editor:'textfield',
allowBlank: false,
menuDisabled:true
},
{
header: 'Date Time',
dataIndex: 'unix_time_stamp',
width: 120,
menuDisabled:true,
// submitFormat: 'd/m/Y',
renderer: Ext.util.Format.dateRenderer('m/d/Y'),
field:{ xtype:'datefield',
autoSync:true,
allowBlank:false,
editor: new Ext.form.DateField(
{format: 'm/d/y'}) }
}];
this.callParent(arguments);
},
});
VIEWPORT:
Ext.Loader.setConfig({enabled:true});
Ext.application({
requires: ['Ext.container.Viewport'],
name: 'AM',
appFolder: 'app',
controllers: ['Users'],
launch: function() {
Ext.create('Ext.container.Viewport', {
layout: 'border',
items:[{
region: 'center',
itemId:'centerPanelRegion',
title:'The Title',
xtype: 'tabpanel',
hidden: true,
activeTab: 0,
items:[{
xtype: 'userlist',
listeners:
{
select: function(selModel, record, index, options)
{
// do something with the selected date
console.log('select');
},
add: function(selModel)
{
// do something with the selected date
console.log('add - init2.js');
},
afterrender:function(selModel)
{
// do something with the selected date
console.log('afterrender - userlist(init2.js)');
},
beforerender:function(selModel)
{
// do something with the selected date
console.log('beforerender - userlist(init2.js)');
}
}
}]
},
{
region: 'west',
itemId:'westPanelRegion',
hidden: true,
layout:'fit',
xtype: 'tabpanel',
activetab:0,
collapsible:false,
split: false,
title: 'The Title',
width:178,
maxWidth:400,
height: 100,
minHeight: 100,
items:[{
title: 'Tab 1',
xtype:'panel',
items:
[{
xtype: 'datepicker',
itemId:'datePickerFld',
listeners:{
beforerender: function(){
console.log('datepicker - beforerender(init2.js)');
var store = Ext.getStore('dates');
store.load({callback: function(){
console.log('datepicker - callback(init2.js');
console.log(store.data.items[999].data.recip_email);
console.log(store.data.items[999].data.unix_time_stamp);
}
})
}
},
handler: function(picker, date)
{
// do something with the selected date
console.log('date picker example in init2.js' + Ext.Date.format(date,'m/d/Y'));
// get store by unique storeId
var store = Ext.getStore('Users');
// clear current filters
store.clearFilter(true);
// filter store
Ext.encode(store.filter("unix_time_stamp", Ext.Date.format(date,'m/d/Y')));
//store.load();
//store.sync();
}
}]
},
{
title: 'Tab 2',
html: 'ers may be added dynamically - Others may be added dynamically',
}]
}]
});
}
});
CONTROLLER:
Ext.define('AM.controller.Users', {
extend: 'Ext.app.Controller',
stores:['Users', 'dates'],
models:['User', 'date'],
views: ['user.List','user.Edit'],
init: function() {
Ext.getStore('dates').addListener('load',this.ondatesStoreLoad, this);
this.control(
{
'viewport > userlist':
{
itemdblclick: this.editUser,
},
'useredit button[action=save]':
{
click: this.updateUser
}
});
},
// ---------- handler Function declarations -------------
ondatesStoreLoad: function(me,records,success)
{
// ------ Gets the dates from dates store and loads an array
var store = this.getStore('dates');
sendDataArray = [];
store.each(function(record){
var recordArray = [record.get("unix_time_stamp")];
sendDataArray.push(recordArray);
});
// ------ Set DatePicker Bullshit right fucking here --------//
var dtFld = Ext.ComponentQuery.query('#datePickerFld')[0];
dtFld.setDisabledDates(["^(?!"+sendDataArray.join("|")+").*$"]);
dtFld.setMaxDate(new Date());
dtFld.setMinDate(new Date('05/01/2013'));
var wstPnlReg = Ext.ComponentQuery.query('#westPanelRegion')[0];
wstPnlReg.show();
var ctrPnlReg = Ext.ComponentQuery.query('#centerPanelRegion')[0];
ctrPnlReg.show();
// var grid = Ext.widget('userlist');
},
onUsersStoreDataChange: function(me)
{
//console.log('Hey the store data just changed!');
},
editUser: function(grid, record)
{
var view = Ext.widget('useredit');
view.down('form').loadRecord(record);
},
updateUser: function(button)
{
var win = button.up('window'),
form = win.down('form'),
record = form.getRecord(),
values = form.getValues();
record.set(values);
win.close();
this.getUsersStore().sync();
},
});
UPDATED VIEWPORT: Changes made only in datepicker handler
Ext.Loader.setConfig({enabled:true});
Ext.application({
requires: ['Ext.container.Viewport'],
name: 'AM',
appFolder: 'app',
controllers: ['Users'],
launch: function() {
Ext.create('Ext.container.Viewport', {
layout: 'border',
items:[{
region: 'center',
itemId:'centerPanelRegion',
title:'The Title',
xtype: 'tabpanel',
hidden: true,
activeTab: 0,
items:[{
xtype: 'userlist',
listeners:
{
select: function(selModel, record, index, options)
{
// do something with the selected date
console.log('select');
},
add: function(selModel)
{
// do something with the selected date
console.log('add - init2.js');
},
afterrender:function(selModel)
{
// do something with the selected date
console.log('afterrender - userlist(init2.js)');
},
beforerender:function(selModel)
{
// do something with the selected date
console.log('beforerender - userlist(init2.js)');
}
}
}]
},
{
region: 'west',
itemId:'westPanelRegion',
hidden: true,
layout:'fit',
xtype: 'tabpanel',
activetab:0,
collapsible:false,
split: false,
title: 'The Title',
width:178,
maxWidth:400,
height: 100,
minHeight: 100,
items:[{
title: 'Tab 1',
xtype:'panel',
items:
[{
xtype: 'datepicker',
itemId:'datePickerFld',
listeners:{
beforerender: function(){
console.log('datepicker - beforerender(init2.js)');
var store = Ext.getStore('dates');
store.load({callback: function(){
console.log('datepicker - callback(init2.js');
console.log(store.data.items[999].data.recip_email);
console.log(store.data.items[999].data.unix_time_stamp);
}
})
}
},
handler: function(picker, date)
{
// do something with the selected date
console.log('date picker example in init2.js' + Ext.Date.format(date,'m/d/Y'));
// get store by unique storeId
var store = Ext.getStore('Users');
// clear current filters
store.clearFilter(true);
// filter store
store.filter("unix_time_stamp", Ext.Date.format(date,'m/d/Y'));
// Load the store
store.load();
}
}]
},
{
title: 'Tab 2',
html: 'ers may be added dynamically - Others may be added dynamically',
}]
}]
});
}
});
This line is likely causing the issues.
Ext.encode(store.filter("unix_time_stamp", Ext.Date.format(date,'m/d/Y')));
I'm not sure why you are calling Ext.encode on whatever store.filter returns, but I don't think you want to do that (and it is likely causing the undefined errors).
As for the paging toolbar not updating the current count, it is likely you just aren't returning the correct information in your server response when updating the store. The server response should include the total number of records. According to the docs for Ext.toolbar.Paging, http://docs.sencha.com/extjs/4.2.2/#!/api/Ext.toolbar.Paging:
The packet sent back from the server would have this form:
{
"success": true,
"results": 2000,
"rows": [ // ***Note:** this must be an Array
{ "id": 1, "name": "Bill", "occupation": "Gardener" },
{ "id": 2, "name": "Ben", "occupation": "Horticulturalist" },
...
{ "id": 25, "name": "Sue", "occupation": "Botanist" }
]
}

populate the combobox dynamically in ExtJs

I want to populate the combobox dynamically based on the data I received from thr Url(which is servlet)
Below is my ExtJS code :
{
xtype:'combo',
id: 'shoutoutsTags',
fieldLabel: 'Tag',
value: '',
mode: 'local',
width: 200,
store: new Ext.data.JsonStore({
id:'ms',
url:'http://localhost:8080/ezdi/extServlet',
//totalProperty:'totalCount',
root:'rows',
fields:[
{name:'un'},
{name:'pwd'}
],
autoLoad:true
}),
displayField: 'un',
valueField: 'pwd',
typeAhead:true,
minChars:1,
forceSelection: true,
triggerAction: 'all',
hideTrigger:true
//hiddenName: 'mytag'
}
But I am getting below error and my Url is not being called:
msg : "You are using a ServerProxy but have not supplied it with a url."
sourceClass : "Ext.data.proxy.Server"
sourceMethod : "buildUrl" uncaught exception: You are using a ServerProxy
but have not supplied it with a
url.
Suggest me how can I overcome this error.
Ext.define("modelname", {
extend: 'Ext.data.Model',
proxy: {
type: 'ajax',
url : '/myServlet',
method:'POST',
reader: {
type: 'json',
root: 'rows'
//,totalProperty: 'totalCount'
}
},
fields: [
{name: 'name', mapping: 'name'}
]
});
var ds = Ext.create('Ext.data.Store', {
pageSize: 10,
model: 'modelName'
});
Your store needs to be updated to use the new Ext JS 4 data model:
var store = Ext.create('Ext.data.Store', {
model: 'MyNamespace.StoreModel',
proxy: {
type: 'ajax',
url: 'http://localhost:8080/ezdi/extServlet',
reader: {
type: 'json',
root: 'rows',
totalProperty: 'totalCount'
}
}
});
You'll notice here that the store has a property 'model', which is a string, and that there is no field mapping. This is because you'll also need to create a model for the store to reference, like so:
Ext.define('MyNamespace.StoreModel', {
extend: 'Ext.data.Model',
fields: [
{name:'un'},
{name:'pwd'}
]
});
Hope this helps!
Thats not a valid url, you'll want just '/ezdi/extServlet'.

Resources