Generic Grouping of objects properties - ramda.js

I'm trying to group this object by name, so in fine I would be able to distinguish all names 'duval' from 'lulu':
const groupName = R.groupBy(R.prop('name'), [data]);
But this won't work on:
let data = {
benj: {
content : undefined,
name : 'duval',
complete: false,
height : 181
},
joy: {
content : undefined,
name : 'duval',
complete: true
},
kaori: {
content : undefined,
name : 'lulu',
complete: true
},
satomi: {
content : undefined,
name : 'lulu',
complete: true
}
}
Should I change the format of my object, or is there a way to do it in this kind of object ?

Passing [data] to groupBy is not going to help much. You want to group a list containing a single item. The fact that that item has properties like 'bennj' and 'joy' rather than 'name' is only part of the issue.
You can get something that will work, I think, if this output would be useful:
{
duval: {
benj: {
content: undefined,
name: "duval",
complete: false,
height: 181
},
joy: {
content: undefined,
name: "duval",
complete: true
}
},
lulu: {
kaori: {
content: undefined,
name: "lulu",
complete: true
},
satomi: {
content: undefined,
name: "lulu",
complete: true
}
}
}
But it's a bit more involved:
compose(map(fromPairs), groupBy(path([1, 'name'])), toPairs)(data)
toPairs converts the data to a list of elements something like this:
[
"benj",
{
complete: false,
content: undefined,
height: 181,
name: "duval"
}
]
then groupBy(path[1, 'name']) does the grouping you're looking to do, by finding the name on the object at index 1 in this list.
And finally map(fromPairs) will turn these lists of lists back into objects.
It's not a particularly elegant solution, but it's fairly typical when you want to do list processing on something that's not really a list.

Related

Using rally app lookback API - unable to fetch defects that are tagged

I am using rally lookback API and creating a defect trend chart. I need to filter defects that do not have a tag "xyz".
Using the following:
this.myTrendChart = Ext.create('Rally.ui.chart.Chart', {
storeType: 'Rally.data.lookback.SnapshotStore',
storeConfig: {
find: {
_TypeHierarchy: "Defect",
State: { $lt: "Closed"},
Tags.Name: { $nin: ["xyz"] },
_ProjectHierarchy: projectOid,
_ValidFrom: {$gte: startDateUTC}
}
},
calculatorType: 'Calci',
calculatorConfig: {},
chartConfig: {
chart: {
zoomType: 'x',
type: 'line'
},
title: {
text: 'Defect trend'
},
xAxis: {
type: 'datetime',
minTickInterval: 7
},
yAxis: {
title: {
text: 'Number of Defects'
}
}
}
});
This does not return any data. Need help with the filter for tags.
Tags is a collection of tag-oids so you'll need to find and use the oid of the tag vs the name, at which point it'll just be Tags: { $nin: [oid] }. Caveat: technically, due to how expensive it is, $nin is unsupported (https://rally1.rallydev.com/analytics/doc/#/manual/48e0589f681160fc316a8a4802dc389f)...but it doesn't throw an error so maybe it works anyway.

Set Keystone List "noedit" based on field value?

I would like to make my Keystone List object editable only if the object is not published. Here's my reduced List definition:
var Campaign = new keystone.List('Campaign', {
nodelete: true,
track: {
createdAt: true,
},
});
Campaign.add({
...,
publish: {
type: Types.Boolean,
required: false,
initial: false,
dependsOn: {
publishedOn: '',
},
},
publishedOn: {
type: Types.Datetime,
label: 'Published On',
hidden: true,
},
});
Is it possible to set noedit only if publishedOn is not null? I'm trying to prevent the object from being modified after it's "published", and am coming up short on examples.
The noedit property for a list or field is part of the model definition, and not part of the definition of an individual item. There is no way to mark a single item as uneditable in the admin UI unless you want to apply it to the field or model as a whole.
If you are less worried about clarity, and more worried about ensuring it cannot be edited, you could try the following:
Campaign.schema.post('init', function () {
if (this.published) this.invalidate('Published items cannot be edited');
});
This will cause an error to be thrown if you attempt to save the item once it is published.
While you could use dependsOn: { published: { $exists: true } } to filter fields, this would hide the information.
Interestingly, I was able to make the publish field simply check itself:
Campaign.add({
...,
publish: {
type: Types.Boolean,
required: false,
initial: false,
dependsOn: {
publish: false,
},
},
...,
});
and now it only shows if publish is false, which works exactly as I hoped it would.

Need a version of _.where that includes the parent object key

What I have is an object like this:
formData = {
name: {
value: '',
valid: true
},
zip: {
value: 'ff',
valid: false
},
//...
}
And I want to filter this so that I only have the invalid objects. The problem with _.where and _.filter is that it returns an object like this:
[
0: {
value: '',
valid: false
},
1: {
value: '',
valid: false
}
]
I need the parent key names, name and zip to be included. How do I do this?
You are looking for _.pick() my friend.
https://lodash.com/docs#pick
_.pick(formData, function(value) {
return value.valid;
})
Good luck! :)

How do I query for tag names with :find in SnapshotStore store config

I am trying to setup a filter that is similar to a defect view within a Trend chart. The filter in the defect view is:
(State < Closed) AND (Severity <= Major) AND (Tags !contains Not a Stop Ship)
I cannot seem to get the Tags find to work correctly. Any suggestions?
this.myTrendChart = Ext.create('Rally.ui.chart.Chart', {
storeType: 'Rally.data.lookback.SnapshotStore',
storeConfig: {
find: {
_TypeHierarchy: "Defect",
State: {
$lt: "Closed"
},
Severity: {
$lte: "Major"
},
Tags: {
$ne: "Not a Stop Ship"
},
_ProjectHierarchy: ProjectOid
},
hydrate: ["Priority"],
fetch: ["_ValidFrom", "_ValidTo", "ObjectID", "Priority"]
},
calculatorType: 'My.TrendCalc',
calculatorConfig: {},
chartConfig: {
chart: {
zoomType: 'x',
type: 'line'
},
title: {
text: 'Defects over Time'
},
xAxis: {
type: 'datetime',
minTickInterval: 3
},
yAxis: {
title: {
text: 'Number of Defects'
}
}
}
});
Based on reviewing the JSON messages, I figured out the tag needed to be the ObjectId. Once I found this, I replaced "Not a Stop Ship" with the ObjectId value and the filter worked correctly.

Kendo UI BarChart Data Grouping

Not sure if this is possible. In my example I am using json as the source but this could be any size. In my example on fiddle I would use this data in a shared fashion by only binding two columns ProductFamily (xAxis) and Value (yAxis) but I would like to be able to group the columns by using an aggregate.
In this example without the grouping it shows multiple columns for FamilyA. Can this be grouped into ONE column and the values aggregated regardless of the amount of data?
So the result will show one column for FamilyA of Value 4850 + 4860 = 9710 etc.?
A problem with all examples online is that there is always the correct amount of data for each category. Not sure if this makes sense?
http://jsfiddle.net/jqIndy/ZPUr4/3/
//Sample data (see fiddle for complete sample)
[{
"Client":"",
"Date":"2011-06-01",
"ProductNumber":"5K190",
"ProductName":"CABLE USB",
"ProductFamily":"FamilyC",
"Status":"OPEN",
"Units":5000,
"Value":5150.0,
"ShippedToDestination":"CHINA"
}]
var productDataSource = new kendo.data.DataSource({
data: dr,
//group: {
// field: "ProductFamily",
//},
sort: {
field: "ProductFamily",
dir: "asc"
},
//aggregate: [
// { field: "Value", aggregate: "sum" }
//],
//schema: {
// model: {
// fields: {
// ProductFamily: { type: "string" },
// Value: { type: "number" },
// }
// }
//}
})
$("#product-family-chart").kendoChart({
dataSource: productDataSource,
//autoBind: false,
title: {
text: "Product Family (past 12 months)"
},
seriesDefaults: {
overlay: {
gradient: "none"
},
markers: {
visible: false
},
majorTickSize: 0,
opacity: .8
},
series: [{
type: "column",
field: "Value"
}],
valueAxis: {
line: {
visible: false
},
labels: {
format: "${0}",
skip: 2,
step: 2,
color: "#727f8e"
}
},
categoryAxis: {
field: "ProductFamily"
},
legend: {
visible: false
},
tooltip: {
visible: true,
format: "Value: ${0:N0}"
}
});​
The Kendo UI Chart does not support binding to group aggregates. At least not yet.
My suggestion is to:
Move the aggregate definition, so it's calculated per group:
group: {
field: "ProductFamily",
aggregates: [ {
field: "Value",
aggregate: "sum"
}]
}
Extract the aggregated values in the change handler:
var view = products.view();
var families = $.map(view, function(v) {
return v.value;
});
var values = $.map(view, function(v) {
return v.aggregates.Value.sum;
});
Bind the groups and categories manually:
series: [ {
type: "column",
data: values
}],
categoryAxis: {
categories: families
}
Working demo can be found here: http://jsbin.com/ofuduy/5/edit
I hope this helps.