Kendo DataSource Filtering with multiple conditions - datasource

I want to build a filter for a datasource with multiple condition. I found this thread (HERE) where the guys have almost the same problem, but me I want to make a OR and not a AND between my two operation.
There is the code I have so far :
var filter = { logic: "OR", filters: [] };
var filterProduct = { logic: "AND", filters: [] };
var supplierValue = dropdownSupplier.value();
if (supplierValue != "00000000-0000-0000-0000-000000000000") {
filterProduct.filters.push({ field: "SupplierId", operator: "eq", value: supplierValue });
}
var categoryValue = dropdownCategory.value();
if (categoryValue != "00000000-0000-0000-0000-000000000000") {
filterProduct.filters.push({ field: "CategoryId", operator: "eq", value: categoryValue });
}
var typeValue = dropdownType.value();
if (typeValue != "00000000-0000-0000-0000-000000000000") {
filterProduct.filters.push({ field: "TypeId", operator: "eq", value: typeValue });
}
var filterSelect = { logic: "OR", filters: [] };
filterSelect.filters.push({ field: "Id", operator: "eq", value: "00000000-0000-0000-0000-000000000000" });
filter.filters.push(filterProduct);
filter.filters.push(filterSelect);
dropdownProduct.dataSource.query({ filter: filter });
In fact what I want to do it's to have : (filterProduct) OR (filterSelect) but if i'm not using "logic" in the variable filter, the filter will be an "AND".
Thanks alot
edit: There is a jsFiddle close to what I want to do but with the "AND" : Example In this example the filter is :
[ {[ Freight = 11.61 OR Freight = 51.30 ]} AND {[ City startswith "Charleroi" ]} ]
But I want to have somethign like :
[ {[ Freight = 11.61 OR Freight = 51.30 ]} OR {[ City startswith "Charleroi" ]} ]

There is the final code working properly :
The keyword AND and OR need to be lowercase and I don't need to use the variable filterSelect
var filter = { logic: "or", filters: [] };
var filterProduct = { logic: "and", filters: [] };
var supplierValue = dropdownSupplier.value();
if (supplierValue != "00000000-0000-0000-0000-000000000000") {
filterProduct.filters.push({ field: "SupplierId", operator: "eq", value: supplierValue });
}
var categoryValue = dropdownCategory.value();
if (categoryValue != "00000000-0000-0000-0000-000000000000") {
filterProduct.filters.push({ field: "CategoryId", operator: "eq", value: categoryValue });
}
var typeValue = dropdownType.value();
if (typeValue != "00000000-0000-0000-0000-000000000000") {
filterProduct.filters.push({ field: "TypeId", operator: "eq", value: typeValue });
}
if (filterProduct.filters.length > 0) {
filter.filters.push(filterProduct);
}
filter.filters.push({ field: "Id", operator: "eq", value: "00000000-0000-0000-0000-000000000000" });
dropdownProduct.dataSource.query({ filter: filter });

Thanks forumma, your example helped me. For others trying to decipher the Kendo UI (since there are multiple, undocumented ways to do things), I have included my example to set filters on two different fields and one field has a compound OR filter:
var initialFilter = { logic: "or", filters: [] };
var filterStatus = [
{ field: "impStatus", operator: "neq", value: "Complete" }
];
var filterDeveloper = { logic: "or", filters: [
{ field: "developer", operator: "eq", value: "Unassigned" }
] };
filterDeveloper.filters.push( { field: "developer", operator: "eq", value: "Bob" } );
initialFilter.filters.push( filterStatus );
initialFilter.filters.push( filterDeveloper );
dataSource.filter( initialFilter );

Related

vue-good-table custom sorting

I am using vue-good-table and have the following code so far:
<vue-good-table :columns="columns" :rows="rows"
styleClass="vgt-table condensed striped bordered"
:sort-options="sortOptions"
:search-options="searchOptions"
:select-options="selectOptions"
#on-selected-rows-change="selectionChanged">
</vue-good-table>
sortOptions: {
enabled: true,
initialSortBy: { field: "date", type: "desc" },
}
columns() {
return [
{
label: "Name",
field: "name",
},
{
label: "CreationDate",
field: "date",
type: "date",
formatFn: function (value) {
return value != null ? moment(value).format('YYYY-MM-DD') : null;
},
sortFn(x, y) {
x = moment(x);
y = moment(y);
return x.unix() < y.unix() ? -1 : x.unix() > y.unix() ? 1 : 0;
},
},
]
}
Sorting works fine so far, and there are three states: 'asc', 'desc' and 'none'.
However i would like to achieve the following:
When clicking the column header and the current sorting type is 'none' for any of the columns, i would like to have the data sorted as defined in the initialSortBy property in the sortOptions. So sorted by date in desc order.
I tried using the #on-sort-change event but don't really know how to proceed further as i am quite new to Vue.
onSortChange(params) {
console.log('on-sort-change:');
console.log(params[0].field)
console.log(params[0].type)
if (params[0].type == 'none') {
console.log("default sort")
//TODO sort data as defined in initial sort
}
}

YADCF custom_func not calling custom function

I have a database field that contains either integer 1 (representing the value 'document') or integer 2 (representing the value 'email') and I use datatables to format/display these integers as the words 'document' or 'email' within the table column. I would therefore like to use YADCF to be able to select 'document' or 'email' and have datatables filter the resultset accordingly.
Link to screen shot of table column.
I have used the custom_func feature as follows (code stripped down for brevity), but regardless of all other aspects of the datatable looking and working correctly, with a filter selector looking as expected and holding the selected value, and no console errors, my custom function is not being called. I have tried manually calling the custom function immediately before initialising YADCF, to check the scope, and it is being called just fine. Can anyone see anything obviously wrong please?
$(document).ready(function() {
function customFilterDocEmail(filterVal, columnVal) {
alert('customFilterDocEmail called');
var found;
if (columnVal === '') {
return true;
}
switch (filterVal) {
case 'doc':
found = columnVal === '1';
break;
case 'email':
found = columnVal === '2';
break;
default:
found = 1;
break;
}
if (found !== -1) {
return true;
}
return false;
}
})
var table = $('#table').DataTable({
serverSide: true,
processing: true,
ajax: {
url: '/api/datatables/getJson/doctext/doctexts',
type: 'POST',
data: function(d) {d.CSRFToken = '****';}
},
stateSave: true,
responsive: true,
pageLength: 25,
order: [[0, 'asc']],
columns: [
{ data: 'txt_type', width: '10%' },
{ data: 'txt_title' },
{ data: 'txt_name', width: '20%' },
{ data: 'link', orderable: false, width: '5%' },
],
}
});
yadcf.init(table, [
{ column_number: 0, filter_type: 'custom_func', custom_func: customFilterDocEmail,
data: [{ value: 'doc', label: 'Document' }, { value: 'email', label: 'Email' }] },
{ column_number: 1, column_data_type: 'text', filter_type: 'text', filter_delay: 500, filter_default_label: '', },
{ column_number: 2, column_data_type: 'text', filter_type: 'text', filter_delay: 500, filter_default_label: '', },
], 'footer');
YADCF Version: 0.9.3.beta.11
DataTables Version: 1.10.16
UPDATE: I haven't a clue what I'm doing wrong above, but I have come up with a little hack that saves having to use 'custom_func' and a custom filter. I've used the standard 'select' filter type but intercepted the filter string within the filter() method of my DatatablesSSP script thus:
$str = $requestColumn['search']['value'];
// returned search values for doctext 'txt_type' are Document/Email, so we need to map these to 1/2.
if ($column['db'] == 'txt_type') {
if ($str == 'Document') { $str = '1'; }
if ($str == 'Email') { $str = '2'; }
}
This works a treat :)
You have to place the customFilterDocEmail function outside of the $(document).ready block so it will be global and yadcf will see it

Query Rally Lookback API with owner name in output

I want a list of all the people who have revised the given user story in addition to other data.
I'm querying the Rally Lookback REST API with the following JSON data:
{
"find" : { "FormattedID": "$STORY" },
"fields" : ["ObjectID", "_ValidFrom", "_ValidTo", "Blocked", "c_KanbanState", "Owner"],
"compress" : true
}
With this query, I get the Owner's OID, like so:
{
"_ValidFrom": "2014-05-09T15:18:29.912Z",
"_ValidTo": "9999-01-01T00:00:00.000Z",
"ObjectID": 18326652440,
"Blocked": false,
"Owner": 13786838413,
"c_KanbanState": "Accepted"
}
Is there a way to hydrate that Owner field? I'd like to see "John Smith", but I'd settle for "jsmith#example.com".
If I have to use the WSAPI for this, is there a way to query for a group of Owner OIDs at once -- if so, a sample would be helpful -- or will I need to loop through the collection of values and query each Owner individually?
As Trever said, in Lookback API user fields cannot be hydrated.
As far as an example that hydrates user fields using wsapi, the code below uses shapshotstore to get snapshots where '_PreviousValues.Blocked' : {$exists: true}, and then uses Rally.data.ModelFactory to get the DisplayName of owner in each snapshot.
Ext.define('CustomApp', {
extend: 'Rally.app.App',
componentCls: 'app',
scopeType: 'iteration',
comboboxConfig: {
labelWidth: 100,
width: 300
},
launch: function() {
var that = this;
var iterationComboBox = Ext.create('Rally.ui.combobox.IterationComboBox',{
listeners:{
ready: function(combobox){
var iterationOid = combobox.getRecord().get('ObjectID');
that._loadStories(iterationOid);
},
select: function(combobox){
var iterationOid = combobox.getRecord().get('ObjectID');
this._loadStories(iterationOid);
},
scope: this
}
});
this.add(iterationComboBox);
},
_loadStories:function(iterationOid){
var that = this;
var snapshotStore = Ext.create('Rally.data.lookback.SnapshotStore', {
autoLoad:true,
find: {
'_TypeHierarchy': 'HierarchicalRequirement',
'_ProjectHierarchy': 12352608219,
'_PreviousValues.Blocked' : {$exists: true},
'Iteration': iterationOid
},
fetch: ['Name','FormattedID','ScheduleState','Blocked','_ValidFrom','_ValidTo', 'BlockedReason','Owner'],
order: 'OpenedDate DESC',
hydrate: ['Blocked','ScheduleState'],
compress: true,
listeners: {
load: function(store,records,success){
console.log("loaded %i records", records.length);
that._onStoriesLoaded(snapshotStore, records);
},
scope:this
}
});
},
_onStoriesLoaded:function(store, records){
var that = this;
var promises = [];
_.each(records, function(story) {
promises.push(that._hydrateOwner(story, that));
});
Deft.Promise.all(promises).then({
success: function(results) {
that._stories = results;
console.log('that._stories', that._stories);
that._makeGrid();
}
});
},
_hydrateOwner:function(story, scope){
var deferred = Ext.create('Deft.Deferred');
var that = scope;
var ownerDisplayName = null;
var userOid = story.get('Owner');
var storyBlocked = story.get('Blocked');
Rally.data.ModelFactory.getModel({
type: 'User',
scope: this,
success: function(model, operation) {
fetch: ['UserName', 'DisplayName'],
model.load(userOid, {
scope: this,
success: function(record, operation) {
owner = record.get('DisplayName');
var fid = story.get('FormattedID');
var state = story.get('ScheduleState');
var name = story.get('Name');
var blocked = story.get('Blocked');
result = {
"fid" : fid,
"name" : name,
"state" : state,
"blocked" : blocked,
"owner" : owner
};
deferred.resolve(result);
}
});
}
});
return deferred;
},
_makeGrid: function() {
if (this.down('#grid')) {
this.down('#grid').destroy();
}
var gridStore = Ext.create('Rally.data.custom.Store', {
data: this._stories
});
var _grid = Ext.create('Rally.ui.grid.Grid', {
itemId: 'grid',
store: gridStore,
columnCfgs: [
{
text: 'Name', dataIndex: 'name'
},
{
text: 'FormattedID', dataIndex: 'fid'
},
{
text: 'ScheduleState', dataIndex: 'state'
},
{
text: 'Blocked', dataIndex: 'blocked'
},
{
text: 'Owner', dataIndex: 'owner'
}
]
});
this.add(_grid);
this._grid.reconfigure(gridStore);
}
});
Unfortunately, per the documentation -
It is not possible to hydrate some field types (e.g. User).
See the hydration section of the documentation
And to add to what Nick and Trever have said, if you want to know who has revised a given story, the field you're looking for is "_User". Owner is the owner, _User is who created the revision. Nick's example code can be tweaked to hydrate the _User, since it's just an OID like Owner.
A caveat: if someone changed Only a big text field (like the Description), that doesn't create a snapshot so won't be returned.

Adding filters with "And" and "or" in 2.0rc1

I am having problem in using filters with "And" and "or" clause. Basically i want to get any userstories having text "Mobile" or "Testing"
I am trying like this :
_createFilters:function(){
var filter = Ext.create('Rally.data.QueryFilter',
{
property: 'Name',
operator: 'contains',
value: 'Mobile'
}
);
filter = filter.or(Ext.create('Rally.data.QueryFilter',
{
property: 'Name',
operator: 'contains',
value: 'Testing'
}));
return filter.toString();
},
_makeDefectsStore:function(ref){
Ext.create('Rally.data.WsapiDataStore',{ // will fetch userstories that have defects
model: 'User Story',
limit: "Infinity",
context: {
project :'/project/xxxx',
projectScopeUp: false,
projectScopeDown: true
},
autoLoad: true,
fetch:['FormattedID','Name','Defects','Feature'],
filters: [this._createFilters()],
scope:this,
listeners: {
load: this._onAllDefectsLoaded,
scope: this
}
});
}
Here filter is returning null, otherwise all the userstories are returned without filtering . Please provide suggestion/fix
Nothing immediately pops out as being incorrect with your filter construction, you might try this simpler version though and see what you get:
Ext.create('Rally.data.WsapiDataStore', {
model : 'UserStory',
filters : Rally.data.QueryFilter.or([{
property : 'Name',
operator : 'contains',
value : 'Testing'
},{
property : 'Name',
operator : 'contains',
value : 'Mobile'
}])
});

Hydrate Tags In Lookback API

I'm trying to get the tags associated with a defect using the lookback api. It seems no matter what I try, I can never get the tags to hydrate. Any Ideas?
I get the following data on return of the query:
ScheduleState: "Backlog"
Tags: Array[1]
0: 3230012667
length: 1
__proto__: Array[0]
My query code is:
Ext.create('Rally.data.lookback.SnapshotStore', {
fetch: ['Name','ScheduleState', 'Project', 'Tags'],
autoLoad: true,
listeners: {
load: function(store, records) {
console.log(store);
}
},
hydrate: ['Tags'],
fields: ['Name','ScheduleState', 'Project', 'Tags'],
filters: [
{
property: '_TypeHierarchy',
operator: '=',
value: 'Defect'
},
{
property: 'ScheduleState',
operator: '!=',
value: 'Accepted'
},
{
property: '__At',
value: dateString
}
]
});
I don't believe you can hydrate tags with the LBAPI. What I would do instead is use the WSAPI create a hash map which maps the tags Object ID to its name. Here's some code to get that done:
Ext.create('Rally.data.WsapiDataStore', {
limit : Infinity,
model : 'Tag',
fetch : ['ObjectID','Name']
}).load({
callback: function(store) {
var tagNameMap = Ext.create('Ext.util.HashMap');
Ext.Array.each(store.getRecords(), function(record) {
tagNameMap.add(record.get('ObjectID'), record.get('Name'));
});
getDefects(tagNameMap); //Pass the tag name map to the LBAPI request
}
});
Now just use tagNameMap.get(tagOID) to get the name of the tag.
Hope this helps :)