[Launch Instance Fix] Magic Search in new Launch Instance

Currently implemented in the "Select Source", Network and
"Select Flavor" step in the Launch Instane workflow.

Co-Authored-By: Rajat Vig<rajatv@thoughtworks.com>

Change-Id: I5e195bfcf7fe3367576089b23cc08b40c2c36b09
Partial-Bug: #1434710
This commit is contained in:
Rajat Vig 2015-09-02 09:16:30 -07:00 committed by Matt Borland
parent de3ae40fb5
commit 5ee8de73e2
8 changed files with 260 additions and 10 deletions

View File

@ -115,6 +115,38 @@
}
scope.chartSettings = donutChartSettings;
/**
* Filtering - client-side MagicSearch
*/
// All facets for flavor step
scope.flavorFacets = [
{
label: gettext('Name'),
name: 'name',
singleton: true
},
{
label: gettext('VCPUs'),
name: 'vcpus',
singleton: true
},
{
label: gettext('RAM'),
name: 'ram',
singleton: true
},
{
label: gettext('Public'),
name: 'isPublic',
singleton: true,
options: [
{ label: gettext('No'), key: false },
{ label: gettext('Yes'), key: true }
]
}
];
} // end of link
} // end of function

View File

@ -18,8 +18,8 @@ limitations under the License.
<thead>
<tr ng-show="showSearchBar">
<th class="search-header" colspan="9">
<hz-search-bar group-classes="input-group-sm" icon-classes="fa-search">
</hz-search-bar>
<hz-magic-search-bar filter-facets="flavorFacets">
</hz-magic-search-bar>
</th>
</tr>
<tr>

View File

@ -61,5 +61,46 @@
};
ctrl.tooltipModel = tooltipService;
/**
* Filtering - client-side MagicSearch
*/
// All facets for network step
ctrl.networkFacets = [
{
label: gettext('Name'),
name: 'name',
singleton: true
},
{
label: gettext('Shared'),
name: 'shared',
singleton: true,
options: [
{ label: gettext('No'), key: false },
{ label: gettext('Yes'), key: true }
]
},
{
label: gettext('Admin State'),
name: 'admin_state',
singleton: true,
options: [
{ label: gettext('Up'), key: "UP" },
{ label: gettext('Down'), key: "DOWN" }
]
},
{
label: gettext('Status'),
name: 'status',
singleton: true,
options: [
{ label: gettext('Active'), key: "ACTIVE"},
{ label: gettext('Down'), key: "DOWN" }
]
}
];
}
})();

View File

@ -71,6 +71,13 @@
expect(ctrl.tableDataMulti.displayedAllocated).toEqual([]);
expect(ctrl.tableDataMulti.displayedAvailable).toEqual([]);
});
it('should set facets for search', function() {
expect(ctrl.networkFacets).toBeDefined();
expect(ctrl.networkFacets.length).toEqual(4);
expect(ctrl.networkFacets[0].name).toEqual('name');
expect(ctrl.networkFacets[1].name).toEqual('shared');
});
});
});

View File

@ -100,8 +100,8 @@
<thead>
<tr>
<th class="search-header" colspan="8">
<hz-search-bar group-classes="input-group-sm" icon-classes="fa-search">
</hz-search-bar>
<hz-magic-search-bar filter-facets="ctrl.networkFacets">
</hz-magic-search-bar>
</th>
</tr>
<tr>

View File

@ -115,6 +115,20 @@
}
};
var diskFormats = [
{ label: gettext('AKI'), key: 'aki' },
{ label: gettext('AMI'), key: 'ami' },
{ label: gettext('ARI'), key: 'ari' },
{ label: gettext('Docker'), key: 'docker' },
{ label: gettext('ISO'), key: 'iso' },
{ label: gettext('OVA'), key: 'ova' },
{ label: gettext('QCOW2'), key: 'qcow2' },
{ label: gettext('RAW'), key: 'raw' },
{ label: gettext('VDI'), key: 'vdi' },
{ label: gettext('VHD'), key: 'vhd' },
{ label: gettext('VMDK'), key: 'vmdk' }
];
// Mapping for dynamic table headers
var tableHeadCellsMap = {
image: [
@ -187,6 +201,98 @@
]
};
/**
* Filtering - client-side MagicSearch
*/
ctrl.sourceFacets = [];
// All facets for source step
var facets = {
created: {
label: gettext('Created'),
name: 'created_at',
singleton: true
},
description: {
label: gettext('Description'),
name: 'description',
singleton: true
},
encrypted: {
label: gettext('Encrypted'),
name: 'encrypted',
singleton: true,
options: [
{ label: gettext('Yes'), key: 'true' },
{ label: gettext('No'), key: 'false' }
]
},
name: {
label: gettext('Name'),
name: 'name',
singleton: true
},
size: {
label: gettext('Size'),
name: 'size',
singleton: true
},
status: {
label: gettext('Status'),
name: 'status',
singleton: true,
options: [
{ label: gettext('Available'), key: 'available' },
{ label: gettext('Creating'), key: 'creating' },
{ label: gettext('Deleting'), key: 'deleting' },
{ label: gettext('Error'), key: 'error' },
{ label: gettext('Error Deleting'), key: 'error_deleting' }
]
},
type: {
label: gettext('Type'),
name: 'disk_format',
singleton: true,
options: diskFormats
},
updated: {
label: gettext('Updated'),
name: 'updated_at',
singleton: true
},
visibility: {
label: gettext('Visibility'),
name: 'is_public',
singleton: true,
options: [
{ label: gettext('Public'), key: 'true' },
{ label: gettext('Private'), key: 'false' }
]
},
volumeType: {
label: gettext('Type'),
name: 'volume_image_metadata.disk_format',
singleton: true,
options: diskFormats
}
};
// Mapping for filter facets based on boot source type
var sourceTypeFacets = {
image: [
facets.name, facets.updated, facets.size, facets.type, facets.visibility
],
snapshot: [
facets.name, facets.updated, facets.size, facets.type, facets.visibility
],
volume: [
facets.name, facets.description, facets.size, facets.volumeType, facets.encrypted
],
volume_snapshot: [
facets.name, facets.description, facets.size, facets.created, facets.status
]
};
var newSpecWatcher = $scope.$watch(
function () {
return $scope.model.newInstanceSpec.instance_count;
@ -253,6 +359,7 @@
updateHelpText(key);
updateTableHeadCells(key);
updateTableBodyCells(key);
updateFacets(key);
}
function updateDataSource(key, preSelection) {
@ -281,6 +388,11 @@
refillArray(ctrl.tableBodyCells, tableBodyCellsMap[key]);
}
function updateFacets(key) {
refillArray(ctrl.sourceFacets, sourceTypeFacets[key]);
$scope.$broadcast('facetsChanged');
}
function refillArray(arrayToRefill, contentArray) {
arrayToRefill.length = 0;
Array.prototype.push.apply(arrayToRefill, contentArray);

View File

@ -125,6 +125,65 @@
expect(ctrl.currentBootSource).toBe('image');
});
describe('facets', function() {
it('should set facets for search by default', function() {
expect(ctrl.sourceFacets).toBeDefined();
expect(ctrl.sourceFacets.length).toEqual(5);
expect(ctrl.sourceFacets[0].name).toEqual('name');
expect(ctrl.sourceFacets[1].name).toEqual('updated_at');
expect(ctrl.sourceFacets[2].name).toEqual('size');
expect(ctrl.sourceFacets[3].name).toEqual('disk_format');
expect(ctrl.sourceFacets[4].name).toEqual('is_public');
});
it('should broadcast event when source type is changed', function() {
spyOn(scope, '$broadcast').and.callThrough();
ctrl.updateBootSourceSelection('volume');
ctrl.updateBootSourceSelection('snapshot');
expect(scope.$broadcast).toHaveBeenCalledWith('facetsChanged');
});
it('should change facets for snapshot source type', function() {
expect(ctrl.sourceFacets).toBeDefined();
ctrl.updateBootSourceSelection('snapshot');
expect(ctrl.sourceFacets.length).toEqual(5);
expect(ctrl.sourceFacets[0].name).toEqual('name');
expect(ctrl.sourceFacets[1].name).toEqual('updated_at');
expect(ctrl.sourceFacets[2].name).toEqual('size');
expect(ctrl.sourceFacets[3].name).toEqual('disk_format');
expect(ctrl.sourceFacets[4].name).toEqual('is_public');
});
it('should change facets for volume source type', function() {
expect(ctrl.sourceFacets).toBeDefined();
ctrl.updateBootSourceSelection('volume');
expect(ctrl.sourceFacets.length).toEqual(5);
expect(ctrl.sourceFacets[0].name).toEqual('name');
expect(ctrl.sourceFacets[1].name).toEqual('description');
expect(ctrl.sourceFacets[2].name).toEqual('size');
expect(ctrl.sourceFacets[3].name).toEqual('volume_image_metadata.disk_format');
expect(ctrl.sourceFacets[4].name).toEqual('encrypted');
});
it('should change facets for volume_snapshot source type', function() {
expect(ctrl.sourceFacets).toBeDefined();
ctrl.updateBootSourceSelection('volume_snapshot');
expect(ctrl.sourceFacets.length).toEqual(5);
expect(ctrl.sourceFacets[0].name).toEqual('name');
expect(ctrl.sourceFacets[1].name).toEqual('description');
expect(ctrl.sourceFacets[2].name).toEqual('size');
expect(ctrl.sourceFacets[3].name).toEqual('created_at');
expect(ctrl.sourceFacets[4].name).toEqual('status');
});
});
describe('Scope Functions', function() {
describe('updateBootSourceSelection', function() {

View File

@ -220,12 +220,11 @@
<!-- transfer table, available table head -->
<thead>
<tr>
<th class="search-header"
colspan="{$ ctrl.tableHeadCells.length + 2 $}">
<hz-search-bar group-classes="input-group-sm"
icon-classes="fa-search">
</hz-search-bar>
<tr>
<th class="search-header"
colspan="{$ ctrl.tableHeadCells.length + 2 $}">
<hz-magic-search-bar filter-facets="ctrl.sourceFacets">
</hz-magic-search-bar>
</th>
</tr>
<tr>