Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions App-debug-apikey.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
<head>
<title>PPM Timesheet</title>
<script type="text/javascript">
var APP_BUILD_DATE = "Wed Jan 25 2017 15:11:40 GMT-0700 (MST)";
var APP_BUILD_DATE = "Fri Jul 02 2021 08:54:49 GMT-0600 (Mountain Daylight Time)";
</script>

<script type="text/javascript" src="https://rally1.rallydev.com/apps/x/sdk-debug.js?apiKey=_PUT_APIKEY_HERE_"></script>
<script type="text/javascript" src="https://rally1.rallydev.com/apps/x/sdk-debug.js?apiKey="></script>

<script type="text/javascript">
Rally.onReady(function() {
Expand Down
65 changes: 42 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,28 +1,32 @@
#PPM Timesheet
# Clarity Timesheet App

This app presents a PPM timesheet through an iFrame in Rally.
## Summary/Description

PPM version must be version 15.2 or above.
The Clarity timesheet app provides an easy way to launch into a configured clarity timesheet.

A PPM host name or IP address and (optionally) HTTPS port must be configured through the app settings.
This app will not be able to serve a timesheet that is only accessible through HTTP protocol.
When the app is loaded, a new tab or window with the configured Clarity server will launch. If the app or window was previously launched from the app, it will regain focus when the app is loaded.

X-Frame Options must also be enabled for the configured PPM server.
If no Clarity server is configured, then a message to configure the clarity server will be presented.

![ScreenShot](/images/ppmtimesheet-app-settings.png)
Clarity version must be version 15.2 or above.

A Clarity host name or IP address and (optionally) HTTPS port must be configured through the app settings.
The default HTTPS port is 443.

![ScreenShot](/images/ppmtimesheet-app-settings.png)

## Development Notes


### First Load

If you've just downloaded this from github and you want to do development,
If you've just downloaded this from github and you want to do development,
you're going to need to have these installed:

* node.js
* grunt-cli
* grunt-init

Since you're getting this from github, we assume you have the command line
version of git also installed. If not, go get git.

Expand All @@ -31,36 +35,42 @@ to get set up to develop:

npm install

#### Deployment & Tests

If you want to use the automatic deployment mechanism, be sure to use the
**makeauth** task with grunt to create a local file that is used to connect
to Rally. This resulting auth.json file should NOT be checked in.

### Structure

* src/javascript: All the JS files saved here will be compiled into the
* src/javascript: All the JS files saved here will be compiled into the
target html file
* src/style: All of the stylesheets saved here will be compiled into the
* src/style: All of the stylesheets saved here will be compiled into the
target html file
* test/fast: Fast jasmine tests go here. There should also be a helper
* test/fast: Fast jasmine tests go here. There should also be a helper
file that is loaded first for creating mocks and doing other shortcuts
(fastHelper.js) **Tests should be in a file named <something>-spec.js**
* test/slow: Slow jasmine tests go here. There should also be a helper
file that is loaded first for creating mocks and doing other shortcuts
file that is loaded first for creating mocks and doing other shortcuts
(slowHelper.js) **Tests should be in a file named <something>-spec.js**
* templates: This is where templates that are used to create the production
and debug html files live. The advantage of using these templates is that
you can configure the behavior of the html around the JS.
* config.json: This file contains the configuration settings necessary to
create the debug and production html files.
* package.json: This file lists the dependencies for grunt
* auth.json: This file should NOT be checked in. Create this to create a
debug version of the app, to run the slow test specs and/or to use grunt to
install the app in your test environment. It should look like:
* auth.json: This file should NOT be checked in. This file is needed for deploying
and testing. You can use the makeauth task to create this or build it by hand in this'
format:
{
"username":"you@company.com",
"password":"secret",
"server": "https://rally1.rallydev.com"
}

### Usage of the grunt file
####Tasks
#### Tasks

##### grunt debug

Use grunt debug to create the debug html file. You only need to run this when you have added new files to
Expand All @@ -72,7 +82,7 @@ Use grunt build to create the production html file. We still have to copy the h

##### grunt test-fast

Use grunt test-fast to run the Jasmine tests in the fast directory. Typically, the tests in the fast
Use grunt test-fast to run the Jasmine tests in the fast directory. Typically, the tests in the fast
directory are more pure unit tests and do not need to connect to Rally.

##### grunt test-slow
Expand All @@ -85,7 +95,10 @@ data.

Use grunt deploy to build the deploy file and then install it into a new page/app in Rally. It will create the page on the Home tab and then add a custom html app to the page. The page will be named using the "name" key in the config.json file (with an asterisk prepended).

To use this task, you must create an auth.json file that contains the following keys:
You can use the makeauth task to create this file OR construct it by hand. Caution: the
makeauth task will delete this file.

The auth.json file must contain the following keys:
{
"username": "fred@fred.com",
"password": "fredfredfred",
Expand All @@ -109,6 +122,12 @@ pageOid and panelOid lines to install in a new place. CAUTION: Currently, erro

##### grunt watch

Run this to watch files (js and css). When a file is saved, the task will automatically build and deploy as shown in the deploy section above.
Run this to watch files (js and css). When a file is saved, the task will automatically build, run fast tests, and deploy as shown in the deploy section above.

##### grunt makeauth

This task will create an auth.json file in the proper format for you. **Be careful** this will delete any existing auth.json file. See **grunt deploy** to see the contents and use of this file.

##### grunt --help

# ppmtimesheet
Get a full listing of available targets.
135 changes: 53 additions & 82 deletions deploy/App.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
<head>
<title>PPM Timesheet</title>
<!-- (c) 2016 CA Technologies. All Rights Reserved. -->
<!-- Build Date: Wed Jan 25 2017 15:11:40 GMT-0700 (MST) -->
<!-- Build Date: Fri Jul 02 2021 08:54:49 GMT-0600 (Mountain Daylight Time) -->

<script type="text/javascript">
var APP_BUILD_DATE = "Wed Jan 25 2017 15:11:40 GMT-0700 (MST)";
var BUILDER = "kcorkan";
var CHECKSUM = 2752129514;
var APP_BUILD_DATE = "Fri Jul 02 2021 08:54:49 GMT-0600 (Mountain Daylight Time)";
var BUILDER = "kc683795";
var CHECKSUM = 3083753201;
</script>

<script type="text/javascript" src="/apps/x/sdk.js"></script>
Expand Down Expand Up @@ -211,108 +211,74 @@ Ext.define('Rally.apps.ppmtimesheet.PPMTimesheetApp', {

mixins: ['Rally.clientmetrics.ClientMetricsRecordable'],

appName: 'PPM Timesheet Frame',
appName: 'PPM Timesheet App v2',

config: {
defaultSettings: {
ppmHost: null,
ppmPort: 443,
ppmRelativePathWithParams: null
relativePath: null
}
},
autoScroll: false,
timesheetSuffix: '/pm/integration.html#',

timesheetSuffix: '/pm/integration.html#', //'/pm/#/timesheets',
loggedInMessage: "Connection to the Clarity timesheet has been launched in a separate tab.<br/><br/>Your browser pop-up blocker may interfere with this process.<br/><br/><a href=\"{0}\" target=\"clarityWindow\">Click here to access or re-launch Clarity.</a><br/><br/>If you will be accessing the Clarity timesheet regularly, you may wish to always allow popus from this site.",
//https://knowledge.broadcom.com/external/article?articleId=206489
launch: function() {

var server = this.getPPMHost(),
port = this.getPPMPort();

this.validateConfig(server, port).then({
success: this.addFrame,
success: this.addLauncher,
failure: this.showAppMessage,
scope: this
});
},
addFrame: function(){
this.logger.log('addFrame');
addLauncher: function(){
var server = this.getPPMHost(),
port = this.getPPMPort(),
relativePath = this.getPPMRelativePath(),
url = this.buildPPMTimesheetURL(server, port, relativePath);

try {

this.add({
xtype: 'container',
html: '<div class="secondary-message" style="font-family: ProximaNova,Helvetica,Arial;text-align:center;color:#8a8a8a;font-size:10pt;font-style:italic">Login to PPM through Agile Central is recommended only when using a private computer'
});
port = this.getPPMPort(),
relativePath = this.getPPMRelativePath(),
url = this.buildPPMTimesheetURL(server, port, relativePath),
height = this.getHeight() || 600;
this.logger.log("addLauncher",url);

var iframe = this.add({
xtype: 'component',
itemId: 'ppmIframe',
autoEl: {
tag: 'iframe',
style: 'height: 100%; width: 100%; border: none;',
src: url
}
});


var me = this;
iframe.getEl().dom.onload = function(e){
me.logger.log('iframe loaded', e, iframe.getEl().dom);
};
}
catch(e){
Rally.ui.notify.Notifier.showError({message: Ext.String.format("Error loading {0} into iFrame.",url)});
var msg = Ext.String.format(this.loggedInMessage, url, server);
this.add({
xtype: 'container',
html: '<div class="secondary-message" style="font-family: ProximaNova,Helvetica,Arial;text-align:center;color:#8a8a8a;font-size:12pt;font-style:italic">' + msg
});

this.launchWindow(url);
},
launchWindow: function(url){
if (!this.currentWindow || this.currentWindow.closed === true){
this.currentWindow = window.open(url,'clarityWindow') //,'toolbar=0,location=0,directories=0,status=0,menubar=0,scrollbars=1,resizable=0,width=700,height=600');
} else {
this.currentWindow.focus();
}

},

validateConfig: function(server, port){
var deferred = Ext.create('Deft.Deferred');

if (!server){
deferred.reject("No PPM Server and Port is configured. Please work with an administrator to configure your PPM https server.");
deferred.reject("No Clarity Server and Port is configured. Please work with an administrator to configure your Clarity https server.");
} else {
//Commented this out due to the chrome issue, as this fails on it.
//var httpRequest = new XMLHttpRequest(),
// suffix = '/ppm/rest/v1/private/userContext',
//url = this.buildPPMTimesheetURL(server, port);
//
//url = url.replace(this.timesheetSuffix, suffix);
//
//httpRequest.withCredentials = true;
//httpRequest.cors = true;
//httpRequest.onreadystatechange = function() {
// console.log('ready', httpRequest.readyState, httpRequest.status);
// if (httpRequest.readyState === 4) {
// console.log('readystate', httpRequest);
// if (httpRequest.status !== 200) {
// console.log('Failed', httpRequest.status);
// var msg = Ext.String.format('The PPM Server and Port provided is not responding as expected. Please verify the configuration in the App Settings.');
// deferred.reject(msg);
// } else {
deferred.resolve();
// }
// }
//};
//httpRequest.open('GET', url);
//httpRequest.send();
deferred.resolve();
}

return deferred;
},
buildPPMTimesheetURL: function(server, port, relativePath){
var url = server.startsWith( "https://" ) ? server : Ext.String.format("https://{0}",server);
var url = Ext.String.format("https://{0}",server);
if (port){
url = Ext.String.format("{0}:{1}", url, port);
}
// if relative path is given then either it's SSO environment or default timesheet suffix is not needed
if( relativePath ) {
if( !url.endsWith("/") && !relativePath.startsWith("/") ) {
url = url + "/";
}
if( !url.endsWith("/") && !relativePath.startsWith("/") ) {
url = url + "/";
}
return url + relativePath;
} else {
return url + this.timesheetSuffix;
Expand All @@ -338,24 +304,24 @@ Ext.define('Rally.apps.ppmtimesheet.PPMTimesheetApp', {

return [{
xtype: 'container',
html: '<div class="secondary-message" style="font-family: ProximaNovaBold,Helvetica,Arial;text-align:left;color:#B81B10;font-size:12pt;">NOTE: The PPM server must be version 15.2 or above.</div>'
html: '<div class="secondary-message" style="font-family: ProximaNovaBold,Helvetica,Arial;text-align:left;color:#B81B10;font-size:12pt;">NOTE: The Clarity server must be version 15.2 or above.</div>'
},{
name: 'ppmHost',
xtype: 'rallytextfield',
width: 400,
labelWidth: 150,
width: 600,
labelWidth: 225,
labelAlign: 'right',
fieldLabel: 'PPM Host name',
fieldLabel: 'Clarity Host name<br/><em>(for SSO the IdP URL)</em>',
margin: '10 0 10 0',
maskRe: /[a-zA-Z0-9\.\-]/,
emptyText: 'Please enter a Host name or IP Address...',
maxLength: 500
maxLength: 255
},{
name: 'ppmPort',
xtype:'rallynumberfield',
labelAlign: 'right',
fieldLabel: 'Port (HTTPS)',
labelWidth: 150,
labelWidth: 225,
emptyText: 443,
minValue: 0,
maxValue: 65535,
Expand All @@ -365,19 +331,19 @@ Ext.define('Rally.apps.ppmtimesheet.PPMTimesheetApp', {
},{
name: 'ppmRelativePathWithParams',
xtype: 'rallytextfield',
width: 605,
labelWidth: 150,
width: 600,
labelWidth: 225,
labelAlign: 'right',
fieldLabel: 'PPM Host Relative Path (for SSO only)',
fieldLabel: 'Clarity Host Relative Path<br/><em>(for SSO only)</em>',
margin: '10 0 10 0',
//maskRe: /[a-zA-Z0-9\.\-]/,
//emptyText: 'In SSO environment, enter relative path with any parameters of IdP initiated SSO PPM URL here and enter host address above ...',
emptyText: 'In SSO environment, enter relative path with any parameters of IdP initiated SSO PPM URL here...',
emptyText: 'In SSO environment, enter relative path with any parameters of IdP URL here...',
maxLength: 500
}];
}
});

Rally.launchApp('Rally.apps.ppmtimesheet.PPMTimesheetApp', {
name: 'PPM Timesheet'
});
Expand Down Expand Up @@ -407,6 +373,11 @@ Ext.define('Rally.apps.ppmtimesheet.PPMTimesheetApp', {
.noScrolling {
overflow: hidden;
}

.subtext {
color:dimgrey;
font-style: italic;
}
</style>

</head>
Expand Down
Binary file modified images/ppmtimesheet-app-settings.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@
"grunt": "~0.4.5",
"grunt-cli": "0.1.6",
"grunt-contrib-jasmine": "~0.5.2",
"grunt-contrib-uglify": "0.3.2",
"grunt-contrib-watch": "^1.1.0",
"grunt-templater": "git://github.com/rockwood/grunt-templater.git",
"request": "2.67",
"underscore": "1.4.4",
"grunt-contrib-uglify":"0.3.2",
"request":"2.67",
"grunt-contrib-watch":"1.0.0",
"username":"2.1.0"
"username": "2.1.0"
}
}
Loading