How to find items that are in one dstore collection but not in another? - dojo

Suppose I have two dstore collections: value1 and value2.
I want to find out what items are in value1 but not in value2. So something like this:
var filterCollection = value1.filter(function(item) {
return value2.notExists(item);
});
But "notExists" function, well, doesn't exist. How do I make this logic work?

As this feature is not included by default in dstore, you can write your own function for comparing the content of your dstores and use the result as you wish.
Here a generic example. You need to populate value1 and value1 with the content of your dstore.
Simplified example.
http://jsbin.com/fozeqamide/edit?html,console,output
Version without using indexOf()
http://jsbin.com/nihelejodo/edit?html,console,output
The way how you loop in your datastore is related to its data structure.
Notes: This is a generic example as the question does not provide any source code, nor an example of data in dstore.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Builder</title>
<style>
</style>
<script>
window.app = {
value1: [1, 2, 3, 4, 5, 6, 4, 8], // populate with date for valu1 dstore
value2: [1, 2, 6, 4, 8], // populate with date for valu1 dstore
valueNotExists: [],
start: function () {
this.notExists();
},
notExists: function () {
this.valueNotExists = this.value1.filter(function (x) {
return this.value2.indexOf(x) < 0;
}.bind(this));
console.log(this.valueNotExists);
},
};
</script>
</head>
<body onload="window.app.start();">
</body>
</html>

Related

Ramda - how to get multiple properties from array

I am trying to get two properties from an array of objects which looks like this:
const nodes = [
{
"id": "0",
"outgoingNodeIds": ['1', '2'],
"outgoingVirtualNodes": [
{
"virtualNodeId": "5",
},
{
"virtualNodeId": "10",
}
],
}
]
I need to get outgoingNodeIds which is a simple array of strings and outgoingVirtualNodes which is an array of objects and I need to get virtualNodeId from it.
There is no problem with getting only one property at the time and then concat two arrays (example in ramda):
const prop1 = R.pipe(
R.pluck('outgoingNodeIds'),
R.flatten
)(nodes)
const prop2 = R.pipe(
R.pluck('outgoingVirtualNodes'),
R.map(R.pluck('virtualNodeId')),
R.flatten
)(nodes)
R.concat(prop1, prop2)
But I would like to combine this into one pipe if possible. I know how to get two properties at once but I don't know how to map the second one to get virtualNodeId.
Any help would be appreciated. Thank you
Use R.ap to apply a list of functions to the array - each function produces a new array of values from all object objects in the original array, and then flatten to a single array. The end result would be an array of all outgoingNodeIds from all objects, and then the virtualNodeId from all objects:
const { pipe, ap, prop, pluck, flatten } = R
const fn = pipe(
ap([
prop('outgoingNodeIds'),
pipe(prop('outgoingVirtualNodes'), pluck('virtualNodeId'))
]),
flatten,
)
// Note that are two objects - a and b
const nodes = [{"id":"0","outgoingNodeIds":["1a","2a"],"outgoingVirtualNodes":[{"virtualNodeId":"5a"},{"virtualNodeId":"10a"}]},{"id":"1","outgoingNodeIds":["3b","4b"],"outgoingVirtualNodes":[{"virtualNodeId":"15b"},{"virtualNodeId":"20b"}]}]
const result = fn(nodes)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.28.0/ramda.min.js" integrity="sha512-t0vPcE8ynwIFovsylwUuLPIbdhDj6fav2prN9fEu/VYBupsmrmk9x43Hvnt+Mgn2h5YPSJOk7PMo9zIeGedD1A==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
If you want the outgoingNodeIds and then virtualNodeId of each object together replace R.ap with R.map and R.juxt. The R.juxt apply a list of functions to a list of parameters (a single object in this case).
const { pipe, map, juxt, prop, pluck, flatten } = R
const fn = pipe(
map(juxt([
prop('outgoingNodeIds'),
pipe(prop('outgoingVirtualNodes'), pluck('virtualNodeId'))
])),
flatten,
)
// Note that are two objects - a and b
const nodes = [{"id":"0","outgoingNodeIds":["1a","2a"],"outgoingVirtualNodes":[{"virtualNodeId":"5a"},{"virtualNodeId":"10a"}]},{"id":"1","outgoingNodeIds":["3b","4b"],"outgoingVirtualNodes":[{"virtualNodeId":"15b"},{"virtualNodeId":"20b"}]}]
const result = fn(nodes)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.28.0/ramda.min.js" integrity="sha512-t0vPcE8ynwIFovsylwUuLPIbdhDj6fav2prN9fEu/VYBupsmrmk9x43Hvnt+Mgn2h5YPSJOk7PMo9zIeGedD1A==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
Since we're dealing with a single object on each iteration of R.map, you can replace R.juxt with R.applySpec:
const { pipe, map, applySpec, prop, pluck, flatten } = R
const fn = pipe(
map(applySpec([
prop('outgoingNodeIds'),
pipe(prop('outgoingVirtualNodes'), pluck('virtualNodeId'))
])),
flatten,
)
// Note that are two objects - a and b
const nodes = [{"id":"0","outgoingNodeIds":["1a","2a"],"outgoingVirtualNodes":[{"virtualNodeId":"5a"},{"virtualNodeId":"10a"}]},{"id":"1","outgoingNodeIds":["3b","4b"],"outgoingVirtualNodes":[{"virtualNodeId":"15b"},{"virtualNodeId":"20b"}]}]
const result = fn(nodes)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.28.0/ramda.min.js" integrity="sha512-t0vPcE8ynwIFovsylwUuLPIbdhDj6fav2prN9fEu/VYBupsmrmk9x43Hvnt+Mgn2h5YPSJOk7PMo9zIeGedD1A==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
Ori Drori has already given several great Ramda versions. But let's not forget how simple this can be in modern JS:
const extractNodeIds = (nodes) => nodes .flatMap ((node) => [
... (node .outgoingNodeIds),
... (node .outgoingVirtualNodes .map (vn => vn .virtualNodeId))
])
const nodes = [{id: '0', outgoingNodeIds: ['1', '2'], outgoingVirtualNodes: [{virtualNodeId: '5'}, {virtualNodeId: '10'}]}]
console .log (extractNodeIds (nodes))
Ramda was designed and mostly built in the days before ES6 was ubiquitous. But these days, tools like flatMap and the array ...spread syntax make many problems that Ramda solved so nicely almost as nice in plain JS. It's not that I don't love the tool -- I'm a Ramda founder and a big fan -- but it no longer seems as necessary as it once did.

Materialize Chips Limit option is not working

I am using materialize chips autocomplete, but i think the limit option is not working.
With limit option I guess that it refers to the maximum number of chips that can be selected.
For example, I put limit 3, but it allows me to add all the available.
How can I limit to select up to 3 options?
html code
<div class="chips-autocomplete"></div>
chips initialization
<script src="js/materialize.js"></script>
<link type="text/css" rel="stylesheet" href="css/materialize.min.css" media="screen,projection"/>
<script type="text/javascript">
$('.chips-autocomplete').chips({
autocompleteOptions: {
data: {
'Apple': null,
'Microsoft': null,
'Android': null,
'Facebook': null,
'Twitter': null,
'Amazon': null,
'Google': null
},
limit: 3,
minLength: 1
}
});
</script>
Materialize chips has two limit options. Limit within autocompleteOptions and limit within chips options:
autocomplete options => this limits the number of suggestions you will see when trying to add a new chip. Ref here in the documentation: https://materializecss.com/autocomplete.html
chips options => this sets the maximum number of chips allowed, which is what you want. Ref here in the documentation: https://materializecss.com/chips.html
So to get the limit on number of chips you can add, move limit outside autoCompleteOptions like this
<script type="text/javascript">
$('.chips-autocomplete').chips({
autocompleteOptions: {
data: {
'Apple': null,
'Microsoft': null,
'Android': null,
'Facebook': null,
'Twitter': null,
'Amazon': null,
'Google': null
}
},
limit: 3,
minLength: 1
}
});
</script>

Datatable component not aligned properly

I'm using a simple table in conjunction with datatable.js.
If I have 6 or 7 columns no problem. The search and paginator align correctly, but with 3 or 4 columns it shows in three columns.
In https://datatables.net/examples/basic_init/dom.html
show how to properly configure this, but I'm using thymeleaf and complains about the syntax
UPDATE 1
I have posted my question in:
https://datatables.net/forums/discussion/45926/dom-in-thymeleaf-html-pages
and this is that post:
Trying to add the code in: https://datatables.net/examples/basic_init/dom.html
in a thymeleaf html page, but it complains about this code:
"dom": '<"top"i>rt<"bottom"flp><"clear">'
I tried to change " by ' and use escape characters but no way.
This script in my html page, doesnt work:
$(document).ready(function() {
$("#mensuales").DataTable({
"dom": '<"top"i>rt<"bottom"flp><"clear">',
"language": {
"url": "//cdn.datatables.net/plug-ins/1.10.15/i18n/Spanish.json"
},
"lenghtMenu": [
[5, 12, 15, 20, -1],
[5, 12, 15, 20, "Todos"]
],
"ordering": true,
stateSave: true
});
});
Allan says the code is correct, but I not be able to use in my pages.
UPDATE 2
Any suggestions?
Thanks
Try with:
<script type="text/javascript" th:inline="javascript">
/*<![CDATA[*/
$(document).ready(function() {
$("#mensuales").DataTable({
"dom": '<"top"i>rt<"bottom"flp><"clear">',
"language": {
"url": "//cdn.datatables.net/plug-ins/1.10.15/i18n/Spanish.json"
},
"lenghtMenu": [
[5, 12, 15, 20, -1],
[5, 12, 15, 20, "Todos"]
],
"ordering": true,
stateSave: true
});
});
/*]]>*/
</script>

How do I get PortfolioItem results in Rally SDK1.33?

I am using the Rally SDK1.33 as in the end I need to display information using the LoginKey outside of Rally. I am trying to query information on PortfolioItem, but it looks like no results are being returned. - However if I put the query in the through the webservice doc pages, I get a result.
Using the following link (replacing 123456789 with a real ObjectID for a PortfolioItem and the workspace 987654321 with a real workspace) I get back the PortfolioItem object:
https://rally1.rallydev.com/slm/webservice/1.43/portfolioitem.js?workspace=https://rally1.rallydev.com/slm/webservice/1.43/workspace/987654321&query=(ObjectID%20%3D%20123456789)&fetch=true&start=1&pagesize=20
However if I try to query it from code, I get back the query results without any results and without any errors (again - using a real PortfolioItem ObjectID instead of the 123456789).
ExternalPortfolio
<!--App information-->
<meta name="Name" content="App: ExternalPortfolio"/>
<meta name="Version" content="1.0"/>
<meta name="Vendor" content=""/>
<!--Include SDK-->
<script type="text/javascript" src="https://rally1.rallydev.com/apps/1.33/sdk.js?debug=true&apiVersion=1.43"></script>
<script type="text/javascript">
function onLoad() {
rallyDataSource = new rally.sdk.data.RallyDataSource('__WORKSPACE_OID__',
'__PROJECT_OID__',
'__PROJECT_SCOPING_UP__',
'__PROJECT_SCOPING_DOWN__');
var objectId = 123456789;
var queryConfig = {
type: 'PortfolioItem',
key: 'portfolio',
fetch: 'FormattedID,Name',
query: '(ObjectID = ' + objectId +')'
};
rallyDataSource.findAll(queryConfig, showPortfolio, errorCallBack);
function showPortfolio(results) {
console.log(results);
}
function errorCallBack(response) {
console.log('Got problems!')
console.log(response.Errors);
console.log(response.Warnings);
}
}
rally.addOnLoad(onLoad);
</script>
<style type="text/css">
.externalPortfolio {
/* Add app styles here */
}
</style>
I have created a number of reports on Stories and Defects (most all running outside of Rally), but never for a PortfolioItem. - Am I missing something here? Or is there a severe bug with the v1.xx SDK or v1.x API in handling portfolio items?
This might not be the issue you're encountering, but if you're running outside Rally, try setting both the Workspace OID and Project OID:
rallyDataSource = new rally.sdk.data.RallyDataSource(
'12345678910',
'12345678911',
'__PROJECT_SCOPING_UP__',
'__PROJECT_SCOPING_DOWN__');
When I initially ran your example using Workspace OID only, I found that like you I was not receiving any results, and no errors were returned. However, examining the generated query URL in Chrome's network console:
https://rally1.rallydev.com/slm/webservice/1.43/adhoc.js?_method=POST&adHocQuery={"portfolio":"/portfolioitem?query=(ObjectID = \"152345647\")&pagesize=200&fetch=FormattedID,Name&workspace=/workspace/12345678910&project=${/user/userprofile/defaultProject}&projectScopeUp=false&projectScopeDown=true"}&jsonp=dojo.io.script.jsonp_dojoIoScript1._jsonpCallback
You can see that the User's default project is being passed as the Project parameter. However the PI with that specific ObjectID was in a different Workspace. As an outcome, I was receiving the following error:
{
portfolio: {
_rallyAPIMajor: "1",
_rallyAPIMinor: "43",
Errors: [
"The specified project must be in the specified workspace. Project OID=12345678921 is in Workspace OID=1234569840 and the specified Workspace is OID=12345678910."
],
Warnings: [ ],
_ref: "/portfolioitem?query=(ObjectID = "152345647")&pagesize=200&fetch=FormattedID,Name&workspace=/workspace/12345678910&project=/project/12345678921&projectScopeUp=false&projectScopeDown=true",
TotalResultCount: 0,
StartIndex: 0,
PageSize: 0,
Results: [ ]
}
}
Once I included the Project OID in the new-up of rallyDataSource instead of the hangman, I obtained the expected result in the console:
Object {errors: Array[0], warnings: Array[0], portfolio: Array[1]}
errors: Array[0]
portfolio: Array[1]
0: Object
DirectChildrenCount: 0
FormattedID: "F10"
Name: "PI Feature 10"
_objectVersion: "7"
_rallyAPIMajor: "1"
_rallyAPIMinor: "43"
_ref: "https://rally1.rallydev.com/slm/webservice/1.43/portfolioitem/feature/152345647.js"
_refObjectName: "PI Feature 10"
_type: "PortfolioItem/Feature"
__proto__: Object
length: 1
__proto__: Array[0]
warnings: Array[0]
__proto__: Object

View pictures or images inside Jquery DataTable

May I know if it is possible to put pictures or images into the rows of DataTables (http://datatables.net/) and how does one goes in doing it?
yes, simple way (Jquery Datatable)
<script>
$(document).ready(function () {
$('#example').dataTable({
"processing": true, // control the processing indicator.
"serverSide": true, // recommended to use serverSide when data is more than 10000 rows for performance reasons
"info": true, // control table information display field
"stateSave": true, //restore table state on page reload,
"lengthMenu": [[10, 20, 50, -1], [10, 20, 50, "All"]], // use the first inner array as the page length values and the second inner array as the displayed options
"ajax":{
"url": "#string.Format("{0}://{1}{2}", Request.Url.Scheme, Request.Url.Authority, Url.Content("~"))/Home/AjaxGetJsonData",
"type": "GET"
},
"columns": [
{ "data": "Name", "orderable" : true },
{ "data": "Age", "orderable": false },
{ "data": "DoB", "orderable": true },
{
"render": function (data, type, JsonResultRow, meta) {
return '<img src="Content/Images/'+JsonResultRow.ImageSrcDB+'">';
}
}
],
"order": [[0, "asc"]]
});
});
</script>
[edit: note that the following code and explanation uses a previous DataTables API (1.9 and below?); it translates easily into the current API (in most cases, just ditch the Hungarian notation ("fnRowCallback" just becomes "rowCallback" for example) but I have not done so yet. The backwards compatibility is still in place I believe, but you should look for the newer conventions where possible]
Original reply follows:
What Daniel says is true, but doesn't necessarily say how it's done. And there are many ways. Here are the main ones:
1) The data source (server or otherwise) provides a complete image tag as part of the data set. Don't forget to escape any characters that need escaping for valid JSON
2) The data source provides one or more fields with the information required. For example, a field called "image link" just has the Images/PictureName.png part. Then in fnRowCallback you use this data to create an image tag.
"fnRowCallback": function( nRow, aData, iDisplayIndex, iDisplayIndexFull ) {
var imgLink = aData['imageLink']; // if your JSON is 3D
// var imgLink = aData[4]; // where 4 is the zero-origin column for 2D
var imgTag = '<img src="' + imgLink + '"/>';
$('td:eq(4)', nRow).html(imgTag); // where 4 is the zero-origin visible column in the HTML
return nRow;
}
3) Similar to above, but instead of adding a whole tag, you just update a class that has the image as a background. You would do this for images that are repeated elements rather than one-off or unique pieces of data.
You mean an image inside a column of the table?
Yes, just place an html image tag
like this
<img src="Images/PictureName.png">
instead of putting data (some string) into a column just put the above html tag....
Asp.net core DataTables
The following code retrieve the image from a folder in WWWroot and the path in the DB field ImagePath
{
"data": "ImagePath",
"render": function (data) {
return '<img src="' + data + '" class="avatar" width="50" height="50"/>';
}
}
In case the Name of the picturefile is put together out of one or more informations in the table, like in my case:
src="/images/' + Nummer + Belegnummer + '.jpg"
you can make it that way:
var table = $('#Table').DataTable({
columnDefs: [
{
targets: 0,
render: getImg
}
]
});
function getImg(data, row, full) {
var Nummer = full[1];
var Belegnummer = full[4];
return '<img src="/images/' + Nummer + Belegnummer + '.jpg"/>';}
The picture is in the first column, so Targets = 0 and gets the Information from the same row.
It is necessary to add the parameters data and row.
It is not necessary to outsource it into a seperate function, here getImg, but it makes it easier to debug.