Lodash creat object with given keys - lodash

Let's assume I have following array of strings that represent keys in object.
['keyA', 'keyB', 'keyC']
I want transform it to following
{ keyA: null, keyB: null, keyC: null }
Is it possible? I found methods like _.fromPairs etc... but not sure how to transform it...

You can use lodash#invert to convert each array values as keys in an object and then use lodash#mapValues with lodash#constant to set each key with a null value.
var result = _(data).invert().mapValues(_.constant(null)).value();
var data = ['keyA', 'keyB', 'keyC'];
var result = _(data).invert().mapValues(_.constant(null)).value();
console.log(result);
body > div { min-height: 100%; top: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>

Related

How to add more default empty rows in list view?

I need to add more default empty rows in the list view.
Right now, it only gives 4 empty rows on a new record. However, I need to add, say, 10 more default empty rows.
This is because I increased the height of the table using css.
.o_list_view .o_list_table {
height: 800px;
}
The result is that it still has 4 rows on default but every row has their height as 25% of the table height. Therefore, I need to add some rows into it so that their height will be fit to the new table height again.
Or another solution, if possible, remove the auto height adjustment for the rows in the table so that it won't be scaled according to the table height.
Either solution is acceptable.
As long as the length of the lines is less than 4, Odoo will try to add an empty row.
To add more default empty rows, you can alter ListRenderer _renderBody:
_renderBody: function () {
var self = this;
var $rows = this._renderRows();
while ($rows.length < 14) {
$rows.push(self._renderEmptyRow());
}
return $('<tbody>').append($rows);
},
You can also set a empty_rows attribute in the tree tag to define the number of empty rows:
XML:
<tree string="" editable="bottom" empty_rows="4">
JavaScript:
var ListRenderer = require('web.ListRenderer');
ListRenderer.include({
_renderBody: function () {
var self = this;
var empty_rows = 4;
if (self.arch && self.arch.attrs.empty_rows) {
empty_rows = self.arch.attrs.empty_rows;
}
var $rows = this._renderRows();
while ($rows.length < empty_rows) {
$rows.push(this._renderEmptyRow());
}
return $('<tbody>').append($rows);
},
});
Check Assets Management on how to add the above code to web.assets_backend bundle and Javascript Module System to create a JavaScript module

Kotlin short-cut to assign value to variable using stream function or other

for (i in 0 until result.size){ result[i].config= addConfig(taskNames!![i],processKeys!![i]) }
Here result is a list of class which has datamember config and tasNames and processKeys are list of string.
Is there a way in kotlin to map result.config with respective taskNames and processKeys without using traditional loop and mentioning length of result.I am new to kotlin.
class Process {
var processKey: String? = null
var task: List<Task>? = null}
class Task {
var taskName: String? = null
var processVariables: List<ProcessVariable>? = null}
class ProcessVariable {
var name: String? = null
var label: String? = null
var applicableValue: List<String>? = null}
Result is already present with datamember config pf type ProcessVariable
If I understand your problem correctly, you need to combine 3 lists.
So iterating over the lists may be easier to understand than some clever way of list transformations.
You can get rid of the traditional for loop, so you don't need to calculate the size of the loop:
result.forEachIndexed {
i, resultData -> resultData.config = addConfig(taskNames[i], processKeys[i])
}
If you want to combine two lists, you can use the zip method:
val configList = taskNames.zip(processKeys) {tsk, prc -> addConfig(tsk, prc)}
In your example, the result-object was already existing. Maybe it is easier to create new result-objects:
val results = configList.map {
Result(config = it)
}

Merge different rows of an array using lodash

I have a JSON array which has the following entries:
[{"customer":"xyz","date":"10.10.2014","attr1":"ABC","attr2":"001"},{"customer":"xyz","date":"10.10.2014","attr3":"XYZ","attr4":"123"},{"customer":"xyz","date":"11.10.2014","attr1":"DEF","attr2":"002"},{"customer":"xyz","date":"11.10.2014","attr3":"DDD","attr4":"222"}]
Is there a way, using lodash, I can merge the array so that this becomes:
[{"customer":"xyz","date":"10.10.2014","attr1":"ABC","attr2":"001","attr3":"XYZ","attr4":"123"},{"customer":"xyz","date":"11.10.2014","attr1":"DEF","attr2":"002","attr3":"DDD","attr4":"222"}]
Basically use the "date" attribute to merge multiple rows with different JSON attributes into a single JSON object entry ?
Use _.groupBy() to group the objects by date. Then _.merge() each group:
var customers = [{"customer":"xyz","date":"10.10.2014","attr1":"ABC","attr2":"001"},{"customer":"xyz","date":"10.10.2014","attr3":"XYZ","attr4":"123"},{"customer":"xyz","date":"11.10.2014","attr1":"DEF","attr2":"002"},{"customer":"xyz","date":"11.10.2014","attr3":"DDD","attr4":"222"}];
var result = _(customers)
.groupBy('date') // group the objects by date
.map(function(item) { // map each group
return _.merge.apply(_, item); // merge all objects in the group
})
.value();
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.16.4/lodash.js"></script>
Here is a solution using lodash 3.10.1. I assumed you want to merge each pair and that the second element of a pair will override existing properties from the first one (if there are such).
var source = [{"customer":"xyz","date":"10.10.2014","attr1":"ABC","attr2":"001"},{"customer":"xyz","date":"10.10.2014","attr3":"XYZ","attr4":"123"},{"customer":"xyz","date":"11.10.2014","attr1":"DEF","attr2":"002"},{"customer":"xyz","date":"11.10.2014","attr3":"DDD","attr4":"222"}];
var chunked = _.chunk(source, 2);
var result = _.map(chunked, _.spread(_.merge));
console.log(result);
And here is a working jsbin.

Conditionally adjust visible columns in Rally Cardboard UI

So I want to allow the user to conditionally turn columns on/off in a Cardboard app I built. I have two problems.
I tried using the 'columns' attribute in the config but I can't seem to find a default value for it that would allow ALL columns to display(All check boxes checked) based on the attribute, ie. the default behavior if I don't include 'columns' in the config object at all (tried null, [] but that displays NO columns).
So that gets to my second problem, if there is no default value is there a simple way to only change that value in the config object or do I have to encapsulate the entire variable in 'if-else' statements?
Finally if I have to manually build the string I need to parse the values of an existing custom attribute (a drop list) we have on the portfolio object. I can't seem to get the rally.forEach loop syntax right. Does someone have a simple example?
Thanks
Dax - Autodesk
I found a example in the online SDK from Rally that I could modify to answer the second part (This assumes a custom attribute on Portfolio item called "ADSK Kanban State" and will output values to console) :
var showAttributeValues = function(results) {
for (var property in results) {
for (var i=0 ; i < results[property].length ; i++) {
console.log("Attribute Value : " + results[property][i]);
}
}
};
var queryConfig = [];
queryConfig[0] = {
type: 'Portfolio Item',
key : 'eKanbanState',
attribute: 'ADSK Kanban State'
};
rallyDataSource.findAll(queryConfig, showAttributeValues);
rally.forEach loops over each key in the first argument and will execute the function passed as the second argument each time.
It will work with either objects or arrays.
For an array:
var array = [1];
rally.forEach(array, function(value, i) {
//value = 1
//i = 0
});
For an object:
var obj = {
foo: 'bar'
};
rally.forEach(obj, function(value, key) {
//value = 'bar'
//key = 'foo'
});
I think that the code to dynamically build a config using the "results" collection created by your query above and passed to your sample showAttributeValues callback, is going to look a lot like the example of dynamically building a set of Table columns as shown in:
Rally App SDK: Is there a way to have variable columns for table?
I'm envisioning something like the following:
// Dynamically build column config array for cardboard config
var columnsArray = new Array();
for (var property in results) {
for (var i=0 ; i < results[property].length ; i++) {
columnsArray.push("'" + results[property][i] + "'");
}
}
var cardboardConfig = {
{
attribute: 'eKanbanState',
columns: columnsArray,
// .. rest of config here
}
// .. (re)-construct cardboard...
Sounds like you're building a neat board. You'll have to provide the board with the list of columns to show each time (destroying the old board and creating a new one).
Example config:
{
attribute: 'ScheduleState'
columns: [
'In-Progress',
'Completed'
]
}

Changing constraints on the fly

I have a dijit.form.NumberTextBox input field that starts out with these parms:
new dijit.form.NumberTextBox({
id: din1,
style: "width:60px",
constraints: {
places: 0,
pattern: '######'
}
},
din1);
Everything works great..My question is I would like to change 'places' and 'pattern' parms on the fly. So I wrote this to change 'places' and 'patterns' parms:
var myFldObj = dijit.byId(din1);
if (myFldObj) {
var myConstObj = myFldObj.attr('constraints');
if (myConstObj) {
myConstObj.places = 2;
myConstObj.pattern = '#####.0';
}
}
So, after I show the form again, I'd expect the entry field to allow 2 decimal places but the form still acts like places=0 and pattern='######'. When I check the values of 'places' and 'pattern' I get what I'd expect (2 and #####.0). My question:
Can you change these values on the fly??
OR
Do you have to destroy the original dijit object and recreate with new parms??
Thx!!
So, here is what worked for me:
First, I think this is a bug because an input field that starts out like
new dijit.form.NumberTextBox({
id: "fieldID",
style: "width:60px",
constraints: {
places: 0
}
},
"fieldID");
that is then changed on the fly with code like:
NOTE: ntbArry - Array of dijit.form.NumberTextBox objs tied to a html
input tag id.
for (var x=0;x < ntbArry.length;x++) {
var handle = ntbArry[x];
if (handle) {
handle.attr('constraints').places = 2;
handle.attr('constraints').pattern = '#####.0#';
}
}
Does not exhibit the same behavior as a field created this way (no constraints mods on the fly):
new dijit.form.NumberTextBox({
id: "fieldID",
style: "width: 60px",
constraints: {
places: 2,
pattern: '#####.0#'
}
},
"fieldID");
It's close in behavior but every time you type a decimal point, the error message pops up stating invalid entry. This message doesn't pop up when typing the decimal point on a field that was originally created with the constraints places=2 and pattern '#####.0#'.
So, to get original behavior I wanted:
fieldIDEvents is an array of dojo events tied to NumberTextBox fields.
Before continuing disconnect dojo events
for (var x=0;x < fieldIDEvents.length;x++) {
var handle = fieldIDEvents[x];
if (handle) {
dojo.disconnect(handle);
}
}
then destroy the NumberTextBox dojo objects
for (var x=0;x < ntbArry.length;x++) {
var handle = ntbArry[x];
if (handle) {
handle.destroy();
ntbArry[x] = null;
}
}
Next, place the input tag back into the html because it gets destroyed:
NOTE: tdtag and an id on a html td tag which should contain the input tag.
var fld1 = this.document.getElementById("tdtag");
if (fld1) {
//alert("\""+fld1.innerHTML+"\"");
fld1.innerHTML = "<input id=\"fieldID\">";
}
Now, create the NumberTextBox object again:
ntbArry[0] = new dijit.form.NumberTextBox({
id: "fieldID",
style: "width: 60px",
constraints: {
places: 2,
pattern: '#####.0#'
}
},
"fieldID");
It's a few extra steps but, at least I know this is what works for me..If I'm missing something basic, let me know, it's easy to miss the small details with this stuff.
I use Dojo 1.3 and I can see that dijit.form.NumberTextBox has no pattern and places properties, but has editOptions property. So I would try to change the constraints like this:
myConstObj.editOption.places = 2;