Extract factory for generating template URLs

This commit is contained in:
Joe Fiorini
2015-07-08 10:13:50 -04:00
parent c52c9d1c8a
commit d2440f6cd7
23 changed files with 308 additions and 214 deletions

View File

@@ -38,6 +38,7 @@ import mainMenu from 'tower/main-menu/main';
import browserData from 'tower/browser-data/main'; import browserData from 'tower/browser-data/main';
import dashboard from 'tower/dashboard/main'; import dashboard from 'tower/dashboard/main';
import moment from 'tower/shared/moment/main'; import moment from 'tower/shared/moment/main';
import templateUrl from 'tower/shared/template-url/main';
import {JobDetailController} from 'tower/controllers/JobDetail'; import {JobDetailController} from 'tower/controllers/JobDetail';
import {JobStdoutController} from 'tower/controllers/JobStdout'; import {JobStdoutController} from 'tower/controllers/JobStdout';
@@ -84,6 +85,7 @@ var tower = angular.module('Tower', [
mainMenu.name, mainMenu.name,
dashboard.name, dashboard.name,
moment.name, moment.name,
templateUrl.name,
'AuthService', 'AuthService',
'Utilities', 'Utilities',
'LicenseHelper', 'LicenseHelper',

View File

@@ -1,14 +1,14 @@
/* jshint unused: vars */ /* jshint unused: vars */
export default export default
[ '$rootScope', [ 'templateUrl',
function() { function(templateUrl) {
return { return {
restrict: 'E', restrict: 'E',
scope: { scope: {
data: '=' data: '='
}, },
replace: false, replace: false,
templateUrl: '/static/js/dashboard/counts/dashboard-counts.partial.html', templateUrl: templateUrl('dashboard/counts/dashboard-counts'),
link: function(scope, element, attrs) { link: function(scope, element, attrs) {
scope.$watch("data", function(data) { scope.$watch("data", function(data) {
if (data && data.hosts) { if (data && data.hosts) {

View File

@@ -1,11 +1,11 @@
/* jshint unused: vars */ /* jshint unused: vars */
export default export default
[ '$rootScope', [ 'templateUrl',
function() { function(templateUrl) {
return { return {
restrict: 'E', restrict: 'E',
scope: true, scope: true,
templateUrl: '/static/js/dashboard/dashboard.partial.html', templateUrl: templateUrl('dashboard/dashboard'),
link: function(scope, element, attrs) { link: function(scope, element, attrs) {
} }
}; };

View File

@@ -1,11 +1,11 @@
/* jshint unused: vars */ /* jshint unused: vars */
export default export default
[ '$rootScope', [ 'templateUrl',
function() { function(templateUrl) {
return { return {
restrict: 'E', restrict: 'E',
scope: true, scope: true,
templateUrl: '/static/js/dashboard/graphs/dashboard-graphs.partial.html', templateUrl: templateUrl('dashboard/graphs/dashboard-graphs'),
link: function(scope, element, attrs) { link: function(scope, element, attrs) {
function clearGraphs() { function clearGraphs() {
scope.jobStatusSelected = false; scope.jobStatusSelected = false;

View File

@@ -8,14 +8,15 @@
[ '$compile', [ '$compile',
'$window', '$window',
'adjustGraphSize', 'adjustGraphSize',
'templateUrl',
HostStatusGraph, HostStatusGraph,
]; ];
function HostStatusGraph($compile, $window, adjustGraphSize) { function HostStatusGraph($compile, $window, adjustGraphSize, templateUrl) {
return { return {
restrict: 'E', restrict: 'E',
link: link, link: link,
templateUrl: '/static/js/dashboard/graphs/host-status/host_status_graph.partial.html' templateUrl: templateUrl('dashboard/graphs/host-status/host_status_graph')
}; };
function link(scope, element, attr) { function link(scope, element, attr) {

View File

@@ -12,16 +12,17 @@
'Wait', 'Wait',
'adjustGraphSize', 'adjustGraphSize',
'jobStatusGraphData', 'jobStatusGraphData',
'templateUrl',
JobStatusGraph JobStatusGraph
]; ];
function JobStatusGraph($rootScope, $compile , $location, $window, Wait, adjustGraphSize, graphDataService) { function JobStatusGraph($rootScope, $compile , $location, $window, Wait, adjustGraphSize, graphDataService, templateUrl) {
return { return {
restrict: 'E', restrict: 'E',
scope: { scope: {
data: '=' data: '='
}, },
templateUrl: '/static/js/dashboard/graphs/job-status/job_status_graph.partial.html', templateUrl: templateUrl('dashboard/graphs/job-status/job_status_graph'),
link: link link: link
}; };

View File

@@ -1,8 +1,8 @@
import JobStatusGraphDirective from 'tower/dashboard/graphs/job-status/job-status-graph.directive'; import JobStatusGraphDirective from 'tower/dashboard/graphs/job-status/job-status-graph.directive';
import JobStatusGraphService from 'tower/dashboard/graphs/job-status/job-status-graph.service'; import JobStatusGraphService from 'tower/dashboard/graphs/job-status/job-status-graph.service';
import DashboardGraphHelpers from 'tower/dashboard/graphs/graph-helpers/main'; import DashboardGraphHelpers from 'tower/dashboard/graphs/graph-helpers/main';
import ApiLoader from 'tower/shared/api-loader'; import templateUrl from 'tower/shared/template-url/main';
export default angular.module('JobStatusGraph', [DashboardGraphHelpers.name, ApiLoader.name]) export default angular.module('JobStatusGraph', [DashboardGraphHelpers.name, templateUrl.name])
.directive('jobStatusGraph', JobStatusGraphDirective) .directive('jobStatusGraph', JobStatusGraphDirective)
.service('jobStatusGraphData', JobStatusGraphService); .service('jobStatusGraphData', JobStatusGraphService);

View File

@@ -1,14 +1,15 @@
/* jshint unused: vars */ /* jshint unused: vars */
export default export default
[ "PlaybookRun", [ "PlaybookRun",
function JobTemplatesList(PlaybookRun) { 'templateUrl',
function JobTemplatesList(PlaybookRun, templateUrl) {
return { return {
restrict: 'E', restrict: 'E',
link: link, link: link,
scope: { scope: {
data: '=' data: '='
}, },
templateUrl: '/static/js/dashboard/lists/job-templates/job-templates-list.partial.html' templateUrl: templateUrl('dashboard/lists/job-templates/job-templates-list')
}; };
function link(scope, element, attr) { function link(scope, element, attr) {

View File

@@ -1,43 +1,44 @@
/* jshint unused: vars */ /* jshint unused: vars */
export default export default
['moment', [ 'moment',
function JobsList(moment) { 'templateUrl',
return { function JobsList(moment, templateUrl) {
restrict: 'E', return {
link: link, restrict: 'E',
scope: { link: link,
data: '=' scope: {
}, data: '='
templateUrl: '/static/js/dashboard/lists/jobs/jobs-list.partial.html' },
}; templateUrl: templateUrl('dashboard/lists/jobs/jobs-list')
function link(scope, element, attr) {
scope.$watch("data", function(data) {
if (data) {
if (data.length > 0) {
createList(data);
scope.noJobs = false;
} else {
scope.noJobs = true;
}
}
});
function createList(list) {
// detailsUrl, status, name, time
scope.jobs = _.map(list, function(job){
return {
detailsUrl: job.url.replace("api/v1", "#"),
status: job.status,
name: job.name,
time: moment(job.finished).fromNow()
}; });
scope.snapRows = (list.length < 4);
}
scope.isSuccessful = function (status) {
return (status === "successful");
}; };
}
function link(scope, element, attr) {
scope.$watch("data", function(data) {
if (data) {
if (data.length > 0) {
createList(data);
scope.noJobs = false;
} else {
scope.noJobs = true;
}
}
});
function createList(list) {
// detailsUrl, status, name, time
scope.jobs = _.map(list, function(job){
return {
detailsUrl: job.url.replace("api/v1", "#"),
status: job.status,
name: job.name,
time: moment(job.finished).fromNow()
}; });
scope.snapRows = (list.length < 4);
}
scope.isSuccessful = function (status) {
return (status === "successful");
};
}
}]; }];

View File

@@ -1,15 +1,18 @@
export default function() { export default
return { [ 'templateUrl',
restrict: 'E', function(templateUrl) {
templateUrl: '/static/js/main-menu/menu-default.partial.html', return {
link: function(scope, element) { restrict: 'E',
var contents = element.contents(); templateUrl: templateUrl('main-menu/menu-default'),
contents.unwrap(); link: function(scope, element) {
var contents = element.contents();
contents.unwrap();
scope.$on('$destroy', function() { scope.$on('$destroy', function() {
contents.remove(); contents.remove();
$(".MenuItem--socketStatus").remove(); $(".MenuItem--socketStatus").remove();
}); });
}
};
} }
}; ];
}

View File

@@ -1,45 +1,48 @@
/* jshint unused: vars */ /* jshint unused: vars */
export default function() { export default
return { [ 'templateUrl',
restrict: 'E', function(templateUrl) {
controllerAs: 'mainMenu', return {
templateUrl: '/static/js/main-menu/main-menu.partial.html', restrict: 'E',
controller: ['$scope', function($scope) { controllerAs: 'mainMenu',
this.open = function() { templateUrl: templateUrl('main-menu/main-menu'),
$scope.isOpen = true; controller: ['$scope', function($scope) {
}; this.open = function() {
$scope.isOpen = true;
};
this.close = function() { this.close = function() {
$scope.isOpen = false; $scope.isOpen = false;
}; };
this.toggle = function() { this.toggle = function() {
$scope.isOpen = !$scope.isOpen; $scope.isOpen = !$scope.isOpen;
}; };
$scope.isOpen = false; $scope.isOpen = false;
}], }],
scope: { scope: {
menuStyle: '&menuStyle', menuStyle: '&menuStyle',
currentUser: '=' currentUser: '='
}, },
link: function(scope, element, attrs) { link: function(scope, element, attrs) {
scope.menuStyleClassName = 'blah'; scope.menuStyleClassName = 'blah';
scope.$watch(function() { scope.$watch(function() {
return scope.$eval(scope.menuStyle); return scope.$eval(scope.menuStyle);
}, function(newValue) { }, function(newValue) {
scope.menuStyleClassName = 'MainMenu--' + newValue; scope.menuStyleClassName = 'MainMenu--' + newValue;
}); });
scope.$watch('isOpen', function(isOpen) { scope.$watch('isOpen', function(isOpen) {
if (isOpen) { if (isOpen) {
element.find('.MainMenu').addClass("Menu--open"); element.find('.MainMenu').addClass("Menu--open");
element.find('menu-toggle-button').addClass("MenuToggle--open"); element.find('menu-toggle-button').addClass("MenuToggle--open");
} else { } else {
element.find('.MainMenu').removeClass("Menu--open"); element.find('.MainMenu').removeClass("Menu--open");
element.find('menu-toggle-button').removeClass("MenuToggle--open"); element.find('menu-toggle-button').removeClass("MenuToggle--open");
}
});
} }
}); };
} }
}; ];
}

View File

@@ -1,27 +1,30 @@
/* jshint unused: vars */ /* jshint unused: vars */
export default function() { export default
return { [ 'templateUrl',
templateUrl: '/static/js/main-menu/menu-toggle.partial.html', function(templateUrl) {
restrict: 'E', return {
require: '^^mainMenu', templateUrl: templateUrl('main-menu/menu-toggle'),
scope: { restrict: 'E',
width: '@', require: '^^mainMenu',
height: '@', scope: {
barHeight: '@' width: '@',
}, height: '@',
link: function(scope, element, attrs, mainMenuController) { barHeight: '@'
scope.$on('$destroy', function() { },
element.off('click'); link: function(scope, element, attrs, mainMenuController) {
}); scope.$on('$destroy', function() {
element.off('click');
});
element.on("click", function(e) { element.on("click", function(e) {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
scope.$apply(function() { scope.$apply(function() {
mainMenuController.toggle(); mainMenuController.toggle();
}); });
}); });
}
};
} }
}; ];
}

View File

@@ -1,15 +1,18 @@
export default function() { export default
return { [ 'templateUrl',
restrict: 'E', function(templateUrl) {
templateUrl: '/static/js/main-menu/menu-portal.partial.html', return {
link: function(scope, element) { restrict: 'E',
var contents = element.contents(); templateUrl: templateUrl('main-menu/menu-portal'),
contents.unwrap(); link: function(scope, element) {
var contents = element.contents();
contents.unwrap();
scope.$on('$destroy', function() { scope.$on('$destroy', function() {
contents.remove(); contents.remove();
$(".MenuItem--socketStatus").remove(); $(".MenuItem--socketStatus").remove();
}); });
}
};
} }
}; ];
}

View File

@@ -1,18 +1,22 @@
/* jshint unused: vars */ /* jshint unused: vars */
export default ['$rootScope', function($rootScope) { export default
return { [ '$rootScope',
restrict: 'E', 'templateUrl',
templateUrl: '/static/js/main-menu/web-socket-status.partial.html', function($rootScope, templateUrl) {
link: function(scope, element, attrs) { return {
scope.socketHelp = $rootScope.socketHelp; restrict: 'E',
scope.socketTip = $rootScope.socketTip; templateUrl: templateUrl('main-menu/web-socket-status'),
$rootScope.$watch('socketStatus', function(newStatus) { link: function(scope, element, attrs) {
scope.socketStatus = newStatus; scope.socketHelp = $rootScope.socketHelp;
}); scope.socketTip = $rootScope.socketTip;
$rootScope.$watch('socketTip', function(newTip) { $rootScope.$watch('socketStatus', function(newStatus) {
scope.socketTip = newTip; scope.socketStatus = newStatus;
}); });
$rootScope.$watch('socketTip', function(newTip) {
scope.socketTip = newTip;
});
}
};
} }
}; ];
}];

View File

@@ -9,30 +9,33 @@
import controller from './breadcrumbs.controller'; import controller from './breadcrumbs.controller';
import 'tower/shared/generator-helpers'; import 'tower/shared/generator-helpers';
export default function() { export default
[ 'templateUrl',
function(templateUrl) {
return { return {
restrict: 'E', restrict: 'E',
controller: controller, controller: controller,
transclude: true, transclude: true,
templateUrl: '/static/js/shared/breadcrumbs/breadcrumbs.partial.html', templateUrl: templateUrl('shared/breadcrumbs/breadcrumbs'),
scope: { scope: {
}, },
link: function(scope, element, attrs, controller) { link: function(scope, element, attrs, controller) {
// make breadcrumbs hidden until the current // make breadcrumbs hidden until the current
// breadcrumb has a title; this avoids // breadcrumb has a title; this avoids
// ugly rendering when an object's title // ugly rendering when an object's title
// is fetched via ajax // is fetched via ajax
// //
controller.setHidden(); controller.setHidden();
scope.$watch('isHidden', function(value) { scope.$watch('isHidden', function(value) {
if (value) { if (value) {
element.hide(); element.hide();
} else { } else {
element.show(); element.show();
}
});
} }
}); };
} }
}; ];
}

View File

@@ -1,29 +1,32 @@
export default function() { export default
return { [ 'templateUrl',
restrict: 'E', function(templateUrl) {
templateUrl: '/static/js/shared/icon/icon.partial.html', return {
scope: { restrict: 'E',
}, templateUrl: templateUrl('shared/icon/icon'),
link: function(scope, element, attrs) { scope: {
var svg = $('svg', element); },
var iconPath = '#' + attrs.name; link: function(scope, element, attrs) {
var svg = $('svg', element);
var iconPath = '#' + attrs.name;
// Make a copy of the <symbol> tag to insert its contents into this // Make a copy of the <symbol> tag to insert its contents into this
// element's svg tag // element's svg tag
var content = $(iconPath).clone(); var content = $(iconPath).clone();
// Copy classes & viewBox off the <symbol> so that we preserve any styling // Copy classes & viewBox off the <symbol> so that we preserve any styling
// when we copy the item inline // when we copy the item inline
var classes = $(iconPath).attr('class'); var classes = $(iconPath).attr('class');
// viewBox needs to be access via native // viewBox needs to be access via native
// javascript's setAttribute function // javascript's setAttribute function
var viewBox = $(iconPath)[0].getAttribute('viewBox'); var viewBox = $(iconPath)[0].getAttribute('viewBox');
svg[0].setAttribute('viewBox', viewBox); svg[0].setAttribute('viewBox', viewBox);
svg.attr('class', classes) svg.attr('class', classes)
.html(content.contents()); .html(content.contents());
}
};
} }
}; ];
}

View File

@@ -7,9 +7,10 @@
import multiSelect from './multi-select-list.directive'; import multiSelect from './multi-select-list.directive';
import selectAll from './select-all.directive'; import selectAll from './select-all.directive';
import selectListItem from './select-list-item.directive'; import selectListItem from './select-list-item.directive';
import templateUrl from 'tower/shared/template-url/main';
export default export default
angular.module('multiSelectList', []) angular.module('multiSelectList', [templateUrl.name])
.directive('multiSelectList', multiSelect) .directive('multiSelectList', multiSelect)
.directive('selectAll', selectAll) .directive('selectAll', selectAll)
.directive('selectListItem', selectListItem); .directive('selectListItem', selectListItem);

View File

@@ -129,12 +129,10 @@
// // => // // =>
// '/static/js/shared/multi-select-list/select-all.html // '/static/js/shared/multi-select-list/select-all.html
// //
function template(base) {
return '/static/js/' + base + '.partial.html';
}
export default export default
[ function() { [ 'templateUrl',
function(templateUrl) {
return { return {
require: '^multiSelectList', require: '^multiSelectList',
restrict: 'E', restrict: 'E',
@@ -145,7 +143,7 @@ export default
extendedLabel: '&', extendedLabel: '&',
isSelectionEmpty: '=selectionsEmpty' isSelectionEmpty: '=selectionsEmpty'
}, },
templateUrl: template('shared/multi-select-list/select-all'), templateUrl: templateUrl('shared/multi-select-list/select-all'),
link: function(scope, element, attrs, controller) { link: function(scope, element, attrs, controller) {
scope.label = scope.label || 'All'; scope.label = scope.label || 'All';

View File

@@ -0,0 +1,6 @@
import templateUrl from './template-url.factory';
export default
angular.module('templateUrl', [])
.factory('templateUrl', templateUrl);

View File

@@ -0,0 +1,20 @@
function templateUrl($sce, path, isTrusted) {
isTrusted = isTrusted !== false; // defaults to true, can be passed in as false
var parts = ['', 'static', 'js'];
parts.push(path);
var url = parts.join('/') + '.partial.html';
if (isTrusted) {
url = $sce.trustAsResourceUrl(url);
}
return url;
}
export default
[ '$sce',
function($sce) {
return _.partial(templateUrl, $sce);
}
];

View File

@@ -8,7 +8,8 @@
export default export default
[ 'moment', [ 'moment',
function(moment) { 'templateUrl',
function(moment, templateUrl) {
return { return {
restrict: 'E', restrict: 'E',
scope: { scope: {
@@ -17,7 +18,7 @@ export default
autoUpdate: '=?', autoUpdate: '=?',
inputClass: '&' inputClass: '&'
}, },
templateUrl: '/static/js/system-tracking/date-picker/date-picker.partial.html', templateUrl: templateUrl('system-tracking/date-picker/date-picker'),
link: function(scope, element, attrs) { link: function(scope, element, attrs) {
// We need to make sure this _never_ recurses, which sometimes happens // We need to make sure this _never_ recurses, which sometimes happens

View File

@@ -1,9 +1,10 @@
/* jshint unused: vars */ /* jshint unused: vars */
export default export default
[ function() { [ 'templateUrl',
function(templateUrl) {
return { restrict: 'E', return { restrict: 'E',
templateUrl: '/static/js/system-tracking/fact-data-table/fact-data-table.partial.html', templateUrl: templateUrl('system-tracking/fact-data-table/fact-data-table'),
scope: scope:
{ leftHostname: '=', { leftHostname: '=',
rightHostname: '=', rightHostname: '=',

View File

@@ -0,0 +1,39 @@
var jsdom = require('jsdom').jsdom;
var document = jsdom('tower');
var window = document.parentWindow;
var mocha = require('mocha');
window.mocha = mocha;
window.beforeEach = beforeEach;
window.afterEach = afterEach;
global.document = document;
global.window = window;
require('angular/angular');
var jquery = require('jquery');
require('angular-mocks/angular-mocks');
var chai = require('chai');
var expect = chai.expect;
var sinonChai = require('sinon-chai');
var chaiAsPromised = require('chai-as-promised');
var sinon = require('sinon');
var chaiThings = require('chai-things');
chai.use(sinonChai);
chai.use(chaiAsPromised);
chai.use(chaiThings);
global.$ = window.$ = jquery;
global.angular = window.angular;
global.expect = chai.expect;
angular.module('templates', []);
require('../../templates');
var lodash = require('lodash');
global._ = lodash;
var LocalStorage = require('node-localstorage').LocalStorage;
global.localStorage = window.localStorage = new LocalStorage('./scratch');