i recently started a confluence cloud project using atlassian connect express.
but i couldn't use any method to include a stylesheet into my macros
here is my index.js
module.exports = function (app, addon) {
// Root route. This route will serve the `atlassian-connect.json` unless the
// documentation url inside `atlassian-connect.json` is set
app.get('/', function (req, res) {
res.format({
// If the request content-type is text-html, it will decide which to serve up
'text/html': function () {
res.redirect('/atlassian-connect.json');
},
// This logic is here to make sure that the `atlassian-connect.json` is always
// served up when requested by the host
'application/json': function () {
res.redirect('/atlassian-connect.json');
}
});
});
// This is an example route that's used by the default "generalPage" module.
// Verify that the incoming request is authenticated with Atlassian Connect
app.get('/hello-world', addon.authenticate(), function (req, res) {
// Rendering a template is easy; the `render()` method takes two params: name of template
// and a json object to pass the context in
res.render('hello-world', {
title: 'Atlassian Connect'
//issueId: req.query['issueId']
});
}
);
// Add any additional route handlers you need for views or REST resources here...
// Render the background-color macro.
app.get('/v1/backgroundColor',addon.authenticate(), function(req, res){
// Grab all input parameters - sent through to us as query params.
var color = req.query['color'],
pageId = req.query['pageId'],
pageVersion = req.query['pageVersion'],
macroHash = req.query['macroHash'],
userKey = req.query['user_key'];
var clientKey = req.context.clientKey;
console.log(" ----- clientKey : ", clientKey);
console.log(" ----- userKey : ", userKey);
// Execute API request to get the macro body.
getHTTPClient(clientKey, userKey).get(
'/rest/api/content/' + pageId +
'/history/' + pageVersion +
'/macro/hash/' + macroHash,
function(err, response, contents){
console.log(" ----- response status: ", response.statusCode);
// If we've encountered errors, render an error screen.
if(err || (response.statusCode < 200 || response.statusCode > 299)) {
console.log(err);
res.render('<strong>An error has occurred :( '+ response.statusCode +'</strong>');
}
console.log(" ----- contents : ", contents);
// Parse the response, and send the body through.
contents = JSON.parse(contents);
// Render with required body.
res.render('background-color', { body : contents.body, color: color });
}
);
});
app.get('/v1/progressbar',addon.authenticate(), function(req, res){
// Grab all input parameters - sent through to us as query params.
var steps = req.query['steps'],
currentstep = req.query['currentstep'],
pageId = req.query['pageId'],
pageVersion = req.query['pageVersion'],
macroHash = req.query['macroHash'],
userKey = req.query['user_key'];
var clientKey = req.context.clientKey;
console.log(" ----- clientKey : ", clientKey);
console.log(" ----- userKey : ", userKey);
// Execute API request to get the macro body.
getHTTPClient(clientKey, userKey).get(
'/rest/api/content/' + pageId +
'/history/' + pageVersion +
'/macro/hash/' + macroHash,
function(err, response, contents){
console.log(" ----- response status: ", response.statusCode);
// If we've encountered errors, render an error screen.
if(err || (response.statusCode < 200 || response.statusCode > 299)) {
console.log(err);
res.render('<strong>An error has occurred :( '+ response.statusCode +'</strong>');
}else{
console.log(" ----- contents : ", contents);
// Parse the response, and send the body through.
contents = JSON.parse(contents);
// Render with required body.
res.render('progress-bar', { body : currentstep, color: steps });
}
}
);
});
// load any additional files you have in routes and apply those to the app
{
var fs = require('fs');
var path = require('path');
var files = fs.readdirSync("routes");
for(var index in files) {
var file = files[index];
if (file === "index.js") continue;
// skip non-javascript files
if (path.extname(file) != ".js") continue;
var routes = require("./" + path.basename(file));
if (typeof routes === "function") {
routes(app, addon);
}
}
}
function getHTTPClient (clientKey, userKey){
return addon.httpClient({
clientKey : clientKey,
userKey : userKey,
appKey : addon.key
});
}
};
my macro handlebar file
{{!< layout}}
{{!--
If we have received a macro body, render it.
Otherwise, show a preview screen/message.
--}}
<div>
<ol class="aui-progress-tracker">
<li class="aui-progress-tracker-step" style="width:25%"><span>Configure instance</span></li>
<li class="aui-progress-tracker-step aui-progress-tracker-step-current" style="width:25%"><span>Select plugins</span>
</li>
<li class="aui-progress-tracker-step" style="width:25%"><span>Invite users</span></li>
<li class="aui-progress-tracker-step" style="width:25%"><span>Confirm</span></li>
</ol>
</div>
my layout.hbs
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="ap-local-base-url" content="{{localBaseUrl}}">
<title>{{title}}</title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script src="//aui-cdn.atlassian.com/aui-adg/6.0.9/js/aui.min.js"></script>
<link rel="stylesheet" href="//aui-cdn.atlassian.com/aui-adg/6.0.9/css/aui.min.css" media="all">
<link rel="stylesheet" href="//aui-cdn.atlassian.com/aui-adg/6.0.9/css/aui-experimental.min.css" media="all">
<script src="//aui-cdn.atlassian.com/aui-adg/6.0.9/js/aui-experimental.min.js"></script>
<script src="//aui-cdn.atlassian.com/aui-adg/6.0.9/js/aui-datepicker.min.js"></script>
<script src="//aui-cdn.atlassian.com/aui-adg/6.0.9/js/aui-soy.min.js"></script>
<!--[if IE 9]><link rel="stylesheet" href="//aui-cdn.atlassian.com/aui-adg/5.9.21/css/aui-ie9.css" media="all"><![endif]-->
<link rel="stylesheet" href="{{furl '/css/addon.css'}}" type="text/css" />
<script src="{{hostScriptUrl}}" type="text/javascript"></script>
</head>
<body class="aui-page-hybrid">
<section id="content" role="main">
{{{body}}}
</section>
<script src="{{furl '/js/addon.js'}}"></script>
</body>
</html>
and my css file which contains the defined classes
/* add-on styles */
.intro-header h1 {
font-size: 48px;
line-height: 60px;
padding-top: 20px;
}
.intro-header p.subtitle {
font-size: 24px;
line-height: 30px;
padding-bottom: 20px;
}
.main-panel .aui-page-panel-item {
padding: 20px 40px 20px 0;
height: 100px;
}
/* SFM styles */
/* Layout */
.aui-progress-tracker {
display: table;
font-size: 12px;
margin: 10px 0 0;
padding: 0;
table-layout: fixed;
word-wrap: break-word; /* doesn't work in IE */
}
.aui-progress-tracker:first-child {
margin-top: 0;
}
.aui-progress-tracker-step {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
display: table-cell;
padding: 0 10px;
max-width: 140px;
min-width: 80px;
text-align: center;
}
/* Progress Bar */
.aui-progress-tracker-step > span,
.aui-progress-tracker-step > a {
display: block;
font-weight: bold;
outline: none;
padding-top: 25px;
position: relative;
}
.aui-progress-tracker-step > span:before,
.aui-progress-tracker-step > a:before {
background: #3b73af;
border-radius: 100%;
box-shadow: 0 0 0 3px #f5f5f5; /* can't just use a 3px border as an IE9 bug causes it to draw a strange additional darker border on the outside in addition to the 3px border */
content: "";
height: 10px;
left: 50%;
margin-left: -5px;
position: absolute;
top: 3px;
width: 10px;
}
.aui-progress-tracker-step + .aui-progress-tracker-step > span:after,
.aui-progress-tracker-step + .aui-progress-tracker-step > a:after {
background: #3b73af;
border: solid #f5f5f5;
border-width: 2px 0;
box-shadow: -5px 0 0 -2px #3b73af, 5px 0 0 -2px #3b73af;
content: "";
height: 4px;
left: -50%;
margin-left: -14px; /* almost touches right edge of previous dot (leaves 1px room for rounding widths like 33.3% in webkit) */
margin-right: 6px; /* almost touches left edge of this dot (leaves 1px room for rounding widths like 33.3% in webkit) */
position: absolute;
right: 50%;
top: 4px;
}
.aui-progress-tracker-step-current ~ .aui-progress-tracker-step {
color: #707070;
}
.aui-progress-tracker-step-current ~ .aui-progress-tracker-step > span:before,
.aui-progress-tracker-step-current ~ .aui-progress-tracker-step > a:before {
background-color: #ccc;
}
.aui-progress-tracker-step-current ~ .aui-progress-tracker-step > span:after,
.aui-progress-tracker-step-current ~ .aui-progress-tracker-step > a:after {
background-color: #f5f5f5;
box-shadow: none;
}
/* Inverted Colours */
.aui-progress-tracker-inverted .aui-progress-tracker-step > span:before,
.aui-progress-tracker-inverted .aui-progress-tracker-step > a:before {
box-shadow: 0 0 0 3px #fff;
}
.aui-progress-tracker-inverted .aui-progress-tracker-step + .aui-progress-tracker-step > span:after,
.aui-progress-tracker-inverted .aui-progress-tracker-step + .aui-progress-tracker-step > a:after {
border-color: #fff;
}
.aui-progress-tracker-inverted .aui-progress-tracker-step-current ~ .aui-progress-tracker-step > span:after,
.aui-progress-tracker-inverted .aui-progress-tracker-step-current ~ .aui-progress-tracker-step > a:after {
background-color: #fff;
}
/* Interaction wih page layout */
.aui-page-header-actions .aui-progress-tracker {
float: right;
}