From 3377927c005bf4988f5c8f4a438dac2e7d490990 Mon Sep 17 00:00:00 2001 From: Chris Houseknecht Date: Tue, 19 Nov 2013 02:25:37 +0000 Subject: [PATCH] Activity stream- completed modification to Rest lib. Fixed searches on activity stream allow search by object type and object name. Improved detail modal so that more of the changes box is visible. Moved search reset button to the right. There is now only one reset button per list, not one per filter widget. --- awx/ui/static/js/forms/ActivityDetail.js | 15 +++++--- awx/ui/static/js/helpers/search.js | 24 ++++++++----- awx/ui/static/js/lists/Streams.js | 35 ++++++++++--------- awx/ui/static/js/widgets/Stream.js | 13 ++++--- awx/ui/static/lib/ansible/RestServices.js | 16 +++++---- awx/ui/static/lib/ansible/form-generator.js | 28 +++++++++++++++ .../static/lib/ansible/generator-helpers.js | 10 ++++-- awx/ui/static/lib/ansible/list-generator.js | 1 - 8 files changed, 98 insertions(+), 44 deletions(-) diff --git a/awx/ui/static/js/forms/ActivityDetail.js b/awx/ui/static/js/forms/ActivityDetail.js index b228382f2e..7cce68036c 100644 --- a/awx/ui/static/js/forms/ActivityDetail.js +++ b/awx/ui/static/js/forms/ActivityDetail.js @@ -13,6 +13,8 @@ angular.module('ActivityDetailDefinition', []) editTitle: 'Activity Detail', well: false, 'class': 'horizontal-narrow', + formFieldSize: 'col-lg-10', + formLabelSize: 'col-lg-2', fields: { timestamp: { @@ -20,6 +22,11 @@ angular.module('ActivityDetailDefinition', []) type: 'text', readonly: true }, + user: { + label: 'Initiated By', + type: 'text', + readonly: true + }, id: { label: 'Event ID', type: 'text', @@ -31,7 +38,7 @@ angular.module('ActivityDetailDefinition', []) readonly: true }, object1: { - label: 'Object 1', + label: 'Resource', type: 'text', ngHide: '!object1', readonly: true @@ -43,7 +50,7 @@ angular.module('ActivityDetailDefinition', []) readonly: true }, object2: { - label: 'Object 2', + label: 'Related', type: 'text', ngHide: '!object2', readonly: true @@ -56,8 +63,8 @@ angular.module('ActivityDetailDefinition', []) }, changes: { label: 'Changes', - type: 'textarea', - ngHide: '!changes', + type: 'lgtextarea', + ngHide: "!changes || changes =='' || changes == 'null'", readonly: true } } diff --git a/awx/ui/static/js/helpers/search.js b/awx/ui/static/js/helpers/search.js index bca7bf816d..f3edabcdfc 100644 --- a/awx/ui/static/js/helpers/search.js +++ b/awx/ui/static/js/helpers/search.js @@ -105,8 +105,10 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper']) } } } - - for (var i=1; i <= 3; i++) { + + // Set default values for each search widget on the page + var widgets = (list.searchWidgets) ? list.searchWidgets : 1; + for (var i=1; i <= widgets; i++) { var modifier = (i == 1) ? '' : i; if ( $('#search-widget-container' + modifier) ) { setDefaults(i); @@ -169,9 +171,13 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper']) scope.search(iterator); } - scope.resetSearch = function(iterator, widget) { + scope.resetSearch = function(iterator) { // Respdond to click of reset button - setDefaults(widget); + var widgets = (list.searchWidgets) ? list.searchWidgets : 1; + for (var i=1; i <= widgets; i++) { + // Clear each search widget + setDefaults(i); + } // Force removal of search keys from the URL window.location = '/#' + $location.path(); scope.search(iterator); @@ -245,6 +251,7 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper']) found_objects = 0; for (var i=1; i <= widgets; i++) { modifier = (i == 1) ? '' : i; + scope[iterator + 'HoldInput' + modifier] = true; //Block any input until we're done. Refresh.js will flip this back. if ($('#search-widget-container' + modifier) && list.fields[scope[iterator + 'SearchField' + modifier]] && list.fields[scope[iterator + 'SearchField' + modifier]].searchObject && @@ -258,12 +265,12 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper']) if ( $('#search-widget-container' + modifier) ) { if (list.fields[scope[iterator + 'SearchField' + modifier]] && list.fields[scope[iterator + 'SearchField' + modifier]].searchObject && - list.fields[scope[iterator + 'SearchField' + modifier]].searchObject !== 'all') { - scope[iterator + 'HoldInput' + modifier] = true; + list.fields[scope[iterator + 'SearchField' + modifier]].searchObject !== 'all') { if (scope[iterator + 'SearchValue' + modifier]) { var objs = list.fields[scope[iterator + 'SearchField' + modifier]].searchObject; - var objUrl = GetBasePath('base') + objs + '/?name__icontains=' + scope[iterator + 'SearchValue']; + var objUrl = GetBasePath('base') + objs + '/?name__icontains=' + scope[iterator + 'SearchValue' + modifier]; Rest.setUrl(objUrl); + Rest.setHeader({ widget: i }); Rest.get() .success( function(data, status, headers, config) { var pk=''; @@ -271,8 +278,7 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper']) pk += "," + data.results[j].id; } pk = pk.replace(/^\,/,''); - console.log(config); - scope.$emit('foundObject', iterator, page, load, spin, i, pk); + scope.$emit('foundObject', iterator, page, load, spin, config.headers['widget'], pk); }) .error( function(data, status, headers, config) { ProcessErrors(scope, data, status, null, diff --git a/awx/ui/static/js/lists/Streams.js b/awx/ui/static/js/lists/Streams.js index 9e83071d74..8c2391c66b 100644 --- a/awx/ui/static/js/lists/Streams.js +++ b/awx/ui/static/js/lists/Streams.js @@ -37,14 +37,8 @@ angular.module('StreamListDefinition', []) searchPlaceholder: 'Initiated by username', searchWidget: 1 }, - objects: { - label: 'Objects', - ngBindHtml: 'activity.objects', - nosort: true, - searchable: false - }, description: { - label: 'Description', + label: 'Action', ngBindHtml: 'activity.description', nosort: true, searchable: false @@ -64,7 +58,7 @@ angular.module('StreamListDefinition', []) label: 'All', searchOnly: true, searchObject: 'all', - searchPlaceholder: 'All primary objects', + searchPlaceholder: 'All resources', searchWidget: 2, searchField: 'object1' }, @@ -72,7 +66,7 @@ angular.module('StreamListDefinition', []) label: 'Credential', searchOnly: true, searchObject: 'credentials', - searchPlaceholder: 'Primary credential name', + searchPlaceholder: 'Credential name', searchWidget: 2, searchField: 'object1' }, @@ -80,7 +74,7 @@ angular.module('StreamListDefinition', []) label: 'Group', searchOnly: true, searchObject: 'groups', - searchPlaceholder: 'Primary group name', + searchPlaceholder: 'Group name', searchWidget: 2, searchField: 'object1' }, @@ -88,7 +82,7 @@ angular.module('StreamListDefinition', []) label: 'Host', searchOnly: true, searchObject: 'hosts', - searchPlaceholder: 'Primary host name', + searchPlaceholder: 'Host name', searchWidget: 2, searchField: 'object1' }, @@ -96,7 +90,7 @@ angular.module('StreamListDefinition', []) label: 'Inventory', searchOnly: true, searchObject: 'inventories', - searchPlaceholder: 'Primary inventory name', + searchPlaceholder: 'Inventory name', searchWidget: 2, searchField: 'object1' }, @@ -104,7 +98,7 @@ angular.module('StreamListDefinition', []) label: 'Job Template', searchOnly: true, searchObject: 'job_templates', - searchPlaceholder: 'Primary job template name', + searchPlaceholder: 'Job template name', searchWidget: 2, searchField: 'object1' }, @@ -112,7 +106,7 @@ angular.module('StreamListDefinition', []) label: 'Organization', searchOnly: true, searchObject: 'organizations', - searchPlaceholder: 'Primary organization name', + searchPlaceholder: 'Organization name', searchWidget: 2, searchField: 'object1' }, @@ -120,7 +114,7 @@ angular.module('StreamListDefinition', []) label: 'Project', searchOnly: true, searchObject: 'projects', - searchPlaceholder: 'Primary project name', + searchPlaceholder: 'Project name', searchWidget: 2, searchField: 'object1' }, @@ -139,7 +133,7 @@ angular.module('StreamListDefinition', []) label: 'All', searchOnly: true, searchObject: 'all', - searchPlaceholder: 'All related objects', + searchPlaceholder: 'All related resources', searchWidget: 3, searchField: 'object2' }, @@ -219,6 +213,15 @@ angular.module('StreamListDefinition', []) ngClick: "refreshStream()", iconSize: 'large' }, + reset: { + dataPlacement: 'top', + icon: "icon-undo", + mode: 'all', + 'class': 'btn-xs btn-primary', + awToolTip: "Reset the search filter", + ngClick: "resetSearch()", + iconSize: 'large' + }, close: { dataPlacement: 'top', icon: "icon-arrow-left", diff --git a/awx/ui/static/js/widgets/Stream.js b/awx/ui/static/js/widgets/Stream.js index 84a2dd3a88..3274f19947 100644 --- a/awx/ui/static/js/widgets/Stream.js +++ b/awx/ui/static/js/widgets/Stream.js @@ -82,14 +82,14 @@ angular.module('StreamWidget', ['RestServices', 'Utilities', 'StreamListDefiniti .factory('BuildDescription', ['FixUrl', 'BuildUrl', function(FixUrl, BuildUrl) { return function(activity) { var descr = ''; - if (activity.summary_fields.user) { + /*if (activity.summary_fields.user) { // this is a user transaction var usr = FixUrl(activity.related.user); descr += 'User ' + activity.summary_fields.user.username + ' '; } else { descr += 'System '; - } + }*/ descr += activity.operation; descr += (/e$/.test(activity.operation)) ? 'd ' : 'ed '; if (activity.summary_fields.object2 && activity.summary_fields.object2.name) { @@ -110,8 +110,8 @@ angular.module('StreamWidget', ['RestServices', 'Utilities', 'StreamListDefiniti } }]) - .factory('ShowDetail', ['Rest', 'Alert', 'GenerateForm', 'ProcessErrors', 'GetBasePath', 'FormatDate', 'ActivityDetailForm', - function(Rest, Alert, GenerateForm, ProcessErrors, GetBasePath, FormatDate, ActivityDetailForm) { + .factory('ShowDetail', ['Rest', 'Alert', 'GenerateForm', 'ProcessErrors', 'GetBasePath', 'FormatDate', 'ActivityDetailForm', 'Empty', + function(Rest, Alert, GenerateForm, ProcessErrors, GetBasePath, FormatDate, ActivityDetailForm, Empty) { return function(activity_id) { var generator = GenerateForm; @@ -157,7 +157,10 @@ angular.module('StreamWidget', ['RestServices', 'Utilities', 'StreamListDefiniti if (results.summary_fields.object2) { scope['object2_name'] = results.summary_fields.object2.name; } - scope['changes'] = JSON.stringify(results['changes'], null, '\t'); + scope['user'] = (results.summary_fields.user) ? results.summary_fields.user.username : 'system'; + scope['changes'] = results['changes']; + //scope['changes'] = (!Empty(results['changes'])) ? JSON.parse(scope.variables) : ''; + //scope['changes'] = JSON.stringify(results['changes'], null, '\t'); scope.formModalAction = function() { $('#form-modal').modal("hide"); } diff --git a/awx/ui/static/lib/ansible/RestServices.js b/awx/ui/static/lib/ansible/RestServices.js index 489d86e8e4..182ec4b0d8 100644 --- a/awx/ui/static/lib/ansible/RestServices.js +++ b/awx/ui/static/lib/ansible/RestServices.js @@ -46,9 +46,9 @@ function($http, $rootScope, $cookieStore, $q, Authorization) { }, setHeader: function(hdr) { - // Passin in { key: value } pairs to be added to the header + // Pass in { key: value } pairs to be added to the header for (var h in hdr) { - this.headers[h] = hdr.h; + this.headers[h] = hdr[h]; } }, get: function(args) { @@ -79,10 +79,11 @@ function($http, $rootScope, $cookieStore, $q, Authorization) { return this.createResponse({ detail: 'Token is expired' }, 401); } else if (token) { + this.setHeader({ Authorization: 'Token ' + token }); return $http({ method: 'POST', url: this.url, - headers: { 'Authorization': 'Token ' + token }, + headers: this.headers, data: data }); } else { @@ -96,10 +97,11 @@ function($http, $rootScope, $cookieStore, $q, Authorization) { return this.createResponse({ detail: 'Token is expired' }, 401); } else if (token) { + this.setHeader({ Authorization: 'Token ' + token }); return $http({ method: 'PUT', url: this.url, - headers: { 'Authorization': 'Token ' + token }, + headers: this.headers, data: data }); } else { @@ -113,10 +115,11 @@ function($http, $rootScope, $cookieStore, $q, Authorization) { return this.createResponse({ detail: 'Token is expired' }, 401); } else if (token) { + this.setHeader({ Authorization: 'Token ' + token }); return $http({ method: 'DELETE', url: this.url, - headers: { 'Authorization': 'Token ' + token }, + headers: this.headers, data: data }); } else { @@ -130,10 +133,11 @@ function($http, $rootScope, $cookieStore, $q, Authorization) { return this.createResponse({ detail: 'Token is expired' }, 401); } else if (token) { + this.setHeader({ Authorization: 'Token ' + token }); return $http({ method: 'OPTIONS', url: this.url, - headers: { 'Authorization': 'Token ' + token } + headers: this.headers }); } else { diff --git a/awx/ui/static/lib/ansible/form-generator.js b/awx/ui/static/lib/ansible/form-generator.js index b7cb2955fb..604a43bb4d 100644 --- a/awx/ui/static/lib/ansible/form-generator.js +++ b/awx/ui/static/lib/ansible/form-generator.js @@ -898,6 +898,34 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies', 'Utilities']) html += "\n"; } + if (field.type == 'lgtextarea') { + // Use for modal, readonly textarea fields + html += "
\n"; + html += ""; + html += "
\n"; + html += "
\n"; + html += "
" + html += "