diff --git a/awx/main/middleware.py b/awx/main/middleware.py index 551faf0594..5a0f587440 100644 --- a/awx/main/middleware.py +++ b/awx/main/middleware.py @@ -126,6 +126,9 @@ class SessionTimeoutMiddleware(object): def process_response(self, request, response): should_skip = 'HTTP_X_WS_SESSION_QUIET' in request.META + # Something went wrong, such as upgrade-in-progress page + if not hasattr(request, 'session'): + return response # Only update the session if it hasn't been flushed by being forced to log out. if request.session and not request.session.is_empty() and not should_skip: expiry = int(settings.SESSION_COOKIE_AGE) diff --git a/awx/ui/client/features/jobs/jobsList.controller.js b/awx/ui/client/features/jobs/jobsList.controller.js index 3881a4071c..922212965e 100644 --- a/awx/ui/client/features/jobs/jobsList.controller.js +++ b/awx/ui/client/features/jobs/jobsList.controller.js @@ -64,13 +64,13 @@ function ListJobsController ( { label: `${strings.get('sort.NAME_ASCENDING')}`, value: 'name' }, { label: `${strings.get('sort.NAME_DESCENDING')}`, value: '-name' }, { label: `${strings.get('sort.FINISH_TIME_ASCENDING')}`, value: 'finished' }, + toolbarSortDefault, { label: `${strings.get('sort.START_TIME_ASCENDING')}`, value: 'started' }, { label: `${strings.get('sort.START_TIME_DESCENDING')}`, value: '-started' }, { label: `${strings.get('sort.LAUNCHED_BY_ASCENDING')}`, value: 'created_by__id' }, { label: `${strings.get('sort.LAUNCHED_BY_DESCENDING')}`, value: '-created_by__id' }, { label: `${strings.get('sort.PROJECT_ASCENDING')}`, value: 'unified_job_template__project__id' }, - { label: `${strings.get('sort.PROJECT_DESCENDING')}`, value: '-unified_job_template__project__id' }, - toolbarSortDefault + { label: `${strings.get('sort.PROJECT_DESCENDING')}`, value: '-unified_job_template__project__id' } ]; vm.toolbarSortValue = toolbarSortDefault; diff --git a/awx/ui/client/src/inventories-hosts/hosts/related/groups/hosts-related-groups.list.js b/awx/ui/client/src/inventories-hosts/hosts/related/groups/hosts-related-groups.list.js index ee79c9680a..f54c700063 100644 --- a/awx/ui/client/src/inventories-hosts/hosts/related/groups/hosts-related-groups.list.js +++ b/awx/ui/client/src/inventories-hosts/hosts/related/groups/hosts-related-groups.list.js @@ -15,7 +15,7 @@ export default ['i18n', function(i18n) { hover: true, trackBy: 'group.id', basePath: 'api/v2/hosts/{{$stateParams.host_id}}/groups/', - layoutClass: 'List-staticColumnLayout--groups', + layoutClass: 'List-staticColumnLayout--statusOrCheckbox', staticColumns: [ { field: 'failed_hosts', diff --git a/awx/ui/client/src/shared/smart-search/queryset.service.js b/awx/ui/client/src/shared/smart-search/queryset.service.js index 2db940b94c..216045eee3 100644 --- a/awx/ui/client/src/shared/smart-search/queryset.service.js +++ b/awx/ui/client/src/shared/smart-search/queryset.service.js @@ -1,7 +1,5 @@ function searchWithoutKey (term, singleSearchParam = null) { - if (singleSearchParam === 'host_filter') { - return { [singleSearchParam]: `${encodeURIComponent(term)}` }; - } else if (singleSearchParam) { + if (singleSearchParam) { return { [singleSearchParam]: `search=${encodeURIComponent(term)}` }; } return { search: encodeURIComponent(term) }; @@ -418,7 +416,11 @@ function QuerysetService ($q, Rest, ProcessErrors, $rootScope, Wait, DjangoSearc let termParams; if (termParts.length === 1) { - termParams = searchWithoutKey(term, singleSearchParam); + if (singleSearchParam && termParts[0].toLowerCase() === "or") { + termParams = { [singleSearchParam]: "or" }; + } else { + termParams = searchWithoutKey(term, singleSearchParam); + } } else if ((isAnsibleFactField && isAnsibleFactField(termParts)) || (isFilterableBaseField && isFilterableBaseField(termParts))) { termParams = this.encodeParam({ term, singleSearchParam, searchTerm: true }); } else if (isRelatedField && isRelatedField(termParts)) { diff --git a/awx/ui/test/spec/smart-search/queryset.service-test.js b/awx/ui/test/spec/smart-search/queryset.service-test.js index eb8563c37d..a2771f9344 100644 --- a/awx/ui/test/spec/smart-search/queryset.service-test.js +++ b/awx/ui/test/spec/smart-search/queryset.service-test.js @@ -63,11 +63,22 @@ describe('Service: QuerySet', () => { spyOn(QuerySet, 'encodeParam').and.callThrough(); const term = 'name:foo'; - const isFilterableBaseField = () => true; + const isFilterableBaseField = (termParts) => termParts[0] === 'name'; const isRelatedField = () => false; expect(QuerySet.getSearchInputQueryset(term, isFilterableBaseField, isRelatedField)).toEqual({ name__icontains_DEFAULT: 'foo' }); expect(QuerySet.encodeParam).toHaveBeenCalledWith({ term: "name:foo", searchTerm: true, singleSearchParam: null }); + expect(QuerySet.getSearchInputQueryset('foo', isFilterableBaseField, null, null, 'host_filter')).toEqual({ host_filter: 'search=foo' }); + expect(QuerySet.getSearchInputQueryset('foo bar', isFilterableBaseField, null, null, 'host_filter')).toEqual({ host_filter: 'search=foo%20and%20search=bar' }); + expect(QuerySet.getSearchInputQueryset('foo or bar', isFilterableBaseField, null, null, 'host_filter')).toEqual({ host_filter: 'search=foo%20or%20search=bar' }); + expect(QuerySet.getSearchInputQueryset('name:foo or bar', isFilterableBaseField, null, null, 'host_filter')).toEqual({ host_filter: 'name__icontains=foo%20or%20search=bar' }); + expect(QuerySet.getSearchInputQueryset('name:foo bar', isFilterableBaseField, null, null, 'host_filter')).toEqual({ host_filter: 'name__icontains=foo%20and%20search=bar' }); + expect(QuerySet.getSearchInputQueryset('foo or name:bar', isFilterableBaseField, null, null, 'host_filter')).toEqual({ host_filter: 'search=foo%20or%20name__icontains=bar' }); + expect(QuerySet.getSearchInputQueryset('foo name:bar', isFilterableBaseField, null, null, 'host_filter')).toEqual({ host_filter: 'search=foo%20and%20name__icontains=bar' }); + expect(QuerySet.getSearchInputQueryset('name:foo or name:bar', isFilterableBaseField, null, null, 'host_filter')).toEqual({ host_filter: 'name__icontains=foo%20or%20name__icontains=bar' }); + expect(QuerySet.getSearchInputQueryset('name:foo name:bar', isFilterableBaseField, null, null, 'host_filter')).toEqual({ host_filter: 'name__icontains=foo%20and%20name__icontains=bar' }); + expect(QuerySet.getSearchInputQueryset('name:foo name:bar or baz', isFilterableBaseField, null, null, 'host_filter')).toEqual({ host_filter: 'name__icontains=foo%20and%20name__icontains=bar%20or%20search=baz' }); + expect(QuerySet.getSearchInputQueryset('baz or name:foo name:bar', isFilterableBaseField, null, null, 'host_filter')).toEqual({ host_filter: 'search=baz%20or%20name__icontains=foo%20and%20name__icontains=bar' }); }); });