Merge pull request #6836 from mabashian/6656-multiselect-preview

Added multi-select preview to group/host associate and instance groups modals
This commit is contained in:
Michael Abashian 2017-06-30 16:48:01 -04:00 committed by GitHub
commit 8c834daf46
15 changed files with 198 additions and 13 deletions

View File

@ -13,7 +13,7 @@ export default {
controller: function($scope, $q, GroupsService, $state){
$scope.associateGroups = function(selectedItems){
var deferred = $q.defer();
return $q.all( _.map(selectedItems, (id) => GroupsService.associateHost({id: parseInt($state.params.host_id)}, id)) )
return $q.all( _.map(selectedItems, (selectedItem) => GroupsService.associateHost({id: parseInt($state.params.host_id)}, selectedItem.id)) )
.then( () =>{
deferred.resolve();
}, (error) => {

View File

@ -13,7 +13,7 @@ export default {
controller: function($scope, $q, GroupsService, $state){
$scope.associateGroups = function(selectedItems){
var deferred = $q.defer();
return $q.all( _.map(selectedItems, (id) => GroupsService.associateGroup({id: id}, $state.params.group_id)) )
return $q.all( _.map(selectedItems, (selectedItem) => GroupsService.associateGroup({id: selectedItem.id}, $state.params.group_id)) )
.then( () =>{
deferred.resolve();
}, (error) => {

View File

@ -13,7 +13,7 @@ export default {
controller: function($scope, $q, GroupsService, $state){
$scope.associateHosts = function(selectedItems){
var deferred = $q.defer();
return $q.all( _.map(selectedItems, (id) => GroupsService.associateHost({id: id}, $state.params.group_id)) )
return $q.all( _.map(selectedItems, (selectedItem) => GroupsService.associateHost({id: selectedItem.id}, $state.params.group_id)) )
.then( () =>{
deferred.resolve();
}, (error) => {

View File

@ -13,7 +13,7 @@ export default {
controller: function($scope, $q, GroupsService, $state){
$scope.associateGroups = function(selectedItems){
var deferred = $q.defer();
return $q.all( _.map(selectedItems, (id) => GroupsService.associateHost({id: parseInt($state.params.host_id)}, id)) )
return $q.all( _.map(selectedItems, (selectedItem) => GroupsService.associateHost({id: parseInt($state.params.host_id)}, selectedItem.id)) )
.then( () =>{
deferred.resolve();
}, (error) => {

View File

@ -35,6 +35,10 @@
list.multiSelect = true;
list.fields.name.ngClick = 'linkoutGroup(associate_group.id)';
list.trackBy = 'associate_group.id';
list.multiSelectPreview = {
selectedRows: 'selectedItems',
availableRows: 'associate_groups'
};
delete list.actions;
delete list.fieldActions;
delete list.fields.failed_hosts;
@ -58,9 +62,11 @@
$scope.$watchCollection('associate_groups', function () {
if($scope.selectedItems) {
$scope.associate_groups.forEach(function(row, i) {
if (_.includes($scope.selectedItems, row.id)) {
$scope.associate_groups[i].isSelected = true;
}
$scope.selectedItems.forEach(function(selectedItem) {
if(selectedItem.id === row.id) {
$scope.associate_groups[i].isSelected = true;
}
});
});
}
});
@ -72,14 +78,14 @@
let item = value.value;
if (value.isSelected) {
$scope.selectedItems.push(item.id);
$scope.selectedItems.push(item);
}
else {
// _.remove() Returns the new array of removed elements.
// This will pull all the values out of the array that don't
// match the deselected item effectively removing it
$scope.selectedItems = _.remove($scope.selectedItems, function(selectedItem) {
return selectedItem !== item.id;
return selectedItem.id !== item.id;
});
}
});

View File

@ -3,7 +3,7 @@
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header Form-header">
<div class="Form-title Form-title--uppercase">SELECT GROUP</div>
<div class="Form-title Form-title--uppercase">SELECT GROUPS</div>
<div class="Form-header--fields"></div>
<div class="Form-exitHolder">
<button type="button" class="Form-exit" ng-click="closeModal()">

View File

@ -3,7 +3,7 @@
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header Form-header">
<div class="Form-title Form-title--uppercase">SELECT HOST</div>
<div class="Form-title Form-title--uppercase">SELECT HOSTS</div>
<div class="Form-header--fields"></div>
<div class="Form-exitHolder">
<button type="button" class="Form-exit" ng-click="closeModal()">

View File

@ -46,7 +46,10 @@ export default ['templateUrl', function(templateUrl) {
instanceGroupList.listTitle = false;
instanceGroupList.well = false;
instanceGroupList.multiSelect = true;
instanceGroupList.multiSelectExtended = true;
instanceGroupList.multiSelectPreview = {
selectedRows: 'igTags',
availableRows: 'instance_groups'
};
delete instanceGroupList.fields.percent_capacity_remaining;
delete instanceGroupList.fields.jobs_running;
@ -104,4 +107,4 @@ export default ['templateUrl', function(templateUrl) {
};
}]
};
}];
}];

View File

@ -163,6 +163,10 @@ export default ['$compile', 'Attr', 'Icon',
html += "</div>\n";
}
if (list.multiSelectPreview) {
html += "<multi-select-preview selected-rows='" + list.multiSelectPreview.selectedRows + "' available-rows='" + list.multiSelectPreview.availableRows + "'></multi-select-preview>";
}
if (options.instructions) {
html += "<div class=\"instructions alert alert-info\">" + options.instructions + "</div>\n";
} else if (list.instructions) {

View File

@ -32,6 +32,7 @@ import directives from './directives';
import features from './features/main';
import orgAdminLookup from './org-admin-lookup/main';
import limitPanels from './limit-panels/main';
import multiSelectPreview from './multi-select-preview/main';
import 'angular-duration-format';
export default
@ -61,6 +62,7 @@ angular.module('shared', [listGenerator.name,
features.name,
orgAdminLookup.name,
limitPanels.name,
multiSelectPreview.name,
require('angular-cookies'),
'angular-duration-format'
])

View File

@ -0,0 +1,11 @@
/*************************************************
* Copyright (c) 2017 Ansible, Inc.
*
* All Rights Reserved
*************************************************/
import multiSelectPreview from './multi-select-preview.directive';
export default
angular.module('multiSelectPreview', [])
.directive('multiSelectPreview', multiSelectPreview);

View File

@ -0,0 +1,99 @@
@import '../branding/colors.default.less';
.MultiSelectPreview {
display: flex;
flex: 1 0 auto;
margin-bottom: 15px;
align-items: baseline;
}
.MultiSelectPreview-selectedItems {
display: flex;
flex: 0 0 100%;
background-color: @default-no-items-bord;
border: 1px solid @default-border;
padding: 10px;
border-radius: 5px;
}
.MultiSelectPreview-selectedItemsLabel, .MultiSelectPreview-label {
color: @default-interface-txt;
margin-right: 10px;
}
.MultiSelectPreview-selectedItemsLabel {
flex: 0 0 80px;
line-height: 29px;
}
.MultiSelectPreview-previewTags--outer {
flex: 1 0 auto;
max-width: ~"calc(100% - 140px)";
}
.MultiSelectPreview-previewTags--inner {
display: flex;
flex-wrap: wrap;
align-items: flex-start;
}
.MultiSelectPreview-previewTagContainer {
display: flex;
}
.MultiSelectPreview-previewTagRevert {
flex: 0 0 60px;
line-height: 29px;
}
.MultiSelectPreview-revertLink {
font-size: 12px;
}
.MultiSelectPreview-previewTagContainerDelete {
background-color: @default-link;
border-top-left-radius: 5px;
border-bottom-left-radius: 5px;
color: @default-bg;
padding: 0 5px;
margin: 4px 0px;
align-items: center;
display: flex;
cursor: pointer;
}
.MultiSelectPreview-previewTagContainerDelete:hover {
border-color: @default-err;
background-color: @default-err;
}
.MultiSelectPreview-previewTagContainerDelete:hover > .MultiSelectPreview-previewTagContainerTagDelete {
color: @default-bg;
}
.MultiSelectPreview-previewTag {
border-radius: 5px;
padding: 2px 10px;
margin: 4px 0px;
font-size: 12px;
color: @default-interface-txt;
background-color: @default-list-header-bg;
margin-right: 5px;
max-width: 100%;
display: inline-block;
}
.MultiSelectPreview-previewTagLabel {
color: @default-list-header-bg;
}
.MultiSelectPreview-previewTag--deletable {
color: @default-bg;
background-color: @default-link;
margin-right: 0px;
border-top-left-radius: 0px;
border-bottom-left-radius: 0px;
border-right: 0;
max-width: ~"calc(100% - 23px)";
margin-right: 5px;
}

View File

@ -0,0 +1,21 @@
/*************************************************
* Copyright (c) 2017 Ansible, Inc.
*
* All Rights Reserved
*************************************************/
export default ['$scope',
function ($scope) {
$scope.unselectSelectedRow = function(index) {
angular.forEach($scope.availableRows, function(value) {
if(value.id === $scope.selectedRows[index].id) {
value.isSelected = false;
}
});
$scope.selectedRows.splice(index, 1);
};
}
];

View File

@ -0,0 +1,20 @@
/*************************************************
* Copyright (c) 2017 Ansible, Inc.
*
* All Rights Reserved
*************************************************/
import MultiSelectPreviewController from './multi-select-preview.controller';
export default ['templateUrl', function(templateUrl) {
return {
restrict: 'E',
replace: true,
scope: {
selectedRows: '=',
availableRows: '='
},
controller: MultiSelectPreviewController,
templateUrl: templateUrl('shared/multi-select-preview/multi-select-preview')
};
}];

View File

@ -0,0 +1,19 @@
<div class="MultiSelectPreview" ng-show="selectedRows.length > 0">
<div class="MultiSelectPreview-selectedItems">
<div class="MultiSelectPreview-selectedItemsLabel">
<span>SELECTED:</span>
</div>
<div class="MultiSelectPreview-previewTags--outer">
<div class="MultiSelectPreview-previewTags--inner">
<div class="MultiSelectPreview-previewTagContainer" ng-repeat="selectedRow in selectedRows">
<div class="MultiSelectPreview-previewTagContainerDelete" ng-click="unselectSelectedRow($index)">
<i class="fa fa-times MultiSelectPreview-previewTagContainerTagDelete"></i>
</div>
<div class="MultiSelectPreview-previewTag MultiSelectPreview-previewTag--deletable">
<span>{{selectedRow.name}}</span>
</div>
</div>
</div>
</div>
</div>
</div>