diff --git a/awx/ui/static/js/controllers/Home.js b/awx/ui/static/js/controllers/Home.js
index 73f978b026..e3a8c2dd38 100644
--- a/awx/ui/static/js/controllers/Home.js
+++ b/awx/ui/static/js/controllers/Home.js
@@ -27,43 +27,11 @@
*/
export function Home($scope, $compile, $routeParams, $rootScope, $location, $log, Wait, DashboardCounts, DashboardJobs,
- ClearScope, Stream, Rest, GetBasePath, ProcessErrors, Button, $window, graphData){
+ ClearScope, Stream, Rest, GetBasePath, ProcessErrors, $window, graphData){
ClearScope('home');
- var buttons, html, e, borderStyles;
-
- // Add buttons to the top of the Home page. We're using lib/ansible/generator_helpers.js-> Buttons()
- // to build buttons dynamically and insure all styling and icons match the rest of the application.
- buttons = {
- refresh: {
- mode: 'all',
- awToolTip: "Refresh the page",
- ngClick: "refresh()",
- ngShow:"socketStatus == 'error'"
- },
- stream: {
- ngClick: "showActivity()",
- awToolTip: "View Activity Stream",
- mode: 'all'
- }
- };
-
- html = Button({
- btn: buttons.refresh,
- action: 'refresh',
- toolbar: true
- });
-
- html += Button({
- btn: buttons.stream,
- action: 'stream',
- toolbar: true
- });
-
- e = angular.element(document.getElementById('home-list-actions'));
- e.html(html);
- $compile(e)($scope);
+ var borderStyles;
if (!$routeParams.login) {
// If we're not logging in, start the Wait widget. Otherwise, it's already running.
@@ -136,7 +104,7 @@ export function Home($scope, $compile, $routeParams, $rootScope, $location, $log
}
Home.$inject = ['$scope', '$compile', '$routeParams', '$rootScope', '$location', '$log','Wait', 'DashboardCounts', 'DashboardJobs',
- 'ClearScope', 'Stream', 'Rest', 'GetBasePath', 'ProcessErrors', 'Button', '$window', 'graphData'
+ 'ClearScope', 'Stream', 'Rest', 'GetBasePath', 'ProcessErrors', '$window', 'graphData'
];
diff --git a/awx/ui/static/js/controllers/Portal.js b/awx/ui/static/js/controllers/Portal.js
index 7fc9b4bb4e..3af4a2234d 100644
--- a/awx/ui/static/js/controllers/Portal.js
+++ b/awx/ui/static/js/controllers/Portal.js
@@ -25,47 +25,15 @@
*
*/
export function PortalController($scope, $compile, $routeParams, $rootScope, $location, $log, Wait, ClearScope, Stream, Rest, GetBasePath, ProcessErrors,
- Button, PortalJobsWidget, GenerateList, PortalJobTemplateList, SearchInit, PaginateInit, PlaybookRun){
+ PortalJobsWidget, GenerateList, PortalJobTemplateList, SearchInit, PaginateInit, PlaybookRun){
ClearScope('portal');
- var html,
- e,
- jobs_scope,
+ var jobs_scope,
list = PortalJobTemplateList,
view= GenerateList,
defaultUrl = GetBasePath('job_templates'),
- max_rows,
- buttons = {
- refresh: {
- mode: 'all',
- awToolTip: "Refresh the page",
- ngClick: "refresh()",
- ngShow:"socketStatus == 'error'"
- }
- // ,
- // stream: {
- // ngClick: "showActivity()",
- // awToolTip: "View Activity Stream",
- // mode: 'all'
- // }
- };
-
- html = Button({
- btn: buttons.refresh,
- action: 'refresh',
- toolbar: true
- });
-
- // html += Button({
- // btn: buttons.stream,
- // action: 'stream',
- // toolbar: true
- // });
-
- e = angular.element(document.getElementById('portal-list-actions'));
- e.html(html);
- $compile(e)($scope);
+ max_rows;
if ($scope.removeLoadPortal) {
$scope.removeLoadPortal();
@@ -176,5 +144,5 @@ export function PortalController($scope, $compile, $routeParams, $rootScope, $lo
}
PortalController.$inject = ['$scope', '$compile', '$routeParams', '$rootScope', '$location', '$log','Wait', 'ClearScope', 'Stream', 'Rest', 'GetBasePath', 'ProcessErrors',
- 'Button', 'PortalJobsWidget', 'generateList' , 'PortalJobTemplateList', 'SearchInit', 'PaginateInit', 'PlaybookRun'
+ 'PortalJobsWidget', 'generateList' , 'PortalJobTemplateList', 'SearchInit', 'PaginateInit', 'PlaybookRun'
];
diff --git a/awx/ui/static/js/shared/directives.js b/awx/ui/static/js/shared/directives.js
index 9fa121b43c..e751460fd6 100644
--- a/awx/ui/static/js/shared/directives.js
+++ b/awx/ui/static/js/shared/directives.js
@@ -404,6 +404,7 @@ angular.module('AWDirectives', ['RestServices', 'Utilities', 'AuthService', 'Job
*/
.directive('awToolTip', ['$sce', function($sce) {
return {
+ priority: 1000,
link: function(scope, element, attrs) {
var delay = (attrs.delay !== undefined && attrs.delay !== null) ? attrs.delay : ($AnsibleConfig) ? $AnsibleConfig.tooltip_delay : {show: 500, hide: 100},
placement;
diff --git a/awx/ui/static/js/shared/form-generator.js b/awx/ui/static/js/shared/form-generator.js
index 4d27d4c918..9affa6dcd8 100644
--- a/awx/ui/static/js/shared/form-generator.js
+++ b/awx/ui/static/js/shared/form-generator.js
@@ -139,9 +139,9 @@ export default
angular.module('FormGenerator', [GeneratorHelpers.name, 'Utilities', listGenerator.name])
.factory('GenerateForm', ['$rootScope', '$location', '$compile', 'generateList', 'SearchWidget', 'PaginateWidget', 'Attr',
- 'Icon', 'Column', 'NavigationLink', 'HelpCollapse', 'Button', 'DropDown', 'Empty', 'SelectIcon', 'Store',
+ 'Icon', 'Column', 'NavigationLink', 'HelpCollapse', 'DropDown', 'Empty', 'SelectIcon', 'Store',
function ($rootScope, $location, $compile, GenerateList, SearchWidget, PaginateWidget, Attr, Icon, Column, NavigationLink,
- HelpCollapse, Button, DropDown, Empty, SelectIcon, Store) {
+ HelpCollapse, DropDown, Empty, SelectIcon, Store) {
return {
setForm: function (form) { this.form = form; },
@@ -553,7 +553,50 @@ angular.module('FormGenerator', [GeneratorHelpers.name, 'Utilities', listGenerat
}
},
- button: Button,
+ button: function(params) {
+ var tagName = "button";
+ var options = params.btn;
+ var tagParts =
+ [ tagName,
+ "toolbar-button"
+ ];
+
+ var attrNames = _.keys(options);
+
+ function isSupportedKey(keyName) {
+ if (keyName === 'icon') {
+ //TODO: Let's add a depecrated logger to our logging helper to output the below message
+ //
+ // The form action key "icon" is deprecated in favor of using the name of the field as the icon name or the iconClass option.
+ return false;
+ }
+
+ return true;
+ }
+
+ var attrs = attrNames
+ .filter(function(name) {
+
+ return isSupportedKey(name) &&
+ !_.isEmpty(options[name]);
+
+ }).map(function(name) {
+ return Attr(options, name);
+ });
+
+ tagParts =
+ tagParts
+ .concat(attrs)
+ .concat(
+ Attr(params, 'iconName'),
+ Attr(params, 'toolbar')
+ );
+
+ var html = "<" + tagParts.join(" ") + ">" + tagName + ">";
+
+ return html;
+
+ },
navigationLink: NavigationLink,
@@ -1346,7 +1389,7 @@ angular.module('FormGenerator', [GeneratorHelpers.name, 'Utilities', listGenerat
var html = "
\n", action;
for (action in this.form.actions) {
if (this.form.actions[action].mode === 'all' || this.form.actions[action].mode === options.mode) {
- html += this.button({ btn: this.form.actions[action], action: action, toolbar: true });
+ html += this.button({ btn: this.form.actions[action], iconName: action, toolbar: true });
}
}
html += "
\n";
@@ -1722,7 +1765,7 @@ angular.module('FormGenerator', [GeneratorHelpers.name, 'Utilities', listGenerat
action = collection.actions[act];
html += this.button({
btn: action,
- action: act,
+ iconName: act,
toolbar: true
});
}
diff --git a/awx/ui/static/js/shared/generator-helpers.js b/awx/ui/static/js/shared/generator-helpers.js
index 1c8f67c372..a68844e7a7 100644
--- a/awx/ui/static/js/shared/generator-helpers.js
+++ b/awx/ui/static/js/shared/generator-helpers.js
@@ -55,6 +55,12 @@ angular.module('GeneratorHelpers', [systemStatus.name])
case 'columnShow':
result = "ng-show=\"" + value + "\" ";
break;
+ case 'iconName':
+ result = "icon-name=\"" + value + "\" ";
+ break;
+ case 'iconSize':
+ result = "icon-size=\"" + value + "\" ";
+ break;
case 'icon':
// new method of constructing icon tag. Replaces Icon method.
result = "";
- html += (btn.img) ? "
" : "";
-
- if (btn.iconClass) {
- html += "";
- }
- else {
- html += SelectIcon({
- action: action,
- size: btn.iconSize
- });
- }
-
- html += (btn.label) ? " " + btn.label : "";
- html += " ";
-
- return html;
- };
- }
-])
-
-
.factory('NavigationLink', ['Attr', 'Icon',
function (Attr, Icon) {
return function (link) {
diff --git a/awx/ui/static/js/shared/list-generator/list-actions.partial.html b/awx/ui/static/js/shared/list-generator/list-actions.partial.html
new file mode 100644
index 0000000000..22982b8a60
--- /dev/null
+++ b/awx/ui/static/js/shared/list-generator/list-actions.partial.html
@@ -0,0 +1,29 @@
+
+
+
+
diff --git a/awx/ui/static/js/shared/list-generator/list-generator.factory.js b/awx/ui/static/js/shared/list-generator/list-generator.factory.js
index 88852cb086..78856e4961 100644
--- a/awx/ui/static/js/shared/list-generator/list-generator.factory.js
+++ b/awx/ui/static/js/shared/list-generator/list-generator.factory.js
@@ -1,7 +1,7 @@
export default ['$location', '$compile', '$rootScope', 'SearchWidget', 'PaginateWidget', 'Attr', 'Icon',
- 'Column', 'DropDown', 'NavigationLink', 'Button', 'SelectIcon', 'Breadcrumbs',
+ 'Column', 'DropDown', 'NavigationLink', 'SelectIcon', 'Breadcrumbs',
function ($location, $compile, $rootScope, SearchWidget, PaginateWidget, Attr, Icon, Column, DropDown, NavigationLink,
- Button, SelectIcon, Breadcrumbs) {
+ SelectIcon, Breadcrumbs) {
return {
setList: function (list) {
@@ -24,8 +24,6 @@ export default ['$location', '$compile', '$rootScope', 'SearchWidget', 'Paginate
$('#lookup-modal').modal('hide');
},
- button: Button,
-
buildHTML: function(list, options) {
this.setList(list);
return this.build(options);
@@ -74,12 +72,11 @@ export default ['$location', '$compile', '$rootScope', 'SearchWidget', 'Paginate
this.scope.mode = options.mode;
this.scope.performAction = function(action) {
- console.log('performing:', action);
this.scope.$eval(action);
}.bind(this);
this.scope.shouldHideAction = function(options) {
- return _.tap(this.scope.$eval(options.ngHide), function(value) { console.log('shouldHide:', value, this.scope.selected_group_id, options); }.bind(this));
+ return this.scope.$eval(options.ngHide);
}.bind(this);
this.scope.canShowAction = function(action) {
var base = $location.path().replace(/^\//, '').split('/')[0];
@@ -92,12 +89,9 @@ export default ['$location', '$compile', '$rootScope', 'SearchWidget', 'Paginate
if (this.scope.shouldHideAction(action)) {
return false;
} else if (!scopeShow) {
- console.log('scopeShow false', action.ngShow);
return false;
} else {
- return _.tap(inActionMode && onScreenForAction, function(value) {
- console.log('mode ', value, action);
- });
+ return inActionMode && onScreenForAction;
}
// return _.tap(scopeShow || , function(value) {
@@ -154,7 +148,7 @@ export default ['$location', '$compile', '$rootScope', 'SearchWidget', 'Paginate
//
var html = '',
list = this.list,
- base, size, action, btn, fld, cnt, field_action, fAction, itm;
+ base, size, action, fld, cnt, field_action, fAction, itm;
if (options.activityStream) {
// Breadcrumbs for activity stream widget
@@ -254,32 +248,16 @@ export default ['$location', '$compile', '$rootScope', 'SearchWidget', 'Paginate
}
html += "\">\n";
- html += "\n";
- html += '
';
- html += '';
- html += '';
- //select instructions
- if (options.mode === 'select' && list.selectInstructions) {
- btn = {
- awPopOver: list.selectInstructions,
- dataPlacement: 'left',
- dataContainer: 'body',
- 'class': 'btn-xs btn-help',
- awToolTip: 'Click for help',
- dataTitle: 'Help',
- iconSize: 'fa-lg'
- };
- //html += this.button(btn, 'select');
- html += this.button({
- btn: btn,
- action: 'help',
- toolbar: true
- });
+ html += "
\n";
+
+ for (action in list.actions) {
+ list.actions[action] =
+ _.defaults(list.actions[action],
+ { dataPlacement: "top"
+ });
}
-
-
html += "
\n";
html += "
\n";
diff --git a/awx/ui/static/js/shared/list-generator/toolbar-button.directive.js b/awx/ui/static/js/shared/list-generator/toolbar-button.directive.js
index 5b0e0288db..a997ab0776 100644
--- a/awx/ui/static/js/shared/list-generator/toolbar-button.directive.js
+++ b/awx/ui/static/js/shared/list-generator/toolbar-button.directive.js
@@ -1,39 +1,60 @@
-export default ['$compile', 'Button', function($compile, Button) {
+export default ['$compile', 'Attr', 'SelectIcon', function($compile, Attr, SelectIcon) {
return {
- restrict: 'E',
- scope: {
- name: '=',
- options: '=',
- onSelected: '&'
- },
+ restrict: 'A',
+ scope: {},
link: function(scope, element, attrs) {
- var html = '';
- // Save the ngClick property from
- // legacy list actions
- scope.action = scope.options.ngClick;
+ var toolbar = attrs.toolbar;
+ if (toolbar) {
+ //if this is a toolbar button, set some defaults
+ attrs.class = 'btn-xs btn-primary';
+ attrs.iconSize = 'fa-lg';
+ }
- var btnOptions = _.clone(scope.options);
- btnOptions.ngClick = "onSelected({ action: action })";
+ element.addClass('btn');
- // These should be taken care of by
- // using ng-show & ng-hide on this
- // directive
- delete btnOptions.ngHide;
- delete btnOptions.ngShow;
+ // If no class specified, default
+ // to btn-sm
+ if (_.isEmpty(attrs.class)) {
+ element.addClass("btn-sm");
+ } else {
+ element.addClass(attrs.class);
+ }
- // console.log('options:', scope.options);
+ if (attrs.awPopOver) {
+ element.addClass("help-link-white");
+ }
- html += Button({
- btn: btnOptions,
- action: scope.name,
- toolbar: true
- });
+ if (attrs.iconName && _.isEmpty(attrs.id)) {
+ element.attr("id",attrs.iconName + "_btn");
+ }
- element.html(html);
+ if (!_.isEmpty(attrs.img)) {
+ $("
")
+ .attr("src", $basePath + "img/" + attrs.img)
+ .css({ width: "12px", height: "12px" })
+ .appendTo(element);
+ }
+
+ if (!_.isEmpty(attrs.iconClass)) {
+ $("")
+ .addClass(attrs.iconClass)
+ .appendTo(element);
+ }
+ else {
+ var icon = SelectIcon({
+ action: attrs.iconName,
+ size: attrs.iconSize
+ });
+
+ $(icon).appendTo(element);
+ }
+
+ if (!toolbar && !_.isEmpty(attrs.label)) {
+ element.text(attrs.label);
+ }
- $compile(element.contents())(scope);
}
};
}];
diff --git a/awx/ui/static/partials/home.html b/awx/ui/static/partials/home.html
index dc70714683..421c2c2b6d 100644
--- a/awx/ui/static/partials/home.html
+++ b/awx/ui/static/partials/home.html
@@ -4,6 +4,24 @@
diff --git a/awx/ui/static/partials/portal.html b/awx/ui/static/partials/portal.html
index 604d36bacf..077eed49e3 100644
--- a/awx/ui/static/partials/portal.html
+++ b/awx/ui/static/partials/portal.html
@@ -3,6 +3,14 @@