GoldenLayout hide/show component (again) - golden-layout

I have an issue with showing/hiding a component similar to this question:
GoldenLayout, how to hide/show component?
My layout is as follows:
let config: Config = {
settings: {
showCloseIcon: false,
showPopoutIcon: false
},
content: [
{
type: 'column',
content: [
{
type: 'row',
height: 25,
content: [
{
title: 'A react component',
type: 'react-component',
component: 'searchContainer'
}
],
},
{
type: 'row',
height: 75,
content: [
{
title: 'A react component',
type: 'react-component',
component: 'leftContainer'
},
{
title: 'Another react component',
type: 'react-component',
component: 'rightContainer'
}
],
},
],
}],
};
I have a hideSearchBar and showSearchBar functions which look like this:
function hideSearchBar() {
let container: ContentItem = layout.root.contentItems[0];
container.contentItems[1].config.height = 100;
container.contentItems[1].contentItems[0].config.height = 100;
container.contentItems[1].contentItems[1].config.height = 100;
container.config.height = 0;
container.contentItems[0].element.hide();
layout.updateSize();
//layout.updateSize($(window).width(), $(window).height());
}
function showSearchBar() {
let container: ContentItem = layout.root.contentItems[0];
container.contentItems[0].element.show();
layout.updateSize();
}
The showSearchBar works perfectly and shows both rows of the grid correctly.
The hideSearchBar hides the top row correctly but leaves the second row does not take up the whole screen. I have tried setting the config.height to 100 in various places but cannot get it to work - there is a gap the size of the top row at the bottom of the screen.
Any help much appreciated.

I solved this with a different layout config where search bar was initially set to 0:
let config: Config = {
settings: {
showCloseIcon: false,
showPopoutIcon: false
},
content: [
{
type: 'column',
content: [
{
type: 'row',
height: 0,
content: [
{
title: 'A react component',
type: 'react-component',
component: LayoutComponent.SearchContainer
}
],
},
{
type: 'row',
height: 100,
content: [
{
title: 'A react component',
type: 'react-component',
component: LayoutComponent.WindowContainer
},
{
title: 'Another react component',
type: 'react-component',
component: LayoutComponent.CollectionContainer
}
],
},
],
}],
};
showSearchBar looks like this:
function showSearchBar() {
let container: ContentItem = layout.root.contentItems[0];
if (searchRowHeight == 0) {
container.contentItems[0].config.height = SEARCH_HEIGHT;
}
else {
container.contentItems[0].config.height = searchRowHeight;
container.contentItems[1].config.height = containerRowHeight;
}
container.contentItems[0].element.show();
layout.updateSize();
}
and hideSearchBar looks like this:
function hideSearchBar() {
let container: ContentItem = layout.root.contentItems[0];
container.contentItems[0].config.height = 0;
container.contentItems[1].config.height = 100;
container.contentItems[0].element.hide();
layout.updateSize();
}
In summary, the config made the searchBar hidden and when it was opened, heights were readjusted.
I use an event listener to check for height changes:
layout.on('stateChanged', () => {
let updateConfig: Config = layout.toConfig();
if (updateConfig.content[0].content[0].height != 0) {
searchRowHeight = updateConfig.content[0].content[0].height;
containerRowHeight = updateConfig.content[0].content[1].height;
}
HTH

Extending #jmc42's answer. Pretty good work-around but once thing it doesn't do is hide the splitter when expanding on pane to 100% and the collapsing the other to 0%.
As a work-around, I thought of 2 choices:
When the pane gets hidden, get the adjacent element representing the splitter bar within the same div and hide it.
When the pane gets hidden, and you detect a resize, always re-apply the expand the top pane to 100% and the bottom pane to 0%.
I opted for option 2 as it was simpler to implement and what I have is:
if (updateConfig.content[0].content[0].height != 0) {
searchRowHeight = updateConfig.content[0].content[0].height;
containerRowHeight = updateConfig.content[0].content[1].height;
}
else {
let container = gbl_Layout.root.contentItems[0].contentItems[0];
container.contentItems[0].config.height = 100;
container.contentItems[1].config.height = 0;
layout.updateSize();
}
My 'if' statement condition is more complex that the one above as I'm performing other checks but that will give you the gist of it. Works pretty well for me.

Related

Highcharts Multiple Series data - label mismatch

I have multiple series lets call them
A, B, C, D
I have pulled the series data like so
data:[1,2,3], data:[4,5,6], data[3,5,7], data[7,8,9]
The data is showing correctly on the bar chart
But when I click the series name/identifier on the y-Axis while the bar shows the correct data, the label that appears beside the bar, is incorrect.It seems to use an index based correlation between series and labels
Here is my code:
axios.get('/api/getData')
.then((response) => {
let data= response.data
//initialize series, category arrays
let series = [];
let categories = [];
//group data by product types
let productTypeGroups = _.groupBy(stockData, (product) => {
return product.type;
});
//loop through grouped data and create series for each product type
for(const[key,value] of Object.entries(productTypeGroups)){
let dataValues= _.map(value, (product)=>{
//push product names into category array
categories.push(product.name)
return product.current_balance < 0 ? 0 : product.current_balance;
})
//set default visibility to true if product is vaccine
let visibility = key === 'A' ? true : false
series.push({
name:key,
data:dataValues,
visible:visibility
})
}
this.dataValuesChart.highchartOptions.xAxis.categories = categories
this.dataValuesChart.dataValues.series = series
Here is the HighCharts Config:
highchartOptions: {
chart: {
type: 'bar',
height: 500
},
title: {
text: 'Stock Balance'
},
subtitle: {
text: ''
},
yAxis: {
title: {
text: 'Doses'
},
labels: {
format: '{value}'
}
},
xAxis: {
categories: [],
labels:{
step:1
}
},
plotOptions: {
series: {
label: {
connectorAllowed: false
}
}
},
series: [],
responsive: {
rules: [{
condition: {
maxWidth: 500
},
chartOptions: {
legend: {
layout: 'horizontal',
align: 'center',
verticalAlign: 'bottom'
}
}
}]
}
}
Here is a screenshot of how the chart displays:
How does the click event know what labels to pull, should we use some sort of dynamic category setting for this to work? Is there another way to do this even?
Credit #ppoctaczek for pointing out the data array can also be a multidimensional array [x, y] as documented here: https://api.highcharts.com/highcharts/series.bar.data
In terms of hiding the unclicked series #ppoctaczek suggested I edit the plotOption section like so. NB default behaviour on click is to add or remove clicked series to already clicked series - you can retain these defaults if that works for you.
plotOptions: {
series: {
label: {
connectorAllowed: false
},
grouping:false,
events:{
legendItemClick: function(){
this.chart.series.forEach(s=>{
s.hide();
});
this.show();
return false;
}
}
}
},
Then in terms of the data array I needed to make it multidimensional, and have the x value referencing the serial indices of the categories across the multiple series. I achieved this by:
//initialize index counter
let i = 0;
//loop through grouped data and create series for each product type
for(const[key,value] of Object.entries(productTypeGroups)){
let balances = [];
_.each(value, (product)=>{
//push product names into category array
categories.push(product.name)
//push index and balance into balances array
balances.push([i, product.current_balance]);
//increment index
i++;
})
//set default visibility to true if product is vaccine
let visibility = key === 'vaccine' ? true : false
series.push({
name:key,
data:balances,
visible:visibility
})
}
Your data array on console.log your series data should look like this:

How to connect to SharePoint Online with IP address

I would like to know how to successfully connect to spo service url with a IP address.
Connect-SPOService https://13.xxx.xxx.9-admin.sharepoint.com
How about triggering the Excel export manually on button click using kendo.ooxml.Workbook combined with kendo.saveAs?
I have made up a Kendo Dojo example. Let me know if this is what you need. Additionally, if you need to retrieve the name of your screen, there are some examples of how to do this here
EDIT
Below is an example of the export generated by the Dojo example when the "Click to Export" button is pressed. Note that the title is custom.
Not sure why this would not work for you, but try the following example with your code and see what happens. Basically, you can hook up the custom function to handle the export button click as follows:
$("#exportButton").kendoButton({
click: function () {
var grid = $("#yourGrid").getKendoGrid();
// declare `rows` and supply your own column names
var rows = [{
cells: [
{ value: "ContactTitle" },
{ value: "CompanyName" },
{ value: "Country" }
]
}];
var trs = grid.dataSource;
// will get any filters applied to grid dataSource
var filteredDataSource = new kendo.data.DataSource({
data: trs.data(),
filter: trs.filter()
});
filteredDataSource.read();
var data = filteredDataSource.view();
for (var i = 0; i < data.length; i++) {
var dataItem = data[i];
rows.push({
cells: [ // dataItem."Whatever Your Attributes Are"
{ value: dataItem.ContactTitle },
{ value: dataItem.CompanyName },
{ value: dataItem.Country }
]
});
}
excelExport(rows);
}
});
This sets up the rows to be exported, and the excelExport function carries out the export:
function excelExport(rows) {
var workbook = new kendo.ooxml.Workbook({
sheets: [
{
columns: [
{ autoWidth: true },
{ autoWidth: true }
],
title: "Name of Tab",
rows: rows
}
]
});
var nameOfPage = "Test-1"; // insert here however you are getting name of screen
kendo.saveAs({ dataURI: workbook.toDataURL(), fileName: nameOfPage + " Export.xlsx" });
}
Let me know the outcome.

Plotly chart area cuts off text

I have the following plotly code:
var element = document.getElementById(scope.changeid);
function getData(division,redraw) {
var employeeData = [];
if (!division) {
$http.get(api.getUrl('competenceUserAverageByMyDivisions', null)).success(function (response) {
processData(response,redraw);
});
}
else {
$http.get(api.getUrl('competenceUserAverageByDivision', division)).success(function (response) {
processData(response,redraw);
})
}
}
function processData(data,redraw) {
var y = [],
x1 = [],
x2 = [];
data.forEach(function (item) {
y.push(item.user.profile.firstname);
x1.push(item.current_level);
x2.push(item.expected);
});
var charData = [{
x: y,
y: x1,
type: 'bar',
name: $filter('translate')('COMPETENCES.GRAPH.CURRENT'),
marker: {
color: '#23b7e5'
}
}, {
x:y,
y:x2,
type: 'bar',
marker: {
color: '#f05050'
},
name: $filter('translate')('COMPETENCES.GRAPH.EXPECTED')
}],
layout = {
title: $filter('translate')('USERMANAGEMENT.USERS'),
barmode: 'stack',
legend: {
traceorder: 'reversed'
}
};
Plotly.newPlot(element,charData,layout);
}
scope.$watch('divisionId', function (newValue, oldValue) {
if (newValue) {
getData(newValue.id,true);
}
}, true);
getData(null,false);
This generates the following chart:
<div class="panel-body">
<h4 class="text-center">{{'COMPETENCES.GRAPH_TITLES.OVERVIEW_GAP' | translate}}</h4>
<vertical-bar-chart id="chartArea" goto="competence.titleCompetenceDetails"
changeid="chartArea" xcolumn="xColumn" y-column="yColumn"
dataset="dataSet"
has-addition="true"
style="width: 80%; text-align: center"></vertical-bar-chart>
</div>
As you might be able to tell the text (x column) is being unintentionally cut off. So my question is how can i avoid this? i have attempted to increase the height of the element however without any luck :(
AS you can see here:
(oh you cant tell because of the white background but the height of panel body is 1000 px however it still cuts it off.)
Try increasing the bottom margin in layout.margin.b (more info in the plotlyjs reference page.
For reference, I had the same issue, margin bottom didn't help, but after the graph was created, I ran the following JQuery which revealed the hidden text:
var heightincrease = $('#yourID').find('.svg-container').height() + 100;
$('#yourID').find('.svg-container').height(heightincrease).find('.main-svg').height(heightincrease);
Obviously adjust as required to reveal your whole graph. Will probably break resizing so will need work if that's a concern.

Dojox.grid.DataGrid with empty Data

My problem is that the datagrid does not appear I need it to be empty so I can add items to do a relation with a existing FilteringSelect Formatter.
function formatter1() {
var x = new FilteringSelect({
name: "Account Select",
//value: "1",
store: remoteData,
searchAttr: "name",
onChange: function () {
console.log("EI");
}
});
x._destroyOnRemove=true;
return x;
}
// Relations data grid
var DataRelations = { identifier: "id", items: [] };
storeRelations = new Write({data: DataRelations, clearOnClose: true });
var layoutRelations = [
{'name': "Words", field: "word", width: 40 },
{'name': "Account", field: "id", width: 40, formatter: formatter1 }
//,{'name': "Accounts Available", field: "AccountsAvailable", width: 20, formatter: formatter1}
];
var gridRelations = new DataGrid({
id: 'gridRelations',
store: storeRelations,
structure: layoutRelations,
rowSelector: '10px'
});
/*append the new grid to the div*/
gridRelations.placeAt("gridDivRelations");
/*Call startup() to render the grid*/
gridRelations.startup();
here is a working jsfiddle based on your code:
http://jsfiddle.net/LFk8Z/
You need to specify a width and a height for the DIV container of the grid. Maybe that was the initial problem. Also you need to load the grid css resources. Your formatter function did not have a paramater, but you need to specify one:
function formatter1(x) {
// Format cell value (which is in x) in here.
}

HTML Form to ExtJS Form

I have an html form in which the fields are extremely scattered. The page has been created using html table - rowspan and colspan combinations.
I need to convert this form to ExtJS and display it in a window.
After carrying out some research, I feel that table layout could be best choice for positioning the fields. But there are few issues which I have been facing as following:
If I give rowspan or colspan as 2 or more, then also the fields don't increase in size to occupy the availabe space and remain confined to single column.
If I resize the window, then the table doesn't resize (though, the form does as the tbar present at the top expand to occupy the complete space).
I have used the layout as 'fit' for window and layout as 'table' for the form.
I have also tried using 'anchor' layout for form and then having a fieldset with table layout, but the positioning didn't work.
Could someone please throw some light on this. Following is a basic code snippet I am using:
var form = Ext.create('Ext.form.Panel', {
url:'voyage_berth_monitoring.php',
fieldDefaults: {
labelAlign: 'right'
},
layout:{
type:'table',
columns:3
},
defaults:{
anchor:'100%'
},
tbar:[
{
xtype:'button',
text:'Clear'
},
{
xtype:'button',
text:'Delete'
},
{
xtype:'tbfill'
},
{
xtype:'button',
text:'Save'
},
{
xtype:'button',
text:'Exit'
}
],
items: [
{
fieldLabel:'item',
xtype:'textfield'
},
{
fieldLabel:'item',
xtype:'textfield',
colspan:2
},
{
fieldLabel:'item',
xtype:'textfield'
},
{
fieldLabel:'item',
xtype:'textfield'
},
{
fieldLabel:'item',
xtype:'textfield'
}
]
});
var win = Ext.create('Ext.window.Window', {
title: 'Window',
closable: true,
closeAction:'hide',
minimizable:true,
maximizable:true,
height:350,
width:750,
layout:'fit',
autoScroll:true,
items: form
});
win.show();
Basicly i had the same problem with the layout table, couldn't find any way to span my displayfields to the length of the td, and also the same issue with the 2 columns field.
The solution i prefered was to extend the table layout and give it that flexibility
Ext.define('Extended.TableLayout', {
alias:'layout.extendedTable',
extend: 'Ext.layout.container.Table',
type: 'extendedTable',
columns: 2,
rightMargin: 20,
tableAttrs:{
width: '100%'
},
tdAttrs:{
width:'50%'
},
itemCls:'x-table-cell',
renderItems: function(items) {
var totalWidth = this.getLayoutTargetSize().width,
len = items.length,
i, item, colNr;
for (i = 0; i < len; i++) {
item = items[i];
colNr = this.columns;
if ((colNr > 1) && Ext.isNumber(item.colspan)) {
colNr = colNr - item.colspan + 1;
}
item.width = Math.floor(totalWidth/colNr) - this.rightMargin;
}
this.callParent(arguments);
}
});
Using the extendedTable layout i get the desired look
One alternative it to serialize your HTML form data as JSON and load it into an EXT store. Once it's in a store, EXT will happily do whatever you want with it.