AC-697 Dynamic help on Permissions page based on Permission Type. Uses a help collapse. Added ngBind support to help collapse, allowing the controller to set a scope variable to an html string. Added a Permissions.js helper to share setting help text and other defaults whenever permission type changes.

This commit is contained in:
Chris Houseknecht
2013-12-02 21:34:53 +00:00
parent a21a740bad
commit 2dd2fb95ac
7 changed files with 87 additions and 48 deletions

View File

@@ -53,6 +53,7 @@ angular.module('ansible', [
'ProjectsHelper', 'ProjectsHelper',
'PermissionFormDefinition', 'PermissionFormDefinition',
'PermissionListDefinition', 'PermissionListDefinition',
'PermissionsHelper',
'JobsListDefinition', 'JobsListDefinition',
'JobFormDefinition', 'JobFormDefinition',
'JobEventsListDefinition', 'JobEventsListDefinition',

View File

@@ -77,7 +77,7 @@ PermissionsList.$inject = [ '$scope', '$rootScope', '$location', '$log', '$route
function PermissionsAdd ($scope, $rootScope, $compile, $location, $log, $routeParams, PermissionsForm, function PermissionsAdd ($scope, $rootScope, $compile, $location, $log, $routeParams, PermissionsForm,
GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ClearScope, GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ClearScope,
GetBasePath, ReturnToCaller, InventoryList, ProjectList, LookUpInit, CheckAccess, GetBasePath, ReturnToCaller, InventoryList, ProjectList, LookUpInit, CheckAccess,
Wait) Wait, PermissionCategoryChange)
{ {
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
//scope. //scope.
@@ -100,7 +100,7 @@ function PermissionsAdd ($scope, $rootScope, $compile, $location, $log, $routePa
scope.category = 'Inventory'; scope.category = 'Inventory';
master.category = 'Inventory'; master.category = 'Inventory';
master.inventoryrequired = true; master.inventoryrequired = true;
master.projectrequired = false master.projectrequired = false;
LookUpInit({ LookUpInit({
scope: scope, scope: scope,
@@ -152,29 +152,27 @@ function PermissionsAdd ($scope, $rootScope, $compile, $location, $log, $routePa
for (var fld in master) { for (var fld in master) {
scope[fld] = master[fld]; scope[fld] = master[fld];
} }
scope.selectCategory();
}; };
scope.selectCategory = function() { scope.selectCategory = function() { PermissionCategoryChange({ scope: scope, reset: true }); };
if (scope.category == 'Inventory') {
scope.projectrequired = false;
} scope.selectCategory();
else {
scope.projectrequired = true;
}
scope.permission_type = null;
}
} }
PermissionsAdd.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'PermissionsForm', PermissionsAdd.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'PermissionsForm',
'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ClearScope', 'GetBasePath', 'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ClearScope', 'GetBasePath',
'ReturnToCaller', 'InventoryList', 'ProjectList', 'LookUpInit', 'CheckAccess', 'Wait' 'ReturnToCaller', 'InventoryList', 'ProjectList', 'LookUpInit', 'CheckAccess', 'Wait',
'PermissionCategoryChange'
]; ];
function PermissionsEdit ($scope, $rootScope, $compile, $location, $log, $routeParams, PermissionsForm, function PermissionsEdit ($scope, $rootScope, $compile, $location, $log, $routeParams, PermissionsForm,
GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ReturnToCaller,
ClearScope, Prompt, GetBasePath, InventoryList, ProjectList, LookUpInit, CheckAccess, ClearScope, Prompt, GetBasePath, InventoryList, ProjectList, LookUpInit, CheckAccess,
Wait) Wait, PermissionCategoryChange)
{ {
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
//scope. //scope.
@@ -191,7 +189,11 @@ function PermissionsEdit ($scope, $rootScope, $compile, $location, $log, $routeP
var master = {}; var master = {};
var relatedSets = {}; var relatedSets = {};
CheckAccess({ scope: scope }) CheckAccess({ scope: scope });
scope.selectCategory = function(resetIn) {
var reset = (resetIn == false) ? false : true;
PermissionCategoryChange({ scope: scope, reset: reset }); }
// Retrieve detail record and prepopulate the form // Retrieve detail record and prepopulate the form
Rest.setUrl(defaultUrl); Rest.setUrl(defaultUrl);
@@ -216,12 +218,9 @@ function PermissionsEdit ($scope, $rootScope, $compile, $location, $log, $routeP
scope.category = 'Deploy'; scope.category = 'Deploy';
if (data['permission_type'] != 'run' && data['permission_type'] != 'check' ) { if (data['permission_type'] != 'run' && data['permission_type'] != 'check' ) {
scope.category = 'Inventory'; scope.category = 'Inventory';
scope.projectrequired = false;
}
else {
scope.projectrequired = true;
} }
master['category'] = scope.category; master['category'] = scope.category;
scope.selectCategory(false); //call without resetting scope.category value
LookUpInit({ LookUpInit({
scope: scope, scope: scope,
@@ -287,24 +286,14 @@ function PermissionsEdit ($scope, $rootScope, $compile, $location, $log, $routeP
for (var fld in master) { for (var fld in master) {
scope[fld] = master[fld]; scope[fld] = master[fld];
} }
scope.selectCategory(false);
}; };
scope.selectCategory = function() {
if (scope.category == 'Inventory') {
scope.projectrequired = false;
}
else {
scope.projectrequired = true;
}
scope.permission_type = null;
}
} }
PermissionsEdit.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'PermissionsForm', PermissionsEdit.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'PermissionsForm',
'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller', 'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller',
'ClearScope', 'Prompt', 'GetBasePath', 'InventoryList', 'ProjectList', 'LookUpInit', 'CheckAccess', 'ClearScope', 'Prompt', 'GetBasePath', 'InventoryList', 'ProjectList', 'LookUpInit', 'CheckAccess',
'Wait' 'Wait', 'PermissionCategoryChange'
]; ];

View File

@@ -14,7 +14,8 @@ angular.module('PermissionFormDefinition', [])
addTitle: 'Add Permission', //Title in add mode addTitle: 'Add Permission', //Title in add mode
editTitle: '{{ name }}', //Title in edit mode editTitle: '{{ name }}', //Title in edit mode
name: 'permission', //entity or model name in singular form name: 'permission', //entity or model name in singular form
well: true, //Wrap the form with TB well/ well: true, //Wrap the form with TB well
forceListeners: true,
stream: { stream: {
'class': "btn-primary btn-xs activity-btn", 'class': "btn-primary btn-xs activity-btn",
@@ -83,18 +84,9 @@ angular.module('PermissionFormDefinition', [])
{label: 'Check', value: 'check', ngShow: "category == 'Deploy'" } {label: 'Check', value: 'check', ngShow: "category == 'Deploy'" }
], ],
addRequired: true, addRequired: true,
editRequired: true editRequired: true,
helpCollapse: [{ hdr: 'Permission', ngBind: 'permissionTypeHelp' }]
} }
/* ,
deployment_permission_type: {
label: 'Permission',
type: 'radio',
ngShow: "category == 'Deploy'",
options: [
{label: 'Deploy', value: 'PERM_INVENTORY_DEPLOY'},
{label: 'Check', value: 'PERM_INVENTORY_CHECK'}
]
}*/
}, },
buttons: { //for now always generates <button> tags buttons: { //for now always generates <button> tags

View File

@@ -0,0 +1,48 @@
/*********************************************
* Copyright (c) 2013 AnsibleWorks, Inc.
*
* Permissions.js
*
* Functions shared amongst Permission related controllers
*
*/
angular.module('PermissionsHelper', [])
// Handle category change event
.factory('PermissionCategoryChange', [ function() {
return function(params) {
var scope = params.scope;
var reset = params.reset;
if (scope.category == 'Inventory') {
scope.projectrequired = false;
scope.permissionTypeHelp =
"<dl>\n" +
"<dt>Admin</dt>\n" +
"<dd>Allow the user or team full access to the inventory. This includes reading, writing, deletion of the inventory and inventory sync operations.</dd>\n" +
"<dt>Read</dt>\n" +
"<dd>Only allow the user or team to view the inventory.</dd>\n" +
"<dt>Write</dt>\n" +
"<dd>Allow the user or team to modify hosts and groups contained in the inventory, add new hosts and groups, and perform inventory sync operations.\n" +
"</dl>\n";
}
else {
scope.projectrequired = true;
scope.permissionTypeHelp =
"<dl>\n" +
"<dt>Run</dt>\n" +
"<dd>Allow the user or team to perform a live deployment of the project against the inventory. In Run mode modules will " +
"be executed, and changes to the inventory will occur.</dd>\n" +
"<dt>Check</dt>\n" +
"<dd>Only allow the user or team to deploy the project against the inventory as a dry-run operation. In Check mode, module operations " +
"will only be simulated. No changes will occur.</dd>\n" +
"</dl>\n";
}
if (reset) {
scope.permission_type = null;
}
}
}]);

View File

@@ -347,6 +347,7 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies', 'Utilities'])
params.content = collapse_array[i].content; params.content = collapse_array[i].content;
params.idx = this.accordion_count++; params.idx = this.accordion_count++;
params.show = (collapse_array[i].show) ? collapse_array[i].show : null; params.show = (collapse_array[i].show) ? collapse_array[i].show : null;
params.bind = (collapse_array[i].ngBind) ? collapse_array[i].ngBind : null;
html += HelpCollapse(params); html += HelpCollapse(params);
} }
return html; return html;
@@ -839,6 +840,10 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies', 'Utilities'])
this.form.name + '_form.' + fld + ".$error.required\">A value is required!</div>\n"; this.form.name + '_form.' + fld + ".$error.required\">A value is required!</div>\n";
} }
html += "<div class=\"error api-error\" ng-bind=\"" + fld + "_api_error\"></div>\n"; html += "<div class=\"error api-error\" ng-bind=\"" + fld + "_api_error\"></div>\n";
// Add help panel(s)
html += (field.helpCollapse) ? this.buildHelpCollapse(field.helpCollapse) : '';
html += "</div>\n"; html += "</div>\n";
} }

View File

@@ -453,6 +453,7 @@ angular.module('GeneratorHelpers', ['GeneratorHelpers'])
var content = params.content; var content = params.content;
var show = params.show; var show = params.show;
var idx = params.idx; var idx = params.idx;
var bind = params.bind; //Pass in scope variable containing html
var html = ''; var html = '';
html += "<div class=\"panel-group collapsible-help\" "; html += "<div class=\"panel-group collapsible-help\" ";
html += (show) ? "ng-show=\"" + show + "\"" : ""; html += (show) ? "ng-show=\"" + show + "\"" : "";
@@ -465,8 +466,10 @@ angular.module('GeneratorHelpers', ['GeneratorHelpers'])
html += "</h4>\n"; html += "</h4>\n";
html += "</div>\n"; html += "</div>\n";
html += "<div id=\"accordion" + idx + "\" class=\"panel-collapse collapse in\">\n"; html += "<div id=\"accordion" + idx + "\" class=\"panel-collapse collapse in\">\n";
html += "<div class=\"panel-body\">\n"; html += "<div class=\"panel-body\" ";
html += content; html += (bind) ? "ng-bind-html-unsafe=\"" + bind + "\" " : "";
html += ">\n";
html += (!bind) ? content : "";
html += "</div>\n"; html += "</div>\n";
html += "</div>\n"; html += "</div>\n";
html += "</div>\n"; html += "</div>\n";

View File

@@ -121,6 +121,7 @@
<script src="{{ STATIC_URL }}js/helpers/Users.js"></script> <script src="{{ STATIC_URL }}js/helpers/Users.js"></script>
<script src="{{ STATIC_URL }}js/helpers/Jobs.js"></script> <script src="{{ STATIC_URL }}js/helpers/Jobs.js"></script>
<script src="{{ STATIC_URL }}js/helpers/Credentials.js"></script> <script src="{{ STATIC_URL }}js/helpers/Credentials.js"></script>
<script src="{{ STATIC_URL }}js/helpers/Permissions.js"></script>
<script src="{{ STATIC_URL }}js/widgets/JobStatus.js"></script> <script src="{{ STATIC_URL }}js/widgets/JobStatus.js"></script>
<script src="{{ STATIC_URL }}js/widgets/InventorySyncStatus.js"></script> <script src="{{ STATIC_URL }}js/widgets/InventorySyncStatus.js"></script>
<script src="{{ STATIC_URL }}js/widgets/SCMSyncStatus.js"></script> <script src="{{ STATIC_URL }}js/widgets/SCMSyncStatus.js"></script>