Code works after page load but not during - javascript

I'm working on an app for internal company use and I'm publishing a list of users that qualify as "supervisor" (using alanning:roles.)
I'm also using useraccounts:bootstrap to collect additional information of each user during registration like who their supervisor is.
I have a function that returns the information I need but it only works when I run it in the browser console after the site has loaded.
If I build the array manually and return it, everything works as expected. The point, of course, is that this should be dynamic and grow as the userbase grows.
About all I know is that the code is not running in the context/order I think it is. I've tried various different things just to see what would happen like moving routes.js into /lib (from /client), moving the function definition into a different file, and more!
How can I correct this? I'm fairly new to Meteor so it's completely possible I'm making some other huge mistake and this difficulty I'm having is just a symptom of that. If so, please let me know!
/server/publications.js
Meteor.publish('supervisor-list', function() {
var criteria = {
roles: {$in: ['supervisor']}
};
var options = {
fields: {
'profile.firstName': 1
, 'profile.lastName': 1
}
};
return Meteor.users.find(criteria, options);
});
/client/routes.js
Router.configure({
layoutTemplate: 'layout'
, loadingTemplate: 'loading'
, notFoundTemplate: '404'
, waitOn: function () {
return [
Meteor.subscribe('transactions')
, Meteor.subscribe('supervisor-list')
];
}
, yieldTemplates: {
nav: {to: 'nav'}
, footer: {to: 'footer'}
}
});
/lib/1functions.js
getSupervisors = function () {
var output = [];
var supervisors = Meteor.users.find().fetch();
for (var i = 0; i < supervisors.length; i++) {
output.push({
text: supervisors[i].profile.firstName + ' ' + supervisors[i].profile.lastName
, value: supervisors[i]._id
});
}
//output = [
// {text: 'Person One', value: 'personone'}
// , {text: 'Person Two', value: 'persontwo'}
// , {text: 'Person Three', value: 'personthree'}
//];
return output;
};
/lib/at_config.js
AccountsTemplates.addField({
_id: 'supervisorEmail'
, type: 'select'
, select: getSupervisors()
, required: true
});

Have a look at the Meteor docs (scroll down a bit to "File load order"). /lib/at_config.js is loaded before /lib/functions.js, so getSupervisors is not defined at that point yet.
Not sure how your code is structured in general, so I can not give any pointers as to how I would do this. The documentation is your friend here.

Related

Finding results that are part of a set with FlexSearch

I have an app that uses FlexSearch. In this app, I have an array of items that looks like this:
let results = [
{ id:'a', name:'The title', status:'in-stock' },
{ id:'b', name:'Another title', status:'out-of-stock' },
{ id:'c', name:'Some other', status:'discontinued' },
];
const resultSchema = {
id: 'id',
field: [
'name',
'status'
]
};
const resultIndex = new FlexSearch({
profile:'score',
doc: resultSchema
});
resultIndex.add(results);
My page has checkboxes for the statuses (in-stock, out-of-stock, and discontinued). My question is, how do I find results that are either a) in-stock or b) out-of-stock. I do not see a way to perform logical ORs with the where function. For example, I'd like to be able to say, give me all results that are either in-stock or out-of-stock. From a logical perspective, one could say, give me everything that is NOT discontinued. However, this is not my entire data set. For that reason, I'm trying to figure out how to do ORs within Flexsearch.
Thank you!
See the section Logical Operators in the readme. This seems to work:
const res = resultIndex.search([
{ field: 'status', query: 'in-stock', bool: 'or' },
{ field: 'status', query: 'out-of-stock', bool: 'or' },
]);
Strangely, { field: 'status', query: 'discontinued', bool: 'not' } didn't work when I tried it.
Doesn't using a custom function solve your problem?(found it in the document)
Something like this:
resultIndex.where(function(item){
return item.status === "in-stock" || item.status === "out-of-stock";
});

How to get React to listen for a click event called in Jquery

I'm using dabeng/OrgChart in a react app. When the user clicks on a node Jquery populates an input box. An example of this can be seen here.
I want react to do this instead of Jquery so I can save the selected node in state instead of the inputbox holding a value.
I've tried things like using references, tried to see if I can call a react method within the jquery function but no joy.
Maybe a publisher/subscriber model would be the solution but not sure how to implement something like that.
class OrgTreeBase extends Component {
state = {
list: {
'name': 'Ball game',
'children': [
{
'name': 'Football',
'children': [
{
'name': 'man united',
'children': [
{ 'name': 'fred' },
{ 'name': 'ander herrera' },
{ 'name': 'scott mctominay' },
]
}
]
},
{
'name': 'Basketball',
'children': [
{'name': 'lakers'},
{ 'name': 'warriors' },
]
},
{ 'name': 'Volleyball' }
]
},
currentLevel: 0,
currentItem: [],
selectedItem: '',
};
componentDidMount() {
this.$el = $(this.el);
let datasource = this.state.list;
this.getId = () => {
return (new Date().getTime()) * 1000 + Math.floor(Math.random() * 1001);
}
//creates the initial chart with the following settings
var oc = $('#chart-container').orgchart({
'data': datasource,
'chartClass': 'edit-state',
'exportButton': true,
'exportFilename': this.state.name,
'parentNodeSymbol': 'fa-th-large',
'createNode': function ($node, data) {
$node[0].id = this.getId;
},
})
//when node is selected
oc.$chartContainer.on('click', '.node', function () {
var $this = $(this);
console.log("this is : " + $this.find('.title').text());
$('#selected-node').val($this.find('.title').text()).data('node', $this);
});
...
onNodeSelected = (node) => {
console.log(node + " was selected");
}
I want to see this.onNodeSelected() called when a node is clicked.
onNodeSelected = (node) => {
console.log(node + " was selected");
}
Thanks in advance for any help you can give me on this.
IMO you're already committed to using jQuery with this library. So I don't see why you can't just do something like this let's say:
//somewhere above
const self = this;
//when node is selected
oc.$chartContainer.on('click', '.node', function () {
var $this = $(this);
console.log("this is : " + $this.find('.title').text());
$('#selected-node').val($this.find('.title').text()).data('node', $this);
//set state and save node here on click. Or the node's text value
self.setState({})
});
Since, this isn't within your requirements I should say that the reason I suggest this is because the DOM appears to be generated by the orgChart library and adding react listeners to that is difficult. And there isn't any reason why you can't call react setState inside a jQuery click function.
It would also be wrong of me to suggest this without adding the warning that jQuery and React are both pretty large libraries that do largely similar-ish things. You probably already know that but, I still want to suggest finding a different organization library or make your own with React.

Magento filters SOAP v2 with Node JS / soap package

I am trying to use the filter for Magento SOAP v2 (Magento 1) but my code doesn't seem to work. I tried several ways of building to object with arrays but none of them seems to affect the returning results.
Can anybody explain me the right way to do that?
What I want to do is pull in all invoices but for example with a specific invoice ID or date.
Link to official Magento documentation:
http://devdocs.magento.com/guides/m1x/api/soap/sales/salesOrderInvoice/sales_order_invoice.list.html
This is my current code:
const filter = {
'complex_filter': [
{
key: 'invoice_id',
value: {
key: 'eq',
value: '94'
}
}
]
};
client.salesOrderInvoiceList(res, filter, function(error, result) {
console.log(result.result)
});
In the above example I only tried to use the filter for the invoice ID but I also tried with the date but that didn't work out either.
Thanks in advance.
For me, the easiest solution was to just map exactly to what the XML document would look like if this was done by PHP SoapClient.
const args = {
sessionId: session_id,
storeView: store_id,
filters: {
complex_filter: {
complexObjectArray: {
key: 'created_at',
value: {
key: 'from',
value: '2017-01-01'
}
}
}
}
};
client.catalogProductList(args, (err, result) => { ... }

Rally SDK: Retrieving all available State values for Defects

I want to retrieve all available State values for Rally Defect.
The following code works good for Features:
this.states = [];
this.stateStore = Ext.create('Ext.data.Store', {
fields: ['_ref', 'name']
});
Ext.create('Rally.data.wsapi.Store', {
model: 'State',
autoLoad: true,
filters: [
{
property: 'Enabled',
operation: '=',
value: true
},
{
property: 'TypeDef.Name',
operation: '=',
value: 'Feature'
}
],
listeners: {
load: function (store, data) {
for (var i = 0; i < data.length; i++) {
this.stateStore.add({ '_ref': data[i].data._ref, 'name': data[i].data.Name });
}
this.statesLoaded = true;
this._initialLoad();
},
scope: this
}
});
With this approach, we load all available State values for features. However, when I change 'Feature' TypeDef.Name filter to 'Defect', I get nothing despite the fact that there are many active States for Defect defined.
Does anybody know why this happens and how get State values for Defect?
Maybe Defects use some other states, not like features, suer stories etc?
In WS API there is a full State object that represents State of PortfolioItems. It is different from the State or ScheduleState of such artifacts as Defect or UserStory, which are only string values in the dropdown field. There is no such thing as State.Name for a Defect.
Using promises, this may look like this:
launch: function(){
this._getModel().then({
success: this._getAllowedValues,
scope:this
}).then({//...})
},
_getModel:function(){
return Rally.data.ModelFactory.getModel({
type:'Defect'
});
},
_getAllowedValues:function(model){
var deferred = Ext.create('Deft.Deferred');
var allowedStateValues = [];
model.getField('State').getAllowedValueStore().load({
callback: function(records,operation,success){
Ext.Array.each(records,function(allowedValue){
allowedStateValues.push(allowedValue.get('StringValue'));
});
if(success){
deferred.resolve(allowedStateValues);
}
else{
deferred.reject();
}
}
}) ;
return deferred.promise;
},//...
See this example that retrieves allowed values for Priority and Severity of defects. Since those allow null values, null values are removed in this app example, but State does not have null values so you may skip that step.

Enyo Collection Merge Strategy

Below is the function I have used to fetch more photos from a service provider once clicked on more button:
showMore: function(){
this.$.resultList.collection.fetch({strategy:"merge",rpp:50});
}
This will call the fetch method defined in collection,
fetch: function(opts) {
this.params = {
feature: this.methodType || "popular",
image_size: 3,
sort: "created_at",
rpp: opts && opts.rpp || 25
};
return this.inherited(arguments);
},
This is working fine, but the problem is once more button is clicked, it should fetch another set of 25 photos and append it to my collection, but what actually happening is sometimes, it shows only say 5 photos along with previous photos .
What I understand by "merge" strategy is, if the records received is same as previous records, it will take only those records which are different from previously fetched records and updates the primarykey of the duplicate records.So one reason i am able to figure out is that, may be, it is fetching 25 photos next time, but because most of them are same as before, it is showing only those which are different from the previous fetched photos.
If i go with the "add" strategy, it works fine for one time, i.e, it shows another set of 25 photos appended to the collection, most of them are again same. But if click on more button one more time, no records are being added to the collection.No idea why this is happening.
How should i approach, if i want to fetch only new photos and append it to the collection.
Using the merge strategy is the right approach. Your description of merge is mostly accurate except that it doesn't update the primary key but instead updates the data for existing records with the same primary key.
It's difficult to say why using "add" doesn't always work. If the records don't have a primary key (which is id by default), "add" and "merge" should always add the records to the collection (unless you're using mergeKeys). If they do have a primary key, it's possible that you're trying to add duplicate records which Enyo will complain about and abort. Check your console log.
Without code, the only other suggestion is to set breakpoints and step through enyo.Collection.merge.
Here's an example of fetching records into a collection. If you comment out setting the id, merge and add strategies will always add records. If you comment out the merge strategy, the code will eventually error when requesting more records.
enyo.kind({
name: "ex.MockSource",
kind: "enyo.Source",
fetch: function(rec, opts) {
if(rec instanceof enyo.Model) {
rec.setObject(Faker.Helpers.createCard());
} else if (rec instanceof enyo.Collection) {
var count = opts && opts.count || 25;
var cards = [];
for(var i=0;i<count;i++) {
var card = Faker.Helpers.createCard();
// artificial id to force merges
card.id = enyo.now()%40;
cards.push(card);
}
opts.success(cards);
}
}
});
enyo.store.addSources({
mock: "ex.MockSource"
});
enyo.kind({
name: "ex.App",
kind: "Scroller",
bindings: [
{from: ".data", to: ".$.list.collection"},
{from: ".data.length", to: ".$.count.content", transform: function(v) {
return enyo.format("Displaying %s records", v);
}}
],
components: [
{name: "count"},
{name: "list", kind: "DataRepeater", components: [
{kind: "onyx.Item", components: [
{name: "name"},
{name: "phone"}
], bindings: [
{from: ".model.name", to: ".$.name.content"},
{from: ".model.phone", to: ".$.phone.content"}
]}
]},
{kind: "onyx.Button", content: "More", ontap: "moreTapped"}
],
create: enyo.inherit(function(sup) {
return function() {
sup.apply(this, arguments);
this.set("data", new enyo.Collection({
defaultSource: "mock"
}));
this.fetchRecords();
};
}),
fetchRecords: function() {
this.data.fetch({
count: 5,
strategy: "merge"
});
},
moreTapped: function() {
this.fetchRecords();
}
});
new ex.App().renderInto(document.body);

Categories