IcCube - Treemap Chart with duplicate names - google-visualization

In the Google Treemap Chart every node has to have a unique id, but two nodes can have the same name (https://groups.google.com/d/msg/google-visualization-api/UDLD-a-0PCM/IwVCGzsWOg8J).
I used the schema from the parent/child demo (http://www.iccube.com/support/documentation/user_guide/schemas_cubes/dim_parentchild.php)
Using the following MDX statement in the treemap works, as long as the names of the nodes are unique:
WITH
MEMBER [parent_name] as IIF( [dim (ALL)].[Hierarchy].currentmember
is [dim (ALL)].[Hierarchy].[ALL],'',
[dim (ALL)]. [Hierarchy].currentmember.parent.name )
SELECT
{[parent_name],[Measures].[value]} on 0,
non empty [dim (ALL)].[Hierarchy].members on 1
FROM
[Cube]
If I added the line to the In-memory table in icCube's schema :
7,4,Spain, 2, 32
but the name Spain is double when rendering the Treemap. To support names a child definition in the GVI table should be something like this:
{v:'uniqueID-Spain', f:'Spain'}

As a workaround you can use the following code that modifies GviTable processing for the google tree widget. Check the example here:
https://drive.google.com/file/d/0B3kSph_LgXizSVhvSm15Q1hIdW8/view?usp=sharing
Report JavaScript:
function consumeEvent( context, event ) {
if (event.name == 'ic3-report-init') {
if(!_.isFunction(ic3.originalProcessGviTable)) {
ic3.originalProcessGviTable = viz.charts.GenericGoogleWidget.prototype.processGviTable
}
viz.charts.GenericGoogleWidget.prototype.processGviTable = function(gviTable){
if(this.props.ic3chartType === "TreeMap") {
gviTable = gviTable || this.gviTable();
var underlying = _.cloneDeep(gviTable.getUnderlyingGviTable());
_.each(underlying.rows, function(row){
// Replace id with parent prefixed
if(_.isObject(row.c[0]) && !_.isString(row.c[0].f)) {
row.c[0].f = row.c[0].v;
if(_.isObject(row.c[0].p) && _.isString(row.c[0].p.mun)) {
row.c[0].v = row.c[0].p.mun;
}
}
});
gviTable = viz.GviTable.fromSnapshot(underlying);
this.startColumnSelection = gviTable.getNumberOfHeaderColumns() - 1;
return viz.charts.toGoogleDataTableOneRowHeader(gviTable);
} else {
return ic3.originalProcessGviTable.apply(this, gviTable);
}
}
}
}
For the query like:
WITH
MEMBER [parent_name] as
IIF( [dim (ALL)].[Hierarchy].currentmember.isAll(),
'',
([dim (ALL)].[Hierarchy].currentmember.parent.uniqueName)
)
SELECT
{[parent_name],[Measures].[value]} on 0,
non empty [dim (ALL)].[Hierarchy].members on 1
FROM
[Cube]

This is a limitation of Google Treemap chart that is using the same column for the id and the label. Besides changing the names to ensure they are unique (e.g. adding the parent) I don't see a workaround to this.
An option would be using another Treemap chart (e.g. one from D3) that has not this limitation.
--- icCube Schema ---
The schema is working (just use , instead of ; as separator )
--- icCube Reporting ---
The issue using Treemap is that you've two rows with the same id (Germany), fiddle
This fiddle is a running example of treemap

Related

ASP NET MVC Core 2 with entity framework saving primery key Id to column that isnt a relationship column

Please look at this case:
if (product.ProductId == 0)
{
product.CreateDate = DateTime.UtcNow;
product.EditDate = DateTime.UtcNow;
context.Products.Add(product);
if (!string.IsNullOrEmpty(product.ProductValueProduct)) { SaveProductValueProduct(product); }
}
context.SaveChanges();
When I debug code the ProductId is negative, but afer save the ProductId is corect in database (I know this is normal), but when I want to use it here: SaveProductValueProduct(product) after add to context.Products.Add(product); ProductId behaves strangely. (I'm creating List inside SaveProductValueProduct)
List<ProductValueProductHelper> pvpListToSave = new List<ProductValueProductHelper>();
foreach (var item in dProductValueToSave)
{
ProductValueProductHelper pvp = new ProductValueProductHelper();
pvp.ProductId = (item.Value.HasValue ? item.Value : product.ProductId).GetValueOrDefault();
pvp.ValueId = Convert.ToInt32(item.Key.Remove(item.Key.IndexOf(",")));
pvp.ParentProductId = (item.Value.HasValue ? product.ProductId : item.Value);
pvpListToSave.Add(pvp);
}
I want to use ProductId for relationship. Depends on logic I have to save ProductId at ProductId column OR ProductId at ParentProductId column.
The ProductId 45 save corent at ProductId column (3rd row - this is a relationship), BUT not at ParentProductId (2nd row - this is just null able int column for app logic), although while debug I pass the same negative value from product.ProductId there.
QUESTION:
how can I pass correct ProductId to column that it isn't a relationship column
I just use SaveProductValueProduct(product) after SaveChanges (used SaveChanges twice)
if (product.ProductId == 0)
{
product.CreateDate = DateTime.UtcNow;
product.EditDate = DateTime.UtcNow;
context.Products.Add(product);
}
context.SaveChanges();
if (product.ProductId != 0)
{
if (!string.IsNullOrEmpty(product.ProductValueProduct)) { SaveProductValueProduct(product); }
context.SaveChanges();
}
I set this as an answer because it fixes the matter, but I am very curious if there is any other way to solve this problem. I dont like to use context.SaveChanges(); one after another.

Acumatica GI - Inventory Transaction History Screen

I want to create a GI for Inventory Transaction History Screen (IN405000).
Since the table InventoryTranHistEnqResult isn't present in the database...few of the columns of this screen are taken from INTran Table.
I am not able to find following columns: BegQty, QtyIn, QtyOut, EndQty...
I also tried the following query on database to find these columns
SELECT c.name AS ColName, t.name AS TableName
FROM sys.columns c
JOIN sys.tables t ON c.object_id = t.object_id
WHERE c.name LIKE '%EndQty%'
The DAC for these fields is:
enter image description here
Looking at the information behind the page in the page Graph will give you the answers to your question. Inventory Transaction History Screen (IN405000) uses graph InventoryTranHistEnq. The grid in this page uses DAC InventoryTranHistEnqResult in the following view:
PXSelectJoin<InventoryTranHistEnqResult,
CrossJoin<INTran>,
Where<True, Equal<True>>,
OrderBy<Asc<InventoryTranHistEnqResult.gridLineNbr>>> ResultRecords
The ResultsRecords are built dynamically in the inquiry using the following:
protected virtual IEnumerable resultRecords()
{
int startRow = PXView.StartRow;
int totalRows = 0;
decimal? beginQty = null;
List<object> list = InternalResultRecords.View.Select(PXView.Currents, PXView.Parameters, new object[PXView.SortColumns.Length], PXView.SortColumns, PXView.Descendings, PXView.Filters, ref startRow, PXView.MaximumRows, ref totalRows);
PXView.StartRow = 0;
foreach (PXResult<InventoryTranHistEnqResult> item in list)
{
InventoryTranHistEnqResult it = (InventoryTranHistEnqResult)item;
it.BegQty = beginQty = (beginQty ?? it.BegQty);
decimal? QtyIn = it.QtyIn;
decimal? QtyOut = it.QtyOut;
beginQty += (QtyIn ?? 0m) - (QtyOut ?? 0m);
it.EndQty = beginQty;
}
return list;
}
So i guess the short answer is you cannot use the results of this page for a GI as it is built in the page only. You might want to look into adding what you need to this history page via a customization or make your own version of this page/graph/dac if the information you need is that important.

Faceted search on multilist in sitecore 7

I'm able to generate the facet and bind the result in Linkbutton within repeater control. Now I'm facing problem in generating the facet query with OR operator when the user selects more than 1 value of same facet type in Sitecore 7.
What can be done to solve it?
Thanks
Here's a blog post about solving this using PredicateBuilder with a specific code example:
http://www.nttdatasitecore.com/en/Blog/2013/November/Building-Facet-Queries-with-PredicateBuilder.aspx
To implement the Facet search in Sitecore use PredicateBuilder class to build the filter query and then add the filter query to the base query. Code is mentioned below:
List<PeopleFields> objPeoplefields = new List<PeopleFields>();
IQueryable<PeopleFields> Query = null;
var predicatePractice = Sitecore.ContentSearch.Utilities.PredicateBuilder.False<PeopleFields>();
var predicateOffice = Sitecore.ContentSearch.Utilities.PredicateBuilder.False<PeopleFields>();
using (var context = ContentSearchManager.GetIndex(SITECORE_WEB_INDEX).CreateSearchContext())
{
//Base query
Query = context.GetQueryable<PeopleFields>().Where(i => i.FirstName.StartsWith(txtFirstName.Text)).Where(i => i.LastName.StartsWith(txtLastName.Text));
foreach (string strselecteFacet in lstPracticefacetSelected)
{
//filter query
predicatePractice = predicatePractice.Or(x => x.Practice.Like(strselecteFacet));
}
foreach (string strselecteFacet in lstOfficefacetSelected)
{
//Filter query
predicateOffice = predicateOffice.Or(x => x.Office.Like(strselecteFacet));
}
//Joining the filter query alongwith base query
if (lstPracticefacetSelected.Count > 0 && lstOfficefacetSelected.Count > 0)
Query = Query.Filter(predicatePractice).Filter(predicateOffice);
else if (lstPracticefacetSelected.Count > 0 && lstOfficefacetSelected.Count == 0)
Query = Query.Filter(predicatePractice);
else if (lstPracticefacetSelected.Count == 0 && lstOfficefacetSelected.Count > 0)
Query = Query.Filter(predicateOffice);
objPeoplefields = Query.ToList();
}
As a quick way, if you're ok with having SitecoreUISearchResultItem as the query result type, you may be able to utilize the same method Sitecore 7 uses to parse queries entered in the content editor search:
Sitecore.Buckets.Util.UIFilterHelpers.ParseDatasourceString(string query)
If that's not up to what you're after, reading how it's implemented with a decompiler (ILSpy, DotPeek, Reflector, Resharper, etc) may help you in composing an expression manually based on dynamic criteria.

Hide UltragridRow that has no visible child rows after applying RowFilter

So, I am setting the DataSource of my BindingSource to the DefaultViewManager of a DataSet that has a DataRelation. I then set my BindingSource as the UltraGrid's DataSource before applying a RowFilter to the the "SalesOrderSublines" DataView.
public void RefreshData()
{
var dataset = DataService.GetMillWorkOrders()
bindingSource1.DataSource = dataset.DefaultViewManager;
ultraGridSequences.SetDataBinding(bindingSource1, "", true, true);
var dvm = bindingSource1.DataSource as DataViewManager;
dvm.DataViewSettings["SalesOrderSublines"].RowFilter = "LINE_NO = 2;
}
public static DataSet GetMillWorkOrders()
{
DataSet ds = OracleHelper.ExecuteDataset(_connectionString, CommandType.StoredProcedure, SQL.GET_WORK_ORDERS);
ds.Tables[0].TableName = "WorkOrders";
ds.Tables[1].TableName = "SalesOrderSublines";
var dr = new DataRelation("WorkOrderSublines", ds.Tables["WorkOrders"].Columns["WORK_ORDER"], ds.Tables["SalesOrderSublines"].Columns["WORK_ORDER"]);
ds.Relations.Add(dr);
return ds;
}
Then, as the UltraGridRows are initializing I want to hide any parent row ("WorkOrders") that has no visible child rows ("WorkOrderSublines") because of my RowFilter.
private void ultraGridSequences_InitializeRow(object sender, Infragistics.Win.UltraWinGrid.InitializeRowEventArgs e)
{
if (e.Row.Band.Key != "WorkOrders") return;
e.Row.Hidden = e.Row.ChildBands["WorkOrderSublines"].Rows.VisibleRowCount == 0;
}
Although the RowFilter does work properly on the rows in the "WorkOrderSublines" band the VisibleRowCount of the band is still greater than zero and so the parent row is never hidden. My guess is that I want to look for something other than the VisibleRowCount of the ChildBand to determine if the top-level row should be hidden, but I'm stuck. Any help would be greatly appreciated. Thanks ahead of time.
Instead of relying on VisibleRowCount you could simply compare the count of child row filtered vs total count.
void ultraGridSequences_InitializeRow(object sender, Infragistics.Win.UltraWinGrid.InitializeRowEventArgs e)
{
if (e.Row.Band.Key != "WorkOrders") return;
var sublinesBand = e.Row.ChildBands["WorkOrderSublines"]
e.Row.Hidden = sublinesBand.Rows.Count(row => row.IsFilteredOut) ==
sublinesBand.Rows.Count();
}
Should be fine performance-wise so long as we're not talking huge amounts of records?
Using the Filtering within the Grid may be an option rather than using the filtering in the DataSource. The following resources have more details on implementing this:
http://forums.infragistics.com/forums/t/51892.aspx
http://devcenter.infragistics.com/Support/KnowledgeBaseArticle.aspx?ArticleID=7703

CFGRID - replace data store or filter on more than one column

ColdFusion 8
I have a cfgrid that that is based on a query. It is not bound to a cfc function because I want a scrolling grid, not a paged grid (you must supply the page number and page size if you use BIND).. I can figure out how to make it filter on one column by using the following code, but I really need to filter on three columns...
grid.getDataSource().filter("OT_MILESTONE",t1);
Adding more to the filter string does not do the trick...it ignores anything more than the first pair of values..
so..I thought if I called a function that passes the three values and returned the query results to me, I could replace the Data Store for the grid..but I cannot figure out the syntax to get it to replace.
The returned variable for the query has the following format:
{"COLUMNS":["SEQ_KEY","ID","OT_MILESTONE"],"DATA":[[63677,"x","y"]]}
Any ideas?
have you looked at queryconvertforgrid()?
http://www.cfquickdocs.com/cf9/#queryconvertforgrid
Update: have you looked at these?
http://www.danvega.org/blog/index.cfm/2008/3/10/ColdFusion-8-Grid-Filtering
http://www.coldfusion-ria.com/Blog/index.cfm/2009/1/13/Playing-with-cfgrid--Filter-showhide-Columns-and-using-the-YUI-Buttons-library
http://cfsilence.com/blog/client/index.cfm/2007/8/9/Filtering-Records-In-An-Ajax-Grid
after much blood, sweat, tears and swearing..here's the answer, in case anyone else might need to filter a cfgrid by more than one variable:
var w1 = ColdFusion.getElementValue('wbs');
var t1 = ColdFusion.getElementValue('task');
var p1 = ColdFusion.getElementValue('project');
grid = ColdFusion.Grid.getGridObject('data');
store = grid.getDataSource();
store.clearFilter();
store.filterBy(function myfilter(record) {
var wantit = true;
if (trim(w1) != '') {
if(record.get('WBS_ID') != w1) {
wantit = false;
}}
if (trim(t1) != '') {
if(record.get('OT_MILESTONE') != t1) {
wantit = false;
}}
if (trim(p1) != '') {
if(record.get('PROJECT') != p1) {
wantit = false;
}}
return wantit;
});
ColdFusion.Grid.refresh('data',false);
you will need a JS trim function...
Make sure the column names are caps...