Passing API Key via Confluence HTML for Standard Reports - javascript

I have been able to get the Java API code to work for Iteration TreeGrid and Iteration Burndown / Release Burnup charts. We have been trying to get this to work on Confluence and there are issues trying to pass just iframes and IT has issues with some of the bypass options. We have been able to get some semblance of this to work via the script below. In fact the Iteration TreeGrid works successfully everytime but most times the Standard Reports just present the Rally login screen. This is not consistent and sometimes this works for me in Chrome, but not in Firefox/IE etc. We have attache the API to the path of the confluence page if entered via link as well as what's in the script. Is there another method for key to passed for Standard Report to be able to generate?
Thanks!
Mark
enter code here {html}
<script type="text/javascript">
var field = 'apiKey';
var url = window.location.href;
if(
(url.indexOf('?' + field + '=') != -1) ||
(url.indexOf('&' + field + '=') != -1)
){
//alert("**** 001");
} else {
var myURL = document.location;
if(window.location.href.indexOf('?') > 0){
document.location = myURL + "&apiKey=_1OS4fhAQBi101VTZ4PytkQXb9jYEt0qYx79WXJacc";
} else {
document.location = myURL + "?apiKey=_1OS4fhAQBi101VTZ4PytkQXb9jYEt0qYx79WXJacc";
}
}
</script>
<div id="div-iterationburndown"></div>
<script type="text/javascript">
Rally.onReady(function() {
Ext.create("Ext.Container", {
context: {},
items: [{
xtype: "rallystandardreport",
width: 750,
height: 500,
reportConfig: {
report: "IterationBurndown",
iteration: "April",
subchart: "hide",
title: "Iteration Burndown"
},
project: "https://rally1.rallydev.com/slm/webservice/v2.0/project/51186094804",
projectScopeUp: !1,
projectScopeDown: !0
}],
renderTo: Ext.get("div-iterationburndown")
});
Rally.launchApp('CustomApp', {
name: "iterationburndown",
parentRepos: ""
});
});
</script>
<div id="div-releaseburnup"></div>
<script type="text/javascript">
Rally.onReady(function() {
Ext.create("Ext.Container", {
context: {},
items: [{
xtype: "rallystandardreport",
width: 750,
height: 500,
reportConfig: {
report: "ReleaseBurnup",
subchart: "hide",
title: "Release Burnup"
},
project: "https://rally1.rallydev.com/slm/webservice/v2.0/project/51186094804",
projectScopeUp: !1,
projectScopeDown: !0
}],
renderTo: Ext.get("div-releaseburnup")
});
Rally.launchApp('CustomApp', {
name: "releaseburnup",
parentRepos: ""
});
});
</script>
<div id="div-RallyGrid" style="border-width:5px 5px 5px 5px;width:300px;height:150px;"></div>
<script type="text/javascript">
Rally.onReady(function() {
Ext.create("Rally.data.wsapi.TreeStoreBuilder").build({
models: ["userstory"],
autoLoad: !0,
context: {
workspace: "https://rally1.rallydev.com/slm/webservice/v2.0/workspace/50876644101",
project: "https://rally1.rallydev.com/slm/webservice/v2.0/project/50891172431"
},
enableHierarchy: !0,
filters: [{
property: "Iteration.Name",
operator: "=",
value: "April"
}, {
property: "Project.Name",
operator: "=",
value: "Harrier"
}]
}).then({
success: function(store) {
Ext.create("Ext.Container", {
width: 1e3,
height: 1e3,
border: 5,
items: [{
xtype: "rallytreegrid",
columnCfgs: ["DisplayColor", "Name", "ScheduleState", "Blocked", "TaskEstimateTotal", "TaskRemainingTotal", "Owner", "Notes"],
store: store
}],
renderTo: Ext.get("div-RallyGrid")
})
}
});
Rally.launchApp('CustomApp', {
name: "RallyGrid",
parentRepos: ""
});
});
</script>
{html}

StandardReport component in AppSDK2 is a wrapper over the first generation analytics service that predates ApiKey. This is the same analytics service that brings you reports on Reports>Reports page. Those reports were also available via StandardReport component in AppSDK1.
ApiKey is not supported in the first generation charts.
AppSDK2 supports ApiKey as described in Embedding Apps guide. AppSDK2 apps can be authenticated with ApiKey. But if an AppSDK2 app is using a StandardReport component, the analytics service behind the report will prompt you to login - it does not work with ApiKey. In your scenario it unfortunately defeats the purpose of embedding the report within other web content to be viewed by stakeholders who may not necessarily have Rally credentials.
I suspect that if it seems that it works occasionally, it is probably because you are already logged in to Rally in another tab of the same browser window. If you open a new window in the incognito mode you will be prompted to login.

Good news! The StandardReport component in AppSDK 2.1 and the backing A1 Analytics service now fully support Api Keys so you should be able to do this fairly easily.
Some useful links:
StandardReport component: https://help.rallydev.com/apps/2.1/doc/#!/api/Rally.ui.report.StandardReport
Embedding Apps externally:
https://help.rallydev.com/apps/2.1/doc/#!/guide/embedding_apps

Related

PowerBI Embedded - how to customize menu operation/context and custom layout

I have integrated powerbi-embedded with Angular 9 web app also add code for custom layut but it's not working.
I want to customize operations menu /context and custom layout.
Configuration object -
const config: any = {
type: 'report',
uniqueId: 'report-id',
permissions: this.model.Permissions.All,
embedUrl: 'embed-url',
accessToken: 'access-token',
settings: {
layoutType: this.models.LayoutType.Custom,
customLayout: {
pageSize: {
type: this.models.PageSizeType.Custom,
width: 1600,
height: 1200
},
displayOption: this.models.DisplayOption.ActualSize,
pagesLayout: {
"MyReportSection007" : {
defaultLayout: {
displayState: {
mode: this.models.VisualContainerDisplayMode.Hidden
}
},
visualsLayout: {
"VisualContainer1": {
x: 1,
y: 1,
z: 1,
width: 400,
height: 300,
displayState: {
mode: this.models.VisualContainerDisplayMode.Visible
}
},
"VisualContainer2": {
displayState: {
mode: this.models.VisualContainerDisplayMode.Visible
}
},
}
}
}
}
}
};
Above config. not working. any idea how can i achived customization in menu operation and layout.
I'm following below docs -
https://microsoft.github.io/PowerBI-JavaScript/demo/v2-demo/index.html#
https://github.com/microsoft/PowerBI-JavaScript/wiki/Custom-Layout
Thanks,
Your query is not clear since you have not shared any error message.
Though, code snippet that you shared offers a correct solution but, it might be possible that you are using wrong names for visual containers (i.e. VisualContainer1 or VisualContainer2) or the report page name (i.e. MyReportSection007). Ensure that you are providing correct names.
And if possible, please share the error message as well.

Upgrading ExtJS in old ASP.NET application from 2.3 to 6

Looking for some assistance. TLDR version: we have an ASP.NET web app that leverages ExtJS 2.3 and we are looking to upgrade to the current ExtJS version. Trying to get my head around what we’re in for.
Now for the details. I will preface by saying that I am not an expert in ExtJS nor .NET development. In fact, I’m a novice pretty much across the board when it comes to web development, so please excuse any poor explanations or misuse of terms on my part. My team is developing a web app on a “custom” framework that was developed a number of years ago at our company. It’s based on some re-runnable code generation tools that take xml templates and spit out the necessary code files. Our project is an ASP.NET MVP application that uses .aspx pages and NHibernate for ORM. Our UI is created from ExtJS—the controls are defined in each page’s .js file and then “assembled” in the .aspx page. The codebehind contains web methods that leverage the presenter of the C# code. I’ve included a snippet to demonstrate what I’m talking about below.
.aspx page:
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="Entity.aspx.cs" Inherits="View.Example.EntityView" MasterPageFile="~/MasterPages/Content.Master" %>
<asp:Content ID="Content1" runat="server">
<script language="javascript" type="text/javascript" src="~/Scripts/ext-2.2.1/ext-all.js"></script>
<script language="javascript" type="text/javascript" src="<%=ResolveUrl("~/Scripts/Factory/Example/Entity.js")%>"></script>
<script language="javascript" type="text/javascript">
var localConfig = new panelConfig();
localConfig.applyExtendedConfig('default_page');
localConfig.addItem(new Ext.grid.GridPanel(pageConfigs.default_page_ManageEntity));
localConfig.addItem(
new Ext.form.Hidden({
id: 'ManageEntityGrid_Rows'
}));
var default_page = localConfig.createExt();
default_page.on('render', default_page_OnShow, default_page, { single: true });
</script>
</asp:Content>
.js file:
var get_manageEntity_columns = function() {
var columns = [
{ header: "Name"
,id: 'ManageEntity-col-Name'
, dataIndex: 'Name'
, sortable: true
},
{ id: 'ManageEntity-col-ActiveFlag'
, header: 'Active Flag'
, dataIndex: 'ActiveFlag'
, hidden: true
,tags: []
, sortable: true
},
{ id: 'ManageEntity-col-CreatedTimestamp'
, header: 'Created Timestamp'
, dataIndex: 'CreatedTimestamp'
, hidden: true
,tags: []
, renderer : formattedDateTime
, sortable: true
},
{ id: 'ManageEntity-col-Id'
, header: 'Entity ID'
, dataIndex: 'Id'
, hidden: true
,tags: []
, sortable: true
}
];
return columns;
}
var get_grid_reader_manageEntity = function(custom_fields) {
var fields = [
{ name: 'ActiveFlag', mapping: 'ActiveFlag' },
{ name: 'CreatedTimestamp', mapping: 'CreatedTimestamp' },
{ name: 'Id', mapping: 'Id' },
{ name: 'Name', mapping: 'Name' }
];
if (custom_fields) {
fields = fields.concat(custom_fields);
}
return new Ext.data.JsonReader({
root: 'Results',
totalProperty: 'Total',
id: 'Id'
}, fields);
}
var get_grid_datastore_manageEntity = function() {
var store = new Ext.data.Store({
proxy: new Ext.data.PageMethodProxy({
pageMethod: 'GetManageEntity'
}),
reader: get_grid_reader_manageEntity()
, remoteSort: true
});
store.loadOrReload = function() {
if (store.rapidLoaded)
store.reload();
else
{
store.rapidLoaded = true;
store.load({ params: { start: 0, limit: gPageSize }
});
}
}
get_grid_datastore_manageEntity = function() { return store; };
return store;
}
var pageConfigs = {
default_page_ManageEntity: {
store: get_grid_datastore_manageEntity(),
columns: get_manageEntity_columns(),
viewConfig: {
forceFit: true
},
sm: get_manageEntity_sm(),
layout:'fit',
frame: true,
id: 'ManageEntity',
plugins: [
grid_filters_manageEntity
],
iconCls: 'icon-grid',
loadMask: true,
stripeRows: true,
bbar: get_grid_paging_toolbar_manageEntity(),
listeners: {
rowcontextmenu: show_grid_menu_manageEntity
,bodyscroll: function() {
var menu = get_grid_menu_manageEntity();
if (menu.isVisible()) menu.hide();
}
,headerClick: function() {
this.getStore().on('beforeload', this.saveState, this, { single: true });
}
,render: function(){
var grid = this;
Ext.onReady(function() {
add_applied_filters(grid);
var grid_state = Ext.state.Manager.get('ManageEntity') || {};
if (!grid_state.default_filter_applied) {
var filters = grid_filters_manageEntity;
var activeflag_filter = filters.getFilter("ActiveFlag");
activeflag_filter.setValue(["", new Array("1")]);
activeflag_filter.setActive(true);
grid.on('beforestatesave', function(grid, state) { state.default_filter_applied = true; });
}
grid.getStore().load({ params: { start: 0, limit: gPageSize }
});
});
}
}
}}
.aspx.cs file:
[WebMethod()]
public static ExtJSGridData GetManageEntity(PageProxyArgs args)
{
var watch = new Stopwatch();
watch.Start();
try
{
var data = new ExtJSGridData();
var criteria = GetManageEntityQuery(args);
criteria.SetFirstResult(args.Start).SetMaxResults(args.Limit);
data.Results = GetDataManageEntity(args.RecordId, criteria);
criteria.SetFirstResult(0).SetMaxResults(RowSelection.NoValue);
criteria.ClearOrders();
data.Total = criteria.SetProjection(Projections.CountDistinct("Id")).UniqueResult<int>();
data.UserUiStateSaved = UserUiStateHelper.SaveUserUiStateInTransaction(args.UserUiState);
watch.Stop();
PageLogHelper.CurrentLog.ServerTime = watch.ElapsedMilliseconds;
return data;
}
catch (Exception ex)
{
LogManager.GetLogger((MethodBase.GetCurrentMethod().DeclaringType)).Error(ex);
ErrorHandler.LogError(ex);
throw;
}
}
private static IList GetDataManageEntity(int id, ICriteria criteria)
{
var list = criteria.List<Model.BusinessObjects.Entity>();
var jsonList = Model.BusinessObjects.Entity.ToJSON(list);
return jsonList;
}
private static ICriteria GetManageEntityQuery(PageProxyArgs args)
{
ICriteria criteria = StaticPresenter.GetEntity();
var helper = new GridFilterHelper(criteria, args, _dManageEntityLookupSortInfo);
helper.ApplyFilterMap(EntityJSON.GetGridFilterMap(criteria, args.Filters));
MapManageEntityFilters(args.Filters, criteria);
helper.ApplyFilters();
if (args.SortInfo == null || string.IsNullOrEmpty(args.SortInfo.FieldName))
return criteria;
IList<IProjection> sortMap = StaticPresenter.GetSortMap_ManageEntity(args.SortInfo.FieldName, args.RecordId, args.ExtraParams, criteria);
if (sortMap == null)
sortMap = EntityJSON.GetSortMap(args.SortInfo.FieldName, criteria);
helper.ApplySort(sortMap);
return criteria;
}
So, here is where the question comes in. As mentioned, the version of ExtJS we’re using is 2.3, and we’re looking to upgrade to the current version. I’ve done some initial homework of googling and looking through the sencha documentation, but there are some things which I’m unclear on and would like to get addressed before I start getting hands on with this effort. I’ve tried to outline my specific questions below.
First and foremost: Is the way our application is built even possible with ExtJS 6? By this, I mean leveraging the ExtJS API to define controls in the .js file and then create a UI on top of a .NET C# backbone. Based on the change notes and questions from other users, it’s pretty apparent that there have been massive (understatement) changes between 2.3 and 6. I guess what I’m getting at is that based on what I’ve read it seems you can now build your entire app, including the model and view (and controller?) in ExtJS. Is this a requirement, or can we still lay ExtJS controls on top of our .NET C# model and view?
As a follow up, I’ve been seeing references about Sencha CMD to create and build the app etc. Is cmd going to be required no matter what? Or can we simply reference the ext js library like we’re currently doing?
Assuming the answer to question 1 is yes it’s possible, the next obvious question becomes: how much work is this going to be? Let’s get the “a lot” answer out of the way—I know. What I do know is that we will have to update all of our templates to use the new API syntax (new Ext… to Ext.create() etc). I’m okay with this. What I’m trying to figure out is what I don’t know. Assuming I update all of the syntax, would our application work? Or are there other things I need to change/fix in order to get it working?
Related to question 2: based on my reading it looks like the way data stores for controls has changed and they now use the model defined in ExtJS. Is this a requirement? As described earlier, we’re currently using web methods in the aspx.cs file. Am I going to need to duplicate our C# model in ExtJS?
Lastly, I see this asked a lot but I can’t seem to find a definitive answer. Classic vs modern? The answer I typically see is that modern is aimed more towards touch screens and modern browsers, while classic is more geared toward desktop users. I’ve also read in places that modern has fewer controls available. Our web app is running in a local environment and will not be going to mobile in the future, which leads me to think classic might be the right choice? I guess I’m just wondering technically what the difference is.
I’m sure there are things I don’t even know I’m missing. Any and all feedback is welcome.
It is possible, but you will have to do a lot handwriting. Just three weeks ago I had to leverage a 3.4 ASP to 6.2.1
You can either set the variables to a global variable and on start add these to the mainView ViewModel or load them right away onBeforeLaunch.
Then code your app and build it using Sencha CMD. At the end add all together in your ASP stuff.
About how much work ... depends a lot on how structured your code is, how easy it will be to rewrite the code.
Let's pretend it is written in the same style all over the application, then it will be relatively easy.

Refreshing jqGrid doesn't save current page position with infinite scroll enabled

Example from http://www.trirand.net/demo/javascript/jqgrid/loading_data/scrollbar/index.html
Versions of Guriddo jqGrid JS: 4.7.0 and 4.7.1
(function ($) {
'use strict';
$(function () {
$('#jqGrid').jqGrid({
url: 'http://trirand.com/blog/phpjqgrid/examples/jsonp/getjsonp.php?callback=?&qwery=longorders',
mtype: 'GET',
datatype: 'json',
page: 1,
colNames: ['Order ID', 'Customer ID', 'Order Date', 'Freight', 'Ship Name'],
colModel: [{
name: 'OrderID',
key: true,
width: 75
}, {
name: 'CustomerID',
width: 150
}, {
name: 'OrderDate',
width: 150
}, {
name: 'Freight',
width: 150
}, {
name: 'ShipName',
width: 150
}],
width: 750,
height: 250,
rowNum: 20,
scroll: 1, // set the scroll property to 1 to enable paging with scrollbar - virtual loading of records
emptyrecords: 'Scroll to bottom to retrieve new page', // the message will be displayed at the bottom
pager: '#jqGridPager'
});
});
})(jQuery);
When I call 2 times:
$('#jqGrid').trigger('reloadGrid', {
page: 3
});
first time request: the page param is 3 as expected.
second time request: the page param is 1 !?
The same problems I see at refresh button with refreshstate: 'current', It doesn't work at all.
First of all I can confirm the bug. It exits in more old versions of jqGrid too (for example in jqGrid 4.6). The reason is in the following lines (see the lines of the source code)
if (ts.grid.prevRowHeight && ts.p.scroll) {
delete ts.p.lastpage;
ts.grid.populateVisible();
} else {
ts.grid.populate();
}
jqGrid have undefined value of ts.grid.prevRowHeight on the first reload of the grid and the set ts.grid.prevRowHeight to 22 (22px is the height of row). So the next (the second) reload of the grid will use populateVisible instead of populate. The function populateVisible uses current scrolling position (scrollTop of bDiv) only and it ignores page parameter of the grid.
Thus I can suggest you multiple solution of the problem: If you have to use specific old version of jqGrid (like if you have to use jqGrid 4.7) then you can use the following code as workaround:
$('#jqGrid')[0].grid.prevRowHeight = undefined; // workaround!!
$('#jqGrid').trigger('reloadGrid', {
page: 3
});
Alternatively you can fix the code of jquery.jqgrid.src.js for example to the following
if (ts.grid.prevRowHeight && ts.p.scroll && opts.page === undefined) {
delete ts.p.lastpage;
ts.grid.populateVisible();
} else {
ts.grid.populate();
}
One more option which I can suggest you: you can load the current version of free jqGrid from github. It's my fork of jqGrid which is based on jqGrid 4.7 and which contains many enhancements (see wiki and the readme). I posted just now the corresponding fix.

Different behavior of ExtJS application in debug and minified mode

I'm facing an strange behavior in an web application I'm currently working on. The interface is totally built with ExtJs 4. The application has two modes, Debug and Production.
In Debug mode, when user click a menu item, I load synchronously, the dependent Javascripts file. Something like this:
for ( var i = 0; i < config.dependency.length; i++ ) {
var element = document.createElement('script');
element.onload = callback;
element.onreadystatechange = function () {
if ( element.readyState == 'loaded' || element.readyState == 'complete' ) {
callback();
}
};
}
One of the module's javascript file is like this:
module.js
Ext.define('Company.view.system.Module', {
extend: 'Company.view.abstract.Panel',
alias: 'widget.system.module',
/**
* These "_items" are built into the Object in `Company.view.abstract.Panel`
* using: Ext.create(this._items[i].clazz, conf);
*
* I'm just omitting the whole business logic there
*/
_items: [{
flex: 2,
clazz: 'Company.view.system.module.Form'
}, {
flex: 5,
clazz: 'Company.view.system.module.HtmlEditor'
}]
});
Ext.define('Company.view.system.module.Form', {
extend: 'Company.view.abstract.Form',
alias: 'widget.system.module.form',
items: [{
xtype: 'fieldset',
title: 'Module Grid',
items: [{
xtype: 'system.module.grid'
}]
}]
});
Ext.define('Company.view.system.module.Grid', {
extend: 'Company.view.abstract.Grid',
alias: 'widget.system.module.grid',
columns: [{
...
}],
afterLayout: function() {
this.callParent(arguments);
alert('after layout');
}
});
Ext.define('Company.view.system.module.HtmlEditor', {
extend: 'Company.view.abstract.HtmlEditor',
alias: 'widget.system.module.htmleditor',
...
});
Everything's working as expected in Debug mode. But in Production mode, I load the whole Modules as a single generated-minified-obfuscated javascript file (modules.js) at start up (i.e. before the ViewPort is rendered), instead of loading dependent modules after menu click event.
In Production mode, every Items, which is instantiated using "xtype" (Company.view.system.module.Grid in the above sample), is not rendered at all!
Screenshots of Debug mode and Production Mode.
What do you think is going on here which I'm missing?
Update:
The problem lies with the Height of the GridPanel, as It was computed at runtime, from the browser's screen size. Hence when the component being instantiated, the Height was not computed yet! Silly mistake :)
I would try moving the system.module.grid definition before it's being used in the system.module.form.
I would advise from having two different versions. What's your reason for that?

ExtJS 4 - How to download a file using Ajax?

I have a form with various textfields and two buttons - Export to Excel and Export to CSV.
The user can provide the values to different fields in the form and click one of the buttons.
Expected behaviour is that an Ajax request should be fired carrying the values of fields as parameters and the chosen file (Excel/CSV as per the button click) should get downloaded (I am not submitting the form as there needs to be done some processing at the values before submit).
I have been using the following code in success function of Ajax request for the download:
result = Ext.decode(response.responseText);
try {
Ext.destroy(Ext.get('testIframe'));
}
catch(e) {}
Ext.core.DomHelper.append(document.body, {
tag: 'iframe',
id:'testIframe',
css: 'display:none;visibility:hidden;height:0px;',
src: result.filename,
frameBorder: 0,
width: 0,
height: 0
});
The above code has been working fine in the case when the file is created physically at the server. But in my current project, the file is not created at the server, rather the contents are just streamed to the browser with proper headers.
Thus, is there a way to download a file using Ajax when the file is not present at the server physically? Just to add that I have a long list of parameters which I need to send to the server and hence can not add them all to the src of iframe.
Could anyone guide at this?
Thanks for any help in advance.
You may use component like this:
Ext.define('CMS.view.FileDownload', {
extend: 'Ext.Component',
alias: 'widget.FileDownloader',
autoEl: {
tag: 'iframe',
cls: 'x-hidden',
src: Ext.SSL_SECURE_URL
},
stateful: false,
load: function(config){
var e = this.getEl();
e.dom.src = config.url +
(config.params ? '?' + Ext.urlEncode(config.params) : '');
e.dom.onload = function() {
if(e.dom.contentDocument.body.childNodes[0].wholeText == '404') {
Ext.Msg.show({
title: 'Attachment missing',
msg: 'The document you are after can not be found on the server.',
buttons: Ext.Msg.OK,
icon: Ext.MessageBox.ERROR
})
}
}
}
});
Put it somewhere in viewport, for example:
{
region: 'south',
html: 'South',
items: [
{
xtype: 'FileDownloader',
id: 'FileDownloader'
}
]
}
Do not forget to require it in your viewport class:
requires: [
'CMS.view.FileDownload'
]
Action handler may look like this:
var downloader = Ext.getCmp('FileDownloader')
downloader.load({
url: '/attachments/' + record.get('id') + '/' + record.get('file')
});
It's very important to have Content-Disposition header in response, otherwise nothing is downloaded.
Regards go to http://www.quispiam.com/blog/post.php?s=2011-06-09-download-a-file-via-an-event-for-extjs4
This thing works for me.

Categories

Resources