Documentation for specifying Template as URL

There's limited documentation in the actions directive
when specifying custom templates for action buttons.

The patch adds documentation, fixes existing tests to
exercise and verify the behavior when using custom
templates.

Change-Id: I8e18ade260c7f23defc192af51545685ccbbbe2b
Partially-Implements: blueprint angularize-images-table
This commit is contained in:
Rajat Vig 2015-12-21 09:37:16 -08:00
parent e1e48c18a4
commit 39a7452930
6 changed files with 83 additions and 35 deletions

View File

@ -1,3 +0,0 @@
<action action-classes="'btn btn-default btn-sm btn-create'">
<span class="fa fa-user-plus">Create Image</span>
</action>

View File

@ -1,3 +0,0 @@
<action action-classes="'text-danger'" item="image">
<span class="fa fa-trash-o text-danger" translate>Delete Image</span>
</action>

View File

@ -0,0 +1 @@
<action action-classes="'btn-custom'" item="customItem">Custom Button</action>

View File

@ -0,0 +1 @@
<action action-classes="'btn-custom-2'">Custom Button 2</action>

View File

@ -53,25 +53,36 @@
* service: <service to use - described below>
* }
*
* template: is an object that can be any of
* template: the Template used for the Action Button.
* It is an object that can be any of
* 1. url: <full_path_to_template.html>
* This specifies the location of the template for the action button.
* Use this for complete extensibility and control over what is rendered.
* The template will be responsible for binding the callback and styling the button.
* This allows for specification of the template for the action button.
* Use this option for complete extensibility and control over what is rendered.
* The directive will be responsible for binding the callback but not for styling the button.
* The template should include the 'item' attribute for the 'action' button,
* if the action needs an item to act upon even for 'row' type. Specifying an 'item' other
* than the current row 'item' is supported'.
*
* The 'scope' in use for the 'actions' directive can be used in the custom template.
*
* Refer to tests that exercise this functionality with some sample templates at
* - 'actions.custom.mock.html' and 'actions.custom.mock2.html'.
*
* 2. type: '<action_button_type>'
* This uses a known action button type.
* This creates an action button based off a 'known' button type.
* Currently supported values are
* 1. 'delete' - Delete a single row. Only for 'row' type.
* 2. 'danger' - For marking an Action as dangerous. Only for 'row' type.
* 3. 'delete-selected' - Delete multiple rows. Only for 'batch' type.
* 4. 'create' - Create a new entity. Only for 'batch' type.
*
* The styling and binding of the callback is done by the template.
* The styling of the action button is done based on the 'listType'.
* The directive will be responsible for binding the correct callback.
*
* 3. text: 'text', actionClasses: 'custom-classes'
* This creates a button with the given text.
* This creates an unstyled button with the given text.
* For custom styling of the button, `actionClasses` can be optionally included.
* The directive will be responsible for binding the correct callback.
*
* service: is the service expected to have two functions
* 1. allowed: is expected to return a promise that resolves

View File

@ -17,7 +17,8 @@
describe('actions directive', function () {
var $scope, $compile, $q, $templateCache, basePath;
var rowItem = {id: 1};
var rowItem = {id: 'row'};
var customItem = {id: 'custom'};
var callback = jasmine.createSpy('callback');
beforeEach(module('templates'));
@ -36,6 +37,44 @@
expect(element.children().length).toBe(0);
});
it('should allow for specifying by url for batch', function () {
$scope.customItem = customItem;
var element = batchElementFor([permittedActionWithUrl('custom')]);
expect(element.children().length).toBe(1);
var actionList = element.find('action-list');
expect(actionList.length).toBe(1);
expect(actionList.attr('class').indexOf('btn-addon')).toBeGreaterThan(-1);
expect(actionList.find('button').attr('class')).toEqual('btn-custom');
expect(actionList.find('button').attr('ng-click')).toEqual('disabled || callback(item)');
expect(actionList.text().trim()).toEqual('Custom Button');
actionList.find('button').click();
expect(callback).toHaveBeenCalledWith(customItem);
});
it('should allow for specifying by url for row', function () {
$scope.customItem = customItem;
var element = rowElementFor([
permittedActionWithUrl('custom2'),
permittedActionWithUrl('custom')
]);
expect(element.children().length).toBe(1);
var actionList = element.find('action-list');
expect(actionList.length).toBe(1);
expect(actionList.attr('class').indexOf('btn-addon')).toEqual(-1);
expect(actionList.find('button.btn-custom-2.split-button').text().trim())
.toEqual('Custom Button 2');
expect(actionList.find('li .btn-custom').text().trim()).toEqual('Custom Button');
actionList.find('button.btn-custom-2.split-button').click();
expect(callback).toHaveBeenCalledWith(undefined);
actionList.find('li .btn-custom').click();
expect(callback).toHaveBeenCalledWith(customItem);
});
it('should allow for specifying action text', function () {
var element = batchElementFor([permittedActionWithText('Create Image')]);
@ -109,14 +148,16 @@
});
it('should have one button if there is one action', function () {
var action = getTemplatePath('action-create', getTemplate());
var element = batchElementFor([permittedActionWithUrl(action)]);
var element = batchElementFor([
permittedActionWithType('create', 'Create Image')
]);
expect(element.children().length).toBe(1);
var actionList = element.find('action-list');
expect(actionList.length).toBe(1);
expect(actionList.attr('class').indexOf('btn-addon')).toBeGreaterThan(-1);
expect(actionList.find('button').attr('class')).toEqual('btn btn-default btn-sm btn-create');
expect(actionList.find('button').attr('class'))
.toEqual('btn btn-default btn-sm pull-right');
expect(actionList.find('button').attr('ng-click')).toEqual('disabled || callback(item)');
expect(actionList.text().trim()).toEqual('Create Image');
});
@ -128,19 +169,18 @@
});
it('should have multiple buttons for multiple actions as a list', function () {
var action1 = getTemplatePath('action-create');
var action2 = getTemplatePath('action-delete');
var element = batchElementFor([
permittedActionWithUrl(action1),
permittedActionWithUrl(action2)
permittedActionWithType('create', 'Create Image'),
permittedActionWithType('delete-selected', 'Delete Images')
]);
expect(element.children().length).toBe(2);
var actionList = element.find('action-list');
expect(actionList.length).toBe(2);
expect(actionList.attr('class').indexOf('btn-addon')).toBeGreaterThan(-1);
expect(actionList.find('button.btn-create').text().trim()).toEqual('Create Image');
expect(actionList.find('button.text-danger').text().trim()).toEqual('Delete Image');
expect(actionList.find('button.btn-default .fa-user-plus').text().trim())
.toEqual('Create Image');
expect(actionList.find('button.btn-danger').text().trim()).toEqual('Delete Images');
});
it('should bind multiple callbacks for multiple buttons in a batch', function () {
@ -163,9 +203,8 @@
});
it('should have as many buttons as permitted', function () {
var actionTemplate1 = getTemplatePath('action-create');
var element = batchElementFor([
permittedActionWithUrl(actionTemplate1),
permittedActionWithType('create', 'Create Image'),
notPermittedAction()
]);
@ -254,9 +293,11 @@
.toEqual('btn btn-sm pull-right btn-default btn-custom');
});
function permittedActionWithUrl(templateUrl) {
function permittedActionWithUrl(templateName) {
return {
template: {url: templateUrl},
template: {
url: getTemplatePath("actions." + templateName)
},
service: getService(getPermission(true), callback)
};
}
@ -302,14 +343,6 @@
};
}
function getTemplate(templateName) {
return $templateCache.get(getTemplatePath(templateName));
}
function getTemplatePath(templateName) {
return basePath + 'action-list/' + templateName + '.mock.html';
}
function getPermission(allowed) {
var deferred = $q.defer();
@ -349,5 +382,13 @@
return element;
}
function getTemplate(templateName) {
return $templateCache.get(getTemplatePath(templateName));
}
function getTemplatePath(templateName) {
return basePath + 'action-list/' + templateName + '.mock.html';
}
});
})();