Add Multiselect checklist modal to Instance Group Fields

Update Issue: #5849
This commit is contained in:
Marliana Lara 2017-06-12 16:01:40 -04:00
parent 23b5f26a83
commit 8c756c49b2
19 changed files with 260 additions and 177 deletions

View File

@ -0,0 +1,106 @@
export default ['templateUrl', function(templateUrl) {
return {
restrict: 'E',
scope: {
instanceGroups: '='
},
templateUrl: templateUrl('instance-groups/instance-groups-multiselect/instance-groups-modal/instance-groups-modal'),
link: function(scope, element) {
$('#instance-groups-modal').on('hidden.bs.modal', function () {
$('#instance-groups-modal').off('hidden.bs.modal');
$(element).remove();
});
scope.showModal = function() {
$('#instance-groups-modal').modal('show');
};
scope.destroyModal = function() {
$('#instance-groups-modal').modal('hide');
};
},
controller: ['$scope', '$compile', 'QuerySet', 'GetBasePath','generateList', 'InstanceGroupList', function($scope, $compile, qs, GetBasePath, GenerateList, InstanceGroupList) {
function init() {
$scope.instance_group_queryset = {
order_by: 'name',
page_size: 5
};
$scope.instance_group_default_params = {
order_by: 'name',
page_size: 5
};
qs.search(GetBasePath('instance_groups'), $scope.instance_groups_queryset)
.then(res => {
$scope.instance_group_dataset = res.data;
$scope.instance_groups = $scope.instance_group_dataset.results;
let instanceGroupList = _.cloneDeep(InstanceGroupList);
instanceGroupList.listTitle = false;
instanceGroupList.well = false;
instanceGroupList.multiSelect = true;
instanceGroupList.multiSelectExtended = true;
delete instanceGroupList.fields.capacity;
delete instanceGroupList.fields.jobs_running;
let html = `${GenerateList.build({
list: instanceGroupList,
input_type: 'instance-groups-modal-body'
})}`;
$scope.list = instanceGroupList;
$('#instance-groups-modal-body').append($compile(html)($scope));
if ($scope.instanceGroups) {
$scope.instance_groups.map( (item) => {
isSelected(item);
});
}
$scope.showModal();
});
}
init();
function isSelected(item) {
if(_.find($scope.instanceGroups, {id: item.id})){
item.isSelected = true;
if (!$scope.igTags) {
$scope.igTags = [];
}
$scope.igTags.push(item);
}
return item;
}
$scope.$on("selectedOrDeselected", function(e, value) {
let item = value.value;
if (value.isSelected) {
if(!$scope.igTags) {
$scope.igTags = [];
}
$scope.igTags.push(item);
} else {
_.remove($scope.igTags, { id: item.id });
}
});
$scope.cancelForm = function() {
$scope.destroyModal();
};
$scope.saveForm = function() {
$scope.instanceGroups = $scope.igTags;
$scope.destroyModal();
};
}]
};
}];

View File

@ -0,0 +1,24 @@
<div id="instance-groups-modal" class="Lookup modal fade">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header Form-header">
<div class="Form-title Form-title--uppercase">INSTANCE GROUPS</div>
<!-- optional: transclude header fields -->
<div class="Form-header--fields"></div>
<div class="Form-exitHolder">
<button type="button" class="Form-exit" ng-click="cancelForm()">
<i class="fa fa-times-circle"></i>
</button>
</div>
</div>
<div class="modal-body">
<div id="instance-groups-modal-body"> {{ instance_group }} </div>
</div>
<div class="modal-footer">
<button type="button" ng-click="cancelForm()" class="Lookup-cancel btn btn-default">CANCEL</button>
<button type="button" ng-click="saveForm()" ng-disabled="!instance_groups || instance_groups.length === 0" class="Lookup-save btn btn-primary">SAVE</button>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,10 @@
export default ['$scope',
function($scope) {
$scope.instanceGroupsTags = [];
$scope.$watch('instanceGroups', function() {
$scope.instanceGroupsTags = _.map($scope.instanceGroups, (item) => item.name);
}, true);
}
];

View File

@ -0,0 +1,18 @@
import instanceGroupsMultiselectController from './instance-groups-multiselect.controller';
export default ['templateUrl', '$compile',
function(templateUrl, $compile) {
return {
scope: {
instanceGroups: '='
},
restrict: 'E',
templateUrl: templateUrl('instance-groups/instance-groups-multiselect/instance-groups'),
controller: instanceGroupsMultiselectController,
link: function(scope) {
scope.openInstanceGroupsModal = function() {
$('#content-container').append($compile('<instance-groups-modal instance-groups="instanceGroups"></instance-groups-modal>')(scope));
};
}
};
}
];

View File

@ -0,0 +1,12 @@
<div class="input-group Form-mixedInputGroup">
<span class="input-group-btn Form-variableHeightButtonGroup">
<button type="button" class="Form-lookupButton Form-lookupButton--variableHeight btn btn-default" ng-click="openInstanceGroupsModal()">
<i class="fa fa-search"></i>
</button>
</span>
<span class="form-control Form-textInput Form-textInput--variableHeight input-medium lookup" style="padding: 4px 6px;">
<span class="LabelList-tag" ng-repeat="tag in instanceGroupsTags">
<span class="LabelList-name">{{ tag }}</span>
</span>
</span>
</div>

View File

@ -3,6 +3,7 @@ export default ['i18n', function(i18n) {
name: 'instance_groups' ,
basePath: 'instance_groups',
iterator: 'instance_group',
editTitle: i18n._('INSTANCE GROUPS'),
listTitle: i18n._('INSTANCE GROUPS'),
index: false,
hover: false,
@ -18,7 +19,7 @@ export default ['i18n', function(i18n) {
label: i18n._('Capacity'),
nosort: true,
},
running_jobs: {
jobs_running: {
label: i18n._('Running Jobs'),
nosort: true,
},

View File

@ -1,13 +1,17 @@
import InstanceGroupsList from './list/instance-groups-list.controller';
import instanceGroupsMultiselect from './instance-groups-multiselect/instance-groups.directive';
import instanceGroupsModal from './instance-groups-multiselect/instance-groups-modal/instance-groups-modal.directive';
import list from './instance-groups.list';
import service from './instance-groups.service';
import { N_ } from '../i18n';
export default
angular.module('instanceGroups', [])
.factory('InstanceGroupList', list)
.service('InstanceGroupsService', service)
.factory('InstanceGroupList', list)
.controller('InstanceGroupsList', InstanceGroupsList)
.directive('instanceGroupsMultiselect', instanceGroupsMultiselect)
.directive('instanceGroupsModal', instanceGroupsModal)
.config(['$stateProvider', 'stateDefinitionsProvider',
function($stateProvider, stateDefinitionsProvider) {
let stateDefinitions = stateDefinitionsProvider.$get();
@ -21,16 +25,11 @@ angular.module('instanceGroups', [])
controllers: {
list: 'InstanceGroupsList'
},
data: {
activityStream: true,
activityStreamTarget: 'instanceGroup'
},
ncyBreadcrumb: {
parent: 'setup',
label: N_('INSTANCE GROUPS')
}
})
});
}
]);

View File

@ -115,6 +115,28 @@ angular.module('inventory', [
data: {
activityStream: true,
activityStreamTarget: 'inventory'
},
resolve: {
edit: {
InstanceGroupsData: ['$stateParams', 'Rest', 'GetBasePath', 'ProcessErrors',
function($stateParams, Rest, GetBasePath, ProcessErrors){
let path = `${GetBasePath('inventory')}${$stateParams.inventory_id}/instance_groups/`;
Rest.setUrl(path);
return Rest.get()
.then(({data}) => {
if (data.results.length > 0) {
return data.results;
}
})
.catch(({data, status}) => {
ProcessErrors(null, data, status, null, {
hdr: 'Error!',
msg: 'Failed to get instance groups. GET returned ' +
'status: ' + status
});
});
}]
}
}
});

View File

@ -13,7 +13,7 @@
function InventoriesAdd($scope, $location,
GenerateForm, InventoryForm, rbacUiControlService, Rest, Alert, ProcessErrors,
ClearScope, GetBasePath, ParseTypeChange, Wait, ToJSON,
$state, canAdd, CreateSelect2, InstanceGroupsService, InstanceGroupsData) {
$state, canAdd, CreateSelect2, InstanceGroupsService) {
$scope.canAdd = canAdd;
@ -42,13 +42,6 @@ function InventoriesAdd($scope, $location,
});
}
$scope.instanceGroupOptions = InstanceGroupsData;
CreateSelect2({
element: '#inventory_instance_groups',
multiple: true,
addNew: false
});
// Save
$scope.formSave = function() {
Wait('start');
@ -104,5 +97,5 @@ function InventoriesAdd($scope, $location,
export default ['$scope', '$location',
'GenerateForm', 'InventoryForm', 'rbacUiControlService', 'Rest', 'Alert',
'ProcessErrors', 'ClearScope', 'GetBasePath', 'ParseTypeChange',
'Wait', 'ToJSON', '$state','canAdd', 'CreateSelect2', 'InstanceGroupsService', 'InstanceGroupsData', InventoriesAdd
'Wait', 'ToJSON', '$state','canAdd', 'CreateSelect2', 'InstanceGroupsService', InventoriesAdd
];

View File

@ -35,36 +35,7 @@ function InventoriesEdit($scope, $location,
$scope.organization_name = inventoryData.summary_fields.organization.name;
$scope.inventory_variables = inventoryData.variables === null || inventoryData.variables === '' ? '---' : ParseVariableString(inventoryData.variables);
$scope.parseType = 'yaml';
$scope.instanceGroupOptions = InstanceGroupsData;
CreateSelect2({
element: '#inventory_instance_groups',
multiple: true,
addNew: false
});
Rest.setUrl(instance_group_url);
Rest.get()
.then(({data}) => {
if (data.results.length > 0) {
var opts = data.results
.map(i => ({id: i.id + "",
name: i.name}));
CreateSelect2({
element:'#inventory_instance_groups',
multiple: true,
addNew: false,
opts: opts
});
}
})
.catch(({data, status}) => {
ProcessErrors($scope, data, status, form, {
hdr: 'Error!',
msg: 'Failed to get instance groups. GET returned ' +
'status: ' + status
});
});
$scope.instance_groups = InstanceGroupsData;
$rootScope.$on('$stateChangeSuccess', function(event, toState) {
if(toState.name === 'inventories.edit') {

View File

@ -81,13 +81,12 @@ function(i18n, InventoryCompletedJobsList) {
},
instance_groups: {
label: i18n._('Instance Groups'),
type: 'select',
type: 'custom',
awPopOver: "<p>" + i18n._("Select the Instance Groups for this Inventory to run on.") + "</p>",
dataTitle: i18n._('Instance Groups'),
dataPlacement: 'right',
dataContainer: 'body',
multiSelect: true,
ngOptions: 'group.name for group in instanceGroupOptions track by group.id',
control: '<instance-groups-multiselect instance-groups="instance_groups"></instance-groups-multiselect>',
},
inventory_variables: {
realName: 'variables',

View File

@ -6,9 +6,9 @@
export default ['$scope', '$rootScope', '$location', '$stateParams',
'OrganizationForm', 'GenerateForm', 'Rest', 'Alert',
'ProcessErrors', 'ClearScope', 'GetBasePath', 'Wait', 'CreateSelect2', '$state','InstanceGroupsService','InstanceGroupsData',
'ProcessErrors', 'ClearScope', 'GetBasePath', 'Wait', 'CreateSelect2', '$state','InstanceGroupsService',
function($scope, $rootScope, $location, $stateParams, OrganizationForm,
GenerateForm, Rest, Alert, ProcessErrors, ClearScope, GetBasePath, Wait, CreateSelect2, $state, InstanceGroupsService, InstanceGroupsData) {
GenerateForm, Rest, Alert, ProcessErrors, ClearScope, GetBasePath, Wait, CreateSelect2, $state, InstanceGroupsService) {
Rest.setUrl(GetBasePath('organizations'));
Rest.options()
@ -33,13 +33,6 @@ export default ['$scope', '$rootScope', '$location', '$stateParams',
GenerateForm.applyDefaults(form, $scope);
}
$scope.instanceGroupOptions = InstanceGroupsData;
CreateSelect2({
element: '#organization_instance_groups',
multiple: true,
addNew: false
});
// Save
$scope.formSave = function() {
Wait('start');

View File

@ -30,37 +30,7 @@ export default ['$scope', '$location', '$stateParams',
});
$scope.$emit("HideOrgListHeader");
$scope.organization_id = id;
$scope.instanceGroupOptions = InstanceGroupsData;
CreateSelect2({
element: '#organization_instance_groups',
multiple: true,
addNew: false
});
Rest.setUrl(instance_group_url);
Rest.get()
.then(({data}) => {
if (data.results.length > 0) {
let opts = data.results
.map(i => ({id: i.id + "",
name: i.name}));
CreateSelect2({
element: '#organization_instance_groups',
multiple: true,
addNew: false,
opts: opts
});
}
})
.catch(({data, status}) => {
ProcessErrors($scope, data, status, form, {
hdr: 'Error!',
msg: 'Failed to get instance groups. GET returned ' +
'status: ' + status
});
});
$scope.instance_groups = InstanceGroupsData;
}

View File

@ -27,23 +27,7 @@ angular.module('Organizations', [
.config(['$stateProvider', 'stateDefinitionsProvider', '$stateExtenderProvider',
function($stateProvider, stateDefinitionsProvider, $stateExtenderProvider) {
let stateExtender = $stateExtenderProvider.$get(),
stateDefinitions = stateDefinitionsProvider.$get(),
organizationResolve = {
InstanceGroupsData: ['Rest', 'GetBasePath', 'ProcessErrors', (Rest, GetBasePath, ProcessErrors) => {
const url = GetBasePath('instance_groups');
Rest.setUrl(url);
return Rest.get()
.then(({data}) => {
return data.results.map((i) => ({name: i.name, id: i.id}));
})
.catch(({data, status}) => {
ProcessErrors(null, data, status, null, {
hdr: 'Error!',
msg: 'Failed to get instance groups info. GET returned status: ' + status
});
});
}]
};
stateDefinitions = stateDefinitionsProvider.$get();
// lazily generate a tree of substates which will replace this node in ui-router's stateRegistry
// see: stateDefinition.factory for usage documentation
@ -72,8 +56,26 @@ angular.module('Organizations', [
activityStreamTarget: 'organization'
},
resolve: {
add: organizationResolve,
edit: organizationResolve
edit: {
InstanceGroupsData: ['$stateParams', 'Rest', 'GetBasePath', 'ProcessErrors',
function($stateParams, Rest, GetBasePath, ProcessErrors){
let path = `${GetBasePath('organizations')}${$stateParams.organization_id}/instance_groups/`;
Rest.setUrl(path);
return Rest.get()
.then(({data}) => {
if (data.results.length > 0) {
return data.results;
}
})
.catch(({data, status}) => {
ProcessErrors(null, data, status, null, {
hdr: 'Error!',
msg: 'Failed to get instance groups. GET returned ' +
'status: ' + status
});
});
}]
}
}
// concat manually-defined state definitions with generated defintions
}).then((generated) => {

View File

@ -36,13 +36,12 @@ export default ['NotificationsList', 'i18n',
},
instance_groups: {
label: i18n._('Instance Groups'),
type: 'select',
type: 'custom',
awPopOver: "<p>" + i18n._("Select the Instance Groups for this Organization to run on.") + "</p>",
dataTitle: i18n._('Instance Groups'),
dataContainer: 'body',
dataPlacement: 'right',
dataTitle: i18n._('Instance Groups'),
multiSelect: true,
ngOptions: 'group.name for group in instanceGroupOptions track by group.id',
control: '<instance-groups-multiselect instance-groups="instance_groups"></instance-groups-multiselect>',
}
},

View File

@ -245,13 +245,12 @@ function(NotificationsList, CompletedJobsList, i18n) {
},
instance_groups: {
label: i18n._('Instance Groups'),
type: 'select',
type: 'custom',
awPopOver: "<p>" + i18n._("Select the Instance Groups for this Job Template to run on.") + "</p>",
dataTitle: i18n._('Instance Groups'),
dataContainer: 'body',
dataPlacement: 'right',
dataTitle: i18n._('Instance Groups'),
multiSelect: true,
ngOptions: 'group.name for group in instanceGroupOptions track by group.id',
control: '<instance-groups-multiselect instance-groups="instance_groups"></instance-groups-multiselect>',
},
job_tags: {
label: i18n._('Job Tags'),

View File

@ -9,14 +9,13 @@
'$stateParams', 'JobTemplateForm', 'GenerateForm', 'Rest', 'Alert',
'ProcessErrors', 'ClearScope', 'GetBasePath', 'md5Setup', 'ParseTypeChange', 'Wait',
'Empty', 'ToJSON', 'CallbackHelpInit', 'GetChoices', '$state',
'CreateSelect2', '$q', 'i18n', 'Inventory', 'Project', 'InstanceGroupsService', 'InstanceGroupsData',
'CreateSelect2', '$q', 'i18n', 'Inventory', 'Project', 'InstanceGroupsService',
function(
$filter, $scope,
$stateParams, JobTemplateForm, GenerateForm, Rest, Alert,
ProcessErrors, ClearScope, GetBasePath, md5Setup, ParseTypeChange, Wait,
Empty, ToJSON, CallbackHelpInit, GetChoices,
$state, CreateSelect2, $q, i18n, Inventory, Project, InstanceGroupsService,
InstanceGroupsData
$state, CreateSelect2, $q, i18n, Inventory, Project, InstanceGroupsService
) {
Rest.setUrl(GetBasePath('job_templates'));
@ -48,13 +47,6 @@
$scope.mode = "add";
$scope.parseType = 'yaml';
$scope.instanceGroupOptions = InstanceGroupsData;
CreateSelect2({
element: '#job_template_instance_groups',
multiple: true,
addNew: false
});
md5Setup({
scope: $scope,
master: master,
@ -244,6 +236,7 @@
$state.go('templates.editJobTemplate', {job_template_id: id}, {reload: true});
}
if ($scope.removeTemplateSaveSuccess) {
$scope.removeTemplateSaveSuccess();
}

View File

@ -54,36 +54,7 @@ export default
$scope.mode = 'edit';
$scope.parseType = 'yaml';
$scope.showJobType = false;
$scope.instanceGroupOptions = InstanceGroupsData;
CreateSelect2({
element: '#job_template_instance_groups',
multiple: true,
addNew: false
});
Rest.setUrl(instance_group_url);
Rest.get()
.then(({data}) => {
if (data.results.length > 0) {
let opts = data.results
.map(i => ({id: i.id + "",
name: i.name}));
CreateSelect2({
element: '#job_template_instance_groups',
multiple: true,
addNew: false,
opts: opts
});
}
})
.catch(({data, status}) => {
ProcessErrors($scope, data, status, form, {
hdr: 'Error!',
msg: 'Failed to get instance groups. GET returned ' +
'status: ' + status
});
});
$scope.instance_groups = InstanceGroupsData;
SurveyControllerInit({
scope: $scope,

View File

@ -46,24 +46,7 @@ angular.module('templates', [surveyMaker.name, templatesList.name, jobTemplatesA
let stateTree, addJobTemplate, editJobTemplate, addWorkflow, editWorkflow,
workflowMaker, inventoryLookup, credentialLookup,
stateDefinitions = stateDefinitionsProvider.$get(),
stateExtender = $stateExtenderProvider.$get(),
instanceGroupsResolve = {
InstanceGroupsData: ['Rest', 'GetBasePath', 'ProcessErrors', (Rest, GetBasePath, ProcessErrors) => {
const url = GetBasePath('instance_groups');
Rest.setUrl(url);
return Rest.get()
.then(({data}) => {
return data.results.map((i) => ({name: i.name, id: i.id}));
})
.catch(({data, status}) => {
ProcessErrors(null, data, status, null, {
hdr: 'Error!',
msg: 'Failed to get instance groups info. GET returned status: ' + status
});
});
}]
};
stateExtender = $stateExtenderProvider.$get();
function generateStateTree() {
@ -102,8 +85,7 @@ angular.module('templates', [surveyMaker.name, templatesList.name, jobTemplatesA
});
});
}
}],
InstanceGroupsData: instanceGroupsResolve.InstanceGroupsData
}]
}
}
});
@ -125,7 +107,26 @@ angular.module('templates', [surveyMaker.name, templatesList.name, jobTemplatesA
activityStreamId: 'job_template_id'
},
resolve: {
edit: instanceGroupsResolve
edit: {
InstanceGroupsData: ['$stateParams', 'Rest', 'GetBasePath', 'ProcessErrors',
function($stateParams, Rest, GetBasePath, ProcessErrors){
let path = `${GetBasePath('job_templates')}${$stateParams.job_template_id}/instance_groups/`;
Rest.setUrl(path);
return Rest.get()
.then(({data}) => {
if (data.results.length > 0) {
return data.results;
}
})
.catch(({data, status}) => {
ProcessErrors(null, data, status, null, {
hdr: 'Error!',
msg: 'Failed to get instance groups. GET returned ' +
'status: ' + status
});
});
}]
}
}
});