diff --git a/awx/ui/client/legacy-styles/ansible-ui.less b/awx/ui/client/legacy-styles/ansible-ui.less index 028529fffa..06d924b141 100644 --- a/awx/ui/client/legacy-styles/ansible-ui.less +++ b/awx/ui/client/legacy-styles/ansible-ui.less @@ -697,6 +697,23 @@ legend { margin-bottom: 7px; } + .pagination>li>a, + .pagination>li>span { + border: 1px solid @grey-border; + padding: 3px 6px; + font-size: 10px; + } + + .pagination li { + a#next-page { + border-radius: 0 4px 4px 0; + } + + a#previous-page { + border-radius: 4px 0 0 4px; + } + } + .modal-body { .pagination { margin-top: 15px; diff --git a/awx/ui/client/legacy-styles/lists.less b/awx/ui/client/legacy-styles/lists.less index 9db2792d2b..2dcac015c8 100644 --- a/awx/ui/client/legacy-styles/lists.less +++ b/awx/ui/client/legacy-styles/lists.less @@ -101,7 +101,6 @@ table, tbody { margin-left: 15px; } - /* -- Pagination -- */ .List-pagination { margin-top: 20px; @@ -110,23 +109,6 @@ table, tbody { text-transform: uppercase; height: 22px; display: flex; - - .pagination>li>a, - .pagination>li>span { - border: 1px solid @grey-border; - padding: 3px 6px; - font-size: 10px; - } - - .pagination li { - a#next-page { - border-radius: 0 4px 4px 0; - } - - a#previous-page { - border-radius: 4px 0 0 4px; - } - } } .List-paginationPagerHolder { @@ -368,25 +350,3 @@ table, tbody { display: block; font-size: 13px; } - -#lookup-modal-dialog { - - .List-searchWidget { - width: 66.6666% - } - - .List-tableHeaderRow { - .List-tableHeader:first-of-type { - width: 3%; - } - } - - .List-tableHeader, - .List-tableHeader:last-of-type { - text-align:left; - } - - .List-tableCell { - color: @default-interface-txt; - } -} diff --git a/awx/ui/client/src/app.js b/awx/ui/client/src/app.js index 43ad6627fb..2c27bf8c20 100644 --- a/awx/ui/client/src/app.js +++ b/awx/ui/client/src/app.js @@ -45,6 +45,7 @@ import adhoc from './adhoc/main'; import login from './login/main'; import activityStream from './activity-stream/main'; import standardOut from './standard-out/main'; +import lookUpHelper from './lookup/main'; import {JobTemplatesList, JobTemplatesAdd, JobTemplatesEdit} from './controllers/JobTemplates'; import {LicenseController} from './controllers/License'; import {ScheduleEditController} from './controllers/Schedules'; diff --git a/awx/ui/client/src/helpers.js b/awx/ui/client/src/helpers.js index 4a277970da..4b9c4ab548 100644 --- a/awx/ui/client/src/helpers.js +++ b/awx/ui/client/src/helpers.js @@ -22,7 +22,6 @@ import Jobs from "./helpers/Jobs"; import License from "./helpers/License"; import LoadConfig from "./helpers/LoadConfig"; import LogViewer from "./helpers/LogViewer"; -import Lookup from "./helpers/Lookup"; import PaginationHelpers from "./helpers/PaginationHelpers"; import Parse from "./helpers/Parse"; import ProjectPath from "./helpers/ProjectPath"; @@ -60,7 +59,6 @@ export License, LoadConfig, LogViewer, - Lookup, PaginationHelpers, Parse, ProjectPath, diff --git a/awx/ui/client/src/helpers/Lookup.js b/awx/ui/client/src/helpers/Lookup.js deleted file mode 100644 index d23614de3c..0000000000 --- a/awx/ui/client/src/helpers/Lookup.js +++ /dev/null @@ -1,306 +0,0 @@ -/************************************************* - * Copyright (c) 2015 Ansible, Inc. - * - * All Rights Reserved - *************************************************/ - - - /** - * @ngdoc function - * @name helpers.function:Lookup - * @description - * LookUpInit( { - * scope: , - * form:
, - * current_item: , - * list: , - * field: , - * hdr: - * postAction: optional function to run after selection made, - * callback: optional label to $emit() on parent scope - * input_type: optional string that specifies whether lookup should have checkboxes or radio buttons. defaults to 'checkbox' --- added by JT 8/21/14 - * }) - */ - -import listGenerator from '../shared/list-generator/main'; - -export default - angular.module('LookUpHelper', ['RestServices', 'Utilities', 'SearchHelper', 'PaginationHelpers', listGenerator.name, 'ApiLoader', 'ModalDialog']) - - .factory('LookUpInit', ['Alert', 'Rest', 'ProcessErrors', 'generateList', 'SearchInit', 'PaginateInit', 'GetBasePath', 'FormatDate', 'Empty', 'CreateDialog', - function (Alert, Rest, ProcessErrors, GenerateList, SearchInit, PaginateInit, GetBasePath, FormatDate, Empty, CreateDialog) { - return function (params) { - - var parent_scope = params.scope, - form = params.form, - list = params.list, - field = params.field, - instructions = params.instructions, - postAction = params.postAction, - callback = params.callback, - autopopulateLookup, - input_type = (params.input_type) ? params.input_type: "checkbox", - defaultUrl, name, watchUrl; - - if (params.autopopulateLookup !== undefined) { - autopopulateLookup = params.autopopulateLookup; - } else { - autopopulateLookup = true; - } - - if (params.url) { - // pass in a url value to override the default - defaultUrl = params.url; - } else { - defaultUrl = (list.name === 'inventories') ? GetBasePath('inventory') : GetBasePath(list.name); - } - - if ($('#htmlTemplate #lookup-modal-dialog').length > 0) { - $('#htmlTemplate #lookup-modal-dialog').empty(); - } - else { - $('#htmlTemplate').append("
"); - } - - name = list.iterator.charAt(0).toUpperCase() + list.iterator.substring(1); - - watchUrl = (/\/$/.test(defaultUrl)) ? defaultUrl + '?' : defaultUrl + '&'; - watchUrl += form.fields[field].sourceField + '__' + 'iexact=:value'; - - $('input[name="' + form.fields[field].sourceModel + '_' + form.fields[field].sourceField + '"]').attr('data-url', watchUrl); - $('input[name="' + form.fields[field].sourceModel + '_' + form.fields[field].sourceField + '"]').attr('data-source', field); - - var sourceModel = form.fields[field].sourceModel, - sourceField = form.fields[field].sourceField; - - // this logic makes sure that the form is being added, and that the lookup to be autopopulated is required - // we also look to see if the lookupinit autopopulateLookup parameter passed in by the controller is false - function fieldIsAutopopulatable() { - if (autopopulateLookup === false) { - return false; - } if (parent_scope.mode === "add") { - if (parent_scope[sourceModel + "_field"].awRequiredWhen && - parent_scope[sourceModel + "_field"].awRequiredWhen.variable && - parent_scope[parent_scope[sourceModel + "_field"].awRequiredWhen.variable]) { - return true; - } else if (parent_scope[sourceModel + "_field"].addRequired === true) { - return true; - } else { - return false; - } - } else { - return false; - } - } - - if (fieldIsAutopopulatable()) { - // Auto populate the field if there is only one result - Rest.setUrl(defaultUrl); - Rest.get() - .success(function (data) { - if (data.count === 1) { - parent_scope[field] = data.results[0].id; - if (parent_scope[form.name + '_form'] && form.fields[field] && sourceModel) { - parent_scope[sourceModel + '_' + sourceField] = - data.results[0][sourceField]; - if (parent_scope[form.name + '_form'][sourceModel + '_' + sourceField]) { - parent_scope[form.name + '_form'][sourceModel + '_' + sourceField] - .$setValidity('awlookup', true); - } - } - if (parent_scope[form.name + '_form']) { - parent_scope[form.name + '_form'].$setDirty(); - } - } - }) - .error(function (data, status) { - ProcessErrors(parent_scope, data, status, form, { hdr: 'Error!', - msg: 'Failed to launch adhoc command. POST returned status: ' + - status }); - }); - } - - - parent_scope['lookUp' + name] = function () { - - var master = {}, - scope = parent_scope.$new(), - name, hdr, buttons; - - // Generating the search list potentially kills the values held in scope for the field. - // We'll keep a copy in master{} that we can revert back to on cancel; - master[field] = scope[field]; - master[form.fields[field].sourceModel + '_' + form.fields[field].sourceField] = - scope[form.fields[field].sourceModel + '_' + form.fields[field].sourceField]; - GenerateList.inject(list, { - mode: 'lookup', - id: 'lookup-modal-dialog', - scope: scope, - instructions: instructions, - input_type: input_type - }); - - name = list.iterator.charAt(0).toUpperCase() + list.iterator.substring(1); - hdr = (params.hdr) ? params.hdr : 'Select ' + name; - - // Show pop-up - buttons = [ - { - label: "Save", - onClick: function() { - scope.selectAction(); - }, - //icon: "fa-check", - "class": "btn btn-primary", - "id": "lookup-save-button" - },{ - label: "Cancel", - "class": "btn btn-default", - "id": "lookup-cancel-button", - onClick: function() { - $('#lookup-modal-dialog').dialog('close'); - } - }]; - - if (scope.removeModalReady) { - scope.removeModalReady(); - } - scope.removeModalReady = scope.$on('ModalReady', function() { - $('#lookup-save-button').attr('disabled','disabled'); - $('#lookup-modal-dialog').dialog('open'); - }); - - CreateDialog({ - scope: scope, - buttons: buttons, - width: 600, - height: (instructions) ? 625 : 450, - minWidth: 500, - title: hdr, - id: 'lookup-modal-dialog', - onClose: function() { - setTimeout( function() { - scope.$apply( function() { - if (Empty(scope[field])) { - scope[field] = master[field]; - scope[form.fields[field].sourceModel + '_' + form.fields[field].sourceField] = - master[form.fields[field].sourceModel + '_' + form.fields[field].sourceField]; - } - }); - }, 300); - }, - callback: 'ModalReady' - }); - - SearchInit({ - scope: scope, - set: list.name, - list: list, - url: defaultUrl - }); - - PaginateInit({ - scope: scope, - list: list, - url: defaultUrl, - mode: 'lookup' - }); - - if (scope.lookupPostRefreshRemove) { - scope.lookupPostRefreshRemove(); - } - scope.lookupPostRefreshRemove = scope.$on('PostRefresh', function () { - var fld, i; - for (fld in list.fields) { - if (list.fields[fld].type && list.fields[fld].type === 'date') { - //convert dates to our standard format - for (i = 0; i < scope[list.name].length; i++) { - scope[list.name][i][fld] = FormatDate(new Date(scope[list.name][i][fld])); - } - } - } - - // List generator creates the list, resetting it and losing the previously selected value. - // If the selected value is in the current set, find it and mark selected. - if (!Empty(parent_scope[form.fields[field].sourceModel + '_' + form.fields[field].sourceField])) { - scope[list.name].forEach(function(elem) { - if (elem[form.fields[field].sourceField] === - parent_scope[form.fields[field].sourceModel + '_' + form.fields[field].sourceField]) { - scope[field] = elem.id; - } - }); - - } - - if (!Empty(scope[field])) { - scope['toggle_' + list.iterator](scope[field]); - } - - }); - - scope.search(list.iterator); - - scope.selectAction = function () { - var i, found = false; - for (i = 0; i < scope[list.name].length; i++) { - if (scope[list.name][i].checked === '1' || scope[list.name][i].checked===1 || scope[list.name][i].checked === true) { - found = true; - parent_scope[field] = scope[list.name][i].id; - if (parent_scope[form.name + '_form'] && form.fields[field] && form.fields[field].sourceModel) { - parent_scope[form.fields[field].sourceModel + '_' + form.fields[field].sourceField] = - scope[list.name][i][form.fields[field].sourceField]; - if (parent_scope[form.name + '_form'][form.fields[field].sourceModel + '_' + form.fields[field].sourceField]) { - parent_scope[form.name + '_form'][form.fields[field].sourceModel + '_' + form.fields[field].sourceField] - .$setValidity('awlookup', true); - } - } - if (parent_scope[form.name + '_form']) { - parent_scope[form.name + '_form'].$setDirty(); - } - } - } - if (found) { - // Selection made - $('#lookup-modal-dialog').dialog('close'); - if (postAction) { - postAction(); - } - if (callback) { - parent_scope.$emit(callback); - } - } - }; - - - scope['toggle_' + list.iterator] = function (id) { - var count = 0; - scope[list.name].forEach( function(row, i) { - if (row.id === id) { - if (row.checked) { - scope[list.name][i].success_class = 'success'; - } - else { - row.checked = true; - scope[list.name][i].success_class = ''; - } - } else { - scope[list.name][i].checked = 0; - scope[list.name][i].success_class = ''; - } - }); - // Check if any rows are checked - scope[list.name].forEach(function(row) { - if (row.checked) { - count++; - } - }); - if (count === 0) { - $('#lookup-save-button').attr('disabled','disabled'); - } - else { - $('#lookup-save-button').removeAttr('disabled'); - } - }; - }; - }; - }]); diff --git a/awx/ui/client/src/lookup/lookup.block.less b/awx/ui/client/src/lookup/lookup.block.less new file mode 100644 index 0000000000..9f2dea25a9 --- /dev/null +++ b/awx/ui/client/src/lookup/lookup.block.less @@ -0,0 +1,22 @@ +@import "../shared/branding/colors.default.less"; + +#LookupModal-dialog { + .List-searchWidget { + width: 66.6666% + } + + .List-tableHeaderRow { + .List-tableHeader:first-of-type { + width: 3%; + } + } + + .List-tableHeader, + .List-tableHeader:last-of-type { + text-align:left; + } + + .List-tableCell { + color: @default-interface-txt; + } +} diff --git a/awx/ui/client/src/lookup/lookup.factory.js b/awx/ui/client/src/lookup/lookup.factory.js new file mode 100644 index 0000000000..468acbc4e6 --- /dev/null +++ b/awx/ui/client/src/lookup/lookup.factory.js @@ -0,0 +1,305 @@ +/************************************************* + * Copyright (c) 2016 Ansible, Inc. + * + * All Rights Reserved + *************************************************/ + + /** +* @ngdoc function +* @name helpers.function:Lookup +* @description +* LookUpInit( { +* scope: , +* form: , +* current_item: , +* list: , +* field: , +* hdr: +* postAction: optional function to run after selection made, +* callback: optional label to $emit() on parent scope +* input_type: optional string that specifies whether lookup should have checkboxes or radio buttons. defaults to 'checkbox' --- added by JT 8/21/14 +* }) +*/ + +export default ['Alert', 'Rest', 'ProcessErrors', 'generateList', + 'SearchInit', 'PaginateInit', 'GetBasePath', 'FormatDate', + 'Empty', 'CreateDialog', + function(Alert, Rest, ProcessErrors, GenerateList, + SearchInit, PaginateInit, GetBasePath, FormatDate, + Empty, CreateDialog) { + return function(params) { + + var parent_scope = params.scope, + form = params.form, + list = params.list, + field = params.field, + instructions = params.instructions, + postAction = params.postAction, + callback = params.callback, + autopopulateLookup, + input_type = (params.input_type) ? params.input_type : "checkbox", + defaultUrl, name, watchUrl; + + if (params.autopopulateLookup !== undefined) { + autopopulateLookup = params.autopopulateLookup; + } else { + autopopulateLookup = true; + } + + if (params.url) { + // pass in a url value to override the default + defaultUrl = params.url; + } else { + defaultUrl = (list.name === 'inventories') ? GetBasePath('inventory') : GetBasePath(list.name); + } + + if ($('#htmlTemplate #LookupModal-dialog').length > 0) { + $('#htmlTemplate #LookupModal-dialog').empty(); + } else { + $('#htmlTemplate').append("
"); + } + + name = list.iterator.charAt(0).toUpperCase() + list.iterator.substring(1); + + watchUrl = (/\/$/.test(defaultUrl)) ? defaultUrl + '?' : defaultUrl + '&'; + watchUrl += form.fields[field].sourceField + '__' + 'iexact=:value'; + + $('input[name="' + form.fields[field].sourceModel + '_' + form.fields[field].sourceField + '"]').attr('data-url', watchUrl); + $('input[name="' + form.fields[field].sourceModel + '_' + form.fields[field].sourceField + '"]').attr('data-source', field); + + var sourceModel = form.fields[field].sourceModel, + sourceField = form.fields[field].sourceField; + + // this logic makes sure that the form is being added, and that the lookup to be autopopulated is required + // we also look to see if the lookupinit autopopulateLookup parameter passed in by the controller is false + function fieldIsAutopopulatable() { + if (autopopulateLookup === false) { + return false; + } + if (parent_scope.mode === "add") { + if (parent_scope[sourceModel + "_field"].awRequiredWhen && + parent_scope[sourceModel + "_field"].awRequiredWhen.variable && + parent_scope[parent_scope[sourceModel + "_field"].awRequiredWhen.variable]) { + return true; + } else if (parent_scope[sourceModel + "_field"].addRequired === true) { + return true; + } else { + return false; + } + } else { + return false; + } + } + + if (fieldIsAutopopulatable()) { + // Auto populate the field if there is only one result + Rest.setUrl(defaultUrl); + Rest.get() + .success(function(data) { + if (data.count === 1) { + parent_scope[field] = data.results[0].id; + if (parent_scope[form.name + '_form'] && form.fields[field] && sourceModel) { + parent_scope[sourceModel + '_' + sourceField] = + data.results[0][sourceField]; + if (parent_scope[form.name + '_form'][sourceModel + '_' + sourceField]) { + parent_scope[form.name + '_form'][sourceModel + '_' + sourceField] + .$setValidity('awlookup', true); + } + } + if (parent_scope[form.name + '_form']) { + parent_scope[form.name + '_form'].$setDirty(); + } + } + }) + .error(function(data, status) { + ProcessErrors(parent_scope, data, status, form, { + hdr: 'Error!', + msg: 'Failed to launch adhoc command. POST returned status: ' + + status + }); + }); + } + + + parent_scope['lookUp' + name] = function() { + + var master = {}, + scope = parent_scope.$new(), + name, hdr, buttons; + + // Generating the search list potentially kills the values held in scope for the field. + // We'll keep a copy in master{} that we can revert back to on cancel; + master[field] = scope[field]; + master[form.fields[field].sourceModel + '_' + form.fields[field].sourceField] = + scope[form.fields[field].sourceModel + '_' + form.fields[field].sourceField]; + GenerateList.inject(list, { + mode: 'lookup', + id: 'LookupModal-dialog', + scope: scope, + instructions: instructions, + input_type: input_type + }); + + name = list.iterator.charAt(0).toUpperCase() + list.iterator.substring(1); + hdr = (params.hdr) ? params.hdr : 'Select ' + name; + + // Show pop-up + buttons = [{ + label: "Save", + onClick: function() { + scope.selectAction(); + }, + //icon: "fa-check", + "class": "btn btn-primary", + "id": "lookup-save-button" + }, { + label: "Cancel", + "class": "btn btn-default", + "id": "lookup-cancel-button", + onClick: function() { + $('#LookupModal-dialog').dialog('close'); + } + }]; + + if (scope.removeModalReady) { + scope.removeModalReady(); + } + scope.removeModalReady = scope.$on('ModalReady', function() { + $('#lookup-save-button').attr('disabled', 'disabled'); + $('#LookupModal-dialog').dialog('open'); + }); + + CreateDialog({ + scope: scope, + buttons: buttons, + width: 600, + height: (instructions) ? 625 : 450, + minWidth: 500, + title: hdr, + id: 'LookupModal-dialog', + onClose: function() { + setTimeout(function() { + scope.$apply(function() { + if (Empty(scope[field])) { + scope[field] = master[field]; + scope[form.fields[field].sourceModel + '_' + form.fields[field].sourceField] = + master[form.fields[field].sourceModel + '_' + form.fields[field].sourceField]; + } + }); + }, 300); + }, + callback: 'ModalReady' + }); + + SearchInit({ + scope: scope, + set: list.name, + list: list, + url: defaultUrl + }); + + PaginateInit({ + scope: scope, + list: list, + url: defaultUrl, + mode: 'lookup' + }); + + if (scope.lookupPostRefreshRemove) { + scope.lookupPostRefreshRemove(); + } + scope.lookupPostRefreshRemove = scope.$on('PostRefresh', function() { + var fld, i; + for (fld in list.fields) { + if (list.fields[fld].type && list.fields[fld].type === 'date') { + //convert dates to our standard format + for (i = 0; i < scope[list.name].length; i++) { + scope[list.name][i][fld] = FormatDate(new Date(scope[list.name][i][fld])); + } + } + } + + // List generator creates the list, resetting it and losing the previously selected value. + // If the selected value is in the current set, find it and mark selected. + if (!Empty(parent_scope[form.fields[field].sourceModel + '_' + form.fields[field].sourceField])) { + scope[list.name].forEach(function(elem) { + if (elem[form.fields[field].sourceField] === + parent_scope[form.fields[field].sourceModel + '_' + form.fields[field].sourceField]) { + scope[field] = elem.id; + } + }); + + } + + if (!Empty(scope[field])) { + scope['toggle_' + list.iterator](scope[field]); + } + + }); + + scope.search(list.iterator); + + scope.selectAction = function() { + var i, found = false; + for (i = 0; i < scope[list.name].length; i++) { + if (scope[list.name][i].checked === '1' || scope[list.name][i].checked === 1 || scope[list.name][i].checked === true) { + found = true; + parent_scope[field] = scope[list.name][i].id; + if (parent_scope[form.name + '_form'] && form.fields[field] && form.fields[field].sourceModel) { + parent_scope[form.fields[field].sourceModel + '_' + form.fields[field].sourceField] = + scope[list.name][i][form.fields[field].sourceField]; + if (parent_scope[form.name + '_form'][form.fields[field].sourceModel + '_' + form.fields[field].sourceField]) { + parent_scope[form.name + '_form'][form.fields[field].sourceModel + '_' + form.fields[field].sourceField] + .$setValidity('awlookup', true); + } + } + if (parent_scope[form.name + '_form']) { + parent_scope[form.name + '_form'].$setDirty(); + } + } + } + if (found) { + // Selection made + $('#LookupModal-dialog').dialog('close'); + if (postAction) { + postAction(); + } + if (callback) { + parent_scope.$emit(callback); + } + } + }; + + + scope['toggle_' + list.iterator] = function(id) { + var count = 0; + scope[list.name].forEach(function(row, i) { + if (row.id === id) { + if (row.checked) { + scope[list.name][i].success_class = 'success'; + } else { + row.checked = true; + scope[list.name][i].success_class = ''; + } + } else { + scope[list.name][i].checked = 0; + scope[list.name][i].success_class = ''; + } + }); + // Check if any rows are checked + scope[list.name].forEach(function(row) { + if (row.checked) { + count++; + } + }); + if (count === 0) { + $('#lookup-save-button').attr('disabled', 'disabled'); + } else { + $('#lookup-save-button').removeAttr('disabled'); + } + }; + }; + }; + + } +]; diff --git a/awx/ui/client/src/lookup/main.js b/awx/ui/client/src/lookup/main.js new file mode 100644 index 0000000000..f5ead33d5b --- /dev/null +++ b/awx/ui/client/src/lookup/main.js @@ -0,0 +1,12 @@ +/************************************************* + * Copyright (c) 2016 Ansible, Inc. + * + * All Rights Reserved + *************************************************/ +import LookUpInit from './lookup.factory'; +import listGenerator from '../shared/list-generator/main'; + +export default + angular.module('LookUpHelper', ['RestServices', 'Utilities', 'SearchHelper', + 'PaginationHelpers', listGenerator.name, 'ApiLoader', 'ModalDialog']) + .factory('LookUpInit', LookUpInit); diff --git a/awx/ui/client/src/partials/portal.html b/awx/ui/client/src/partials/portal.html index 077eed49e3..fe6039de54 100644 --- a/awx/ui/client/src/partials/portal.html +++ b/awx/ui/client/src/partials/portal.html @@ -32,4 +32,4 @@ - +