WL JSONStore Sort key <field> is not one of the valid strings - ibm-mobilefirst

I am having an error when trying to sort doing a findAll:
"Sort key dateis not one of the valid strings."
My options are the following (I tried different formats for desc, everyone was throwing the same 'error'):
var options = {sort: [{"date": "desc"}]};
Everything seems fine, the JSONStore works as expected, sorting the returned data, I just want to be sure that the 'error' is indeed a bug or mistake on the worklight.js part and not that I am doing something wrong.
This is the function that checks for a valid sortObj in worklight.js:
/** Checks if sortObj is a valid sort object for a query
* #private
*/
var __isValidSortObject = function(sortObj, searchFields, additionalSearchFields) {
var propertiesValidated = 0,
sortObjKey, sortStr;
for (sortObjKey in sortObj) {
if (sortObj.hasOwnProperty(sortObjKey)) {
if (propertiesValidated > 0) {
WL.Logger.trace('Sort object ' + JSON.stringify(sortObj) + ' has more than one property. Each object must have only one property.');
return false;
}
//check is sortObjKey is lowerCase
if (_.isUndefined(searchFields[sortObjKey.toLowerCase()]) && _.isUndefined(additionalSearchFields[sortObjKey.toLowerCase()])) {
WL.Logger.trace('Sort key ' + sortObjKey + ' is not part of search fields: ' + JSON.stringify(searchFields) + ' or additional search fields: ' + JSON.stringify(additionalSearchFields));
return false;
}
sortStr = sortObj[sortObjKey];
//Check that the string that specifies sorting order says either "asc" or "desc"
**if (__isString(sortStr) && sortStr.length > 0 && (/^(a|de)sc$/i.test(sortStr))) {
WL.Logger.trace('Sort key ' + sortObjKey + 'is not one of the valid strings.');
propertiesValidated++;
} else {
// Here seems to be the problem, shouldn't the trace be before return false?
return false;
}**
}
}
if (propertiesValidated === 0) {
return false;
}
return true;
};
You can clearly see that they do the WL.Logger.trace when the check is fine and that it should be just before return false.
Does anyone that has used sort on a JSONStore receives this trace as well?.
Platform version: 7.1.0.00.20160129-1923

I contacted IBM support and they indeed confirmed that it is a bug that will be solved in the next build.

Related

vue.js dynamically adding to a list of components

I'm having trouble dynamically adding to a list of components.
I've defined the list in the data element "things" of the vue document. For each object in "things" there is a component loaded onto the page
data() {
return {
things: []
}
}
I use something like the code below to load each of the things on the page.
<div v-for="thing in things" :key="thing.objectId">
Then I load in more elements and add them to the list
let temp = JSON.parse(JSON.stringify(results))
vm.things = vm.things.concat(temp)
And when I run it in dev I get the following
[Vue warn]: You may have an infinite update loop in a component render
function.
Other then the error message, the code works in dev mode but crashes the browser when run in production.
I've narrowed it down to this code, there is a bit in the loop which prints out a heading which is the month the data belongs to, so it might say January, then list all the data under january, then onto the next month and so on
showDate(data) {
this.currentDataMonth = helperfunctionsgetDate_format_month_year(data)
if (this.currentDataMonth != this.currentmonth) {
this.currentmonth = this.currentDataMonth
return "<h2>" + this.currentmonth + "</h2>"
} else {
return ""
}
Your issue is caused by the fact that you both modify the state, and use the state from the same method.
showDate(data) {
this.currentDataMonth = helperfunctionsgetDate_format_month_year(data) // set of the state
if (this.currentDataMonth != this.currentmonth) { // get of the state
this.currentmonth = this.currentDataMonth
return "<h2>" + this.currentmonth + "</h2>"
} else {
return ""
}
Since you directly use those variables inside your function, make them local to the function
showDate(data) {
const currentDataMonth = helperfunctionsgetDate_format_month_year(data)
if (currentDataMonth != undefined) {
const currentmonth = currentDataMonth
return "<h2>" + currentmonth + "</h2>"
} else {
return ""
}
Since the purpose of the code is to list every month under its own heading, you should do that using a computed function to return a list of data per month, and use 2 loops to loop over that

How to do an "or" in chai should

How do I do an or test with chai.should?
e.g. something like
total.should.equal(4).or.equal(5)
or
total.should.equal.any(4,5)
What's the right syntax? I couldn't find anything in the documentation.
Asserts that the target is a member of the given array list. However, it’s often best to assert that the target is equal to its expected value.
expect(1).to.be.oneOf([1, 2, 3]);
expect(1).to.not.be.oneOf([2, 3, 4]);
https://www.chaijs.com/api/bdd/#method_oneof
Viewing the Chai expect / should documentation, there are several ways to do this test.
Note that you can chain using "and" but apparently not "or" - wish they had this functionality.
Check whether an object passes a truth test:
.satisfy(method)
#param{ Function }matcher
#param{ String }message_optional_
Asserts that the target passes a given truth test.
Example:
expect(1).to.satisfy(function(num) { return num > 0; });
In your case, to test an "or" condition:
yourVariable.should.satisfy(function (num) {
if ((num === 4) || (num === 5)) {
return true;
} else {
return false;
}
});
Check whether a number is within a range:
.within(start, finish)
#param{ Number }startlowerbound inclusive
#param{ Number }finishupperbound inclusive
#param{ String }message_optional_
Asserts that the target is within a range.
Example:
expect(7).to.be.within(5,10);
I have a similar problem to write tests to postman. I solved using the following script:
// delete all products, need token with admin role to complete this operation
pm.test("response is ok and should delete all products", function() {
pm.expect(pm.response.code).to.satisfy((status) => status === 204 || status === 404);
});
Here, I shared exactly what you need to check.
expect(true).to.satisfy(() => {
if (total == 4 || total == 5) return true;
else return false;
});
Because chai assertions throw error you could use try/catch construction:
try {
total.should.equal(4)
} catch (e) {
total.should.equal(5)
}
example of more difficult case:
try {
expect(result).to.have.nested.property('data.' + options.path, null)
} catch (e) {
expect(result).to.have.property('data', null)
}

Registering plugin on quick find in Dynamics CRM 2013

I have to register a plugin on Quick Find search on "Artilce" entity. When user enter any thing in quick find text box on Article entity at that time my plugin execute and return filter the data based on our business logic.
1.What event is fired when we find using quick find.
2.What message passes when this event is fired.
I have tried registering the plugin on RetrieveMultiple message but this is not triggered when we click on search in quick find.
Please help.
We have a Plugin registered on the RetrieveMultiple. We had a business requirement to search for the records, using WildCard by default.
Plugin Registration Details:
Message: RetrieveMultiple
Primary Entity:None
Secondary Entity:None
Pre-Operation
Code:
public const String QueryLiteral = "Query";
public const String LIKE = "%";
public void Execute(IServiceProvider serviceProvider)
{
String ParentEntity = String.Empty;
String OriginalSearch = String.Empty;
// Obtain the execution context from the service provider.
var ContextInstance = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
// Get a reference to the Organization service.
IOrganizationService ServiceInstance =
((IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory))).
CreateOrganizationService(ContextInstance.InitiatingUserId);
// Critical Point here - NOTICE that the InputParameters Contains the word Query
if (ContextInstance.Depth < 2 && ContextInstance.InputParameters.Contains(QueryLiteral) &&
ContextInstance.InputParameters[QueryLiteral] is QueryExpression)
{
QueryExpression QueryPointer = (ContextInstance.InputParameters[QueryLiteral] as QueryExpression);
//Verify the conversion worked as expected - if not, everything else is useless
if (null != QueryPointer)
{
// Check if the request is coming from any Search View
// We know this b/c Criteria isn't null and the Filters Count > 1
if (null != QueryPointer.Criteria && QueryPointer.Criteria.Filters.Count > 1)
{
ParentEntity = ContextInstance.PrimaryEntityName;
OriginalSearch = QueryPointer.Criteria.Filters[1].Conditions[0].Values[0].ToString();
OriginalSearch = String.Format(CultureInfo.CurrentCulture,
"{0}{1}", LIKE, OriginalSearch);
}
ConditionExpression NewCondition = null;
FilterExpression NewFilter = null;
if (null != QueryPointer.Criteria)
{
//Change the default 'BeginsWith'Operator to 'Contains/Like' operator in the basic search query
foreach (FilterExpression FilterSet in QueryPointer.Criteria.Filters)
{
foreach (ConditionExpression ConditionSet in FilterSet.Conditions)
{
if (ConditionSet.Operator == ConditionOperator.Like)
{
if (OriginalSearch != "")
ConditionSet.Values[0] = OriginalSearch;
else
{
OriginalSearch = QueryPointer.Criteria.Filters[0].Conditions[0].Values[0].ToString();
OriginalSearch = String.Format(CultureInfo.CurrentCulture,
"{0}{1}", LIKE, OriginalSearch);
ConditionSet.Values[0] = OriginalSearch;
}
}
}
}
}
}
ContextInstance.InputParameters[QueryLiteral] = QueryPointer;
}
}
Check details on this Post: http://www.williamgryan.mobi/?p=596
We have raised a ticket with Microsoft to address this situaation.
The solution they provided was to modify the Database to make the message
SearchByTitleKbArticleRequest available in the plugin registration tool.
I currently dont remember the table that we updated a flag against these messages.
After updating the table we were able to register the plugin against the message
SearchByTitleKbArticleRequest
Then the plugin triggered and we modified the entity collection returned from there.

Using boolean fields with Magento ORM

I am working on a backend edit page for my custom entity. I have almost everything working, including saving a bunch of different text fields. I have a problem, though, when trying to set the value of a boolean field.
I have tried:
$landingPage->setEnabled(1);
$landingPage->setEnabled(TRUE);
$landingPage->setEnabled(0);
$landingPage->setEnabled(FALSE);
None seem to persist a change to my database.
How are you supposed to set a boolean field using magento ORM?
edit
Looking at my database, mysql is storing the field as a tinyint(1), so magento may be seeing this as an int not a bool. Still can't get it to set though.
This topic has bring curiosity to me. Although it has been answered, I'd like to share what I've found though I didn't do intense tracing.
It doesn't matter whether the cache is enabled / disabled, the table schema will be cached.
It will be cached during save process.
Mage_Core_Model_Abstract -> save()
Mage_Core_Model_Resource_Db_Abstract -> save(Mage_Core_Model_Abstract $object)
Mage_Core_Model_Resource_Db_Abstract
public function save(Mage_Core_Model_Abstract $object)
{
...
//any conditional will eventually call for:
$this->_prepareDataForSave($object);
...
}
protected function _prepareDataForSave(Mage_Core_Model_Abstract $object)
{
return $this->_prepareDataForTable($object, $this->getMainTable());
}
Mage_Core_Model_Resource_Abstract
protected function _prepareDataForTable(Varien_Object $object, $table)
{
$data = array();
$fields = $this->_getWriteAdapter()->describeTable($table);
foreach (array_keys($fields) as $field) {
if ($object->hasData($field)) {
$fieldValue = $object->getData($field);
if ($fieldValue instanceof Zend_Db_Expr) {
$data[$field] = $fieldValue;
} else {
if (null !== $fieldValue) {
$fieldValue = $this->_prepareTableValueForSave($fieldValue, $fields[$field]['DATA_TYPE']);
$data[$field] = $this->_getWriteAdapter()->prepareColumnValue($fields[$field], $fieldValue);
} else if (!empty($fields[$field]['NULLABLE'])) {
$data[$field] = null;
}
}
}
}
return $data;
}
See the line: $fields = $this->_getWriteAdapter()->describeTable($table);
Varien_Db_Adapter_Pdo_Mysql
public function describeTable($tableName, $schemaName = null)
{
$cacheKey = $this->_getTableName($tableName, $schemaName);
$ddl = $this->loadDdlCache($cacheKey, self::DDL_DESCRIBE);
if ($ddl === false) {
$ddl = parent::describeTable($tableName, $schemaName);
/**
* Remove bug in some MySQL versions, when int-column without default value is described as:
* having default empty string value
*/
$affected = array('tinyint', 'smallint', 'mediumint', 'int', 'bigint');
foreach ($ddl as $key => $columnData) {
if (($columnData['DEFAULT'] === '') && (array_search($columnData['DATA_TYPE'], $affected) !== FALSE)) {
$ddl[$key]['DEFAULT'] = null;
}
}
$this->saveDdlCache($cacheKey, self::DDL_DESCRIBE, $ddl);
}
return $ddl;
}
As we can see:
$ddl = $this->loadDdlCache($cacheKey, self::DDL_DESCRIBE);
will try to load the schema from cache.
If the value is not exists: if ($ddl === false)
it will create one: $this->saveDdlCache($cacheKey, self::DDL_DESCRIBE, $ddl);
So the problem that occurred in this question will be happened if we ever save the model that is going to be altered (add column, etc).
Because it has ever been $model->save(), the schema will be cached.
Later after he add new column and "do saving", it will load the schema from cache (which is not containing the new column) and resulting as: the data for new column is failed to be saved in database
Delete var/cache/* - your DB schema is cached by Magento even though the new column is already added to the MySQL table.

How to restrict typing hyphen into extjs numberfield?

Currently extjs numberfield is allowing '-' hyphen otherthan numbers into the field. how to restrict that from typing? if i give custom vtype validation it is checking only after i submit that.
use autoStripChars and remove hyphen from allowed in initComponent. corrected code below.
autoStripChars: true,
initComponent: function() {
var me = this,
allowed;
me.callParent();
me.setMinValue(me.minValue);
me.setMaxValue(me.maxValue);
// Build regexes for masking and stripping based on the configured options
if (me.disableKeyFilter !== true) {
allowed = me.baseChars + '';
if (me.allowDecimals) {
allowed += me.decimalSeparator;
}
/* removed code
if (me.minValue < 0) {
allowed += '-';
}
*/
allowed = Ext.String.escapeRegex(allowed);
me.maskRe = new RegExp('[' + allowed + ']');
if (me.autoStripChars) {
me.stripCharsRe = new RegExp('[^' + allowed + ']', 'gi');
}
}
}
You need to create custom VType. VType validation is called after any change in the textfield and you have ability to configure what characters are allowed to be entered:
http://docs.sencha.com/ext-js/4-0/#!/api/Ext.form.field.VTypes
Take a look at xxxMask property.
You could also use a regular Textfield with a maskRe config.
maskRe: /[0-9]/
Similar to #lagnat's reply which is a whitelist you can blacklist characters using stripCharsRe config.
stripCharsRe: /-/
If you are wanting to restrict negative values.
minValue: 0
{
minValue: 0,
autoStripChars: true,
allowExponential: false
}