mirror of
https://github.com/ansible/awx.git
synced 2026-03-20 18:37:39 -02:30
move search into feature-level component
This commit is contained in:
@@ -1,9 +1,7 @@
|
|||||||
let $compile;
|
let $compile;
|
||||||
let $q;
|
let $q;
|
||||||
let $scope;
|
let $scope;
|
||||||
let $state;
|
|
||||||
let page;
|
let page;
|
||||||
let qs;
|
|
||||||
let render;
|
let render;
|
||||||
let resource;
|
let resource;
|
||||||
let scroll;
|
let scroll;
|
||||||
@@ -21,8 +19,6 @@ function JobsIndexController (
|
|||||||
_$scope_,
|
_$scope_,
|
||||||
_$compile_,
|
_$compile_,
|
||||||
_$q_,
|
_$q_,
|
||||||
_$state_,
|
|
||||||
_qs_,
|
|
||||||
_status_,
|
_status_,
|
||||||
) {
|
) {
|
||||||
vm = this || {};
|
vm = this || {};
|
||||||
@@ -50,24 +46,6 @@ function JobsIndexController (
|
|||||||
vm.resource = resource;
|
vm.resource = resource;
|
||||||
vm.title = resource.model.get('name');
|
vm.title = resource.model.get('name');
|
||||||
|
|
||||||
// Search
|
|
||||||
$state = _$state_;
|
|
||||||
qs = _qs_;
|
|
||||||
|
|
||||||
vm.search = {
|
|
||||||
clearSearch,
|
|
||||||
searchKeyExamples,
|
|
||||||
searchKeyFields,
|
|
||||||
toggleSearchKey,
|
|
||||||
removeSearchTag,
|
|
||||||
submitSearch,
|
|
||||||
value: '',
|
|
||||||
key: false,
|
|
||||||
rejected: false,
|
|
||||||
disabled: !resource.model.get('finished'),
|
|
||||||
tags: getSearchTags(getCurrentQueryset()),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Stdout Navigation
|
// Stdout Navigation
|
||||||
vm.scroll = {
|
vm.scroll = {
|
||||||
showBackToTop: false,
|
showBackToTop: false,
|
||||||
@@ -111,13 +89,9 @@ function init () {
|
|||||||
onStart () {
|
onStart () {
|
||||||
status.resetCounts();
|
status.resetCounts();
|
||||||
status.setJobStatus('running');
|
status.setJobStatus('running');
|
||||||
|
|
||||||
vm.search.disabled = true;
|
|
||||||
},
|
},
|
||||||
onStop () {
|
onStop () {
|
||||||
status.updateStats();
|
status.updateStats();
|
||||||
|
|
||||||
vm.search.disabled = false;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -346,63 +320,6 @@ function toggle (uuid, menu) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// Search
|
|
||||||
//
|
|
||||||
|
|
||||||
const searchReloadOptions = { reload: true, inherit: false };
|
|
||||||
const searchKeyExamples = ['id:>1', 'task:set', 'created:>=2000-01-01'];
|
|
||||||
const searchKeyFields = ['changed', 'failed', 'host_name', 'stdout', 'task', 'role', 'playbook', 'play'];
|
|
||||||
|
|
||||||
function toggleSearchKey () {
|
|
||||||
vm.search.key = !vm.search.key;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getCurrentQueryset () {
|
|
||||||
const { job_event_search } = $state.params; // eslint-disable-line camelcase
|
|
||||||
|
|
||||||
return qs.decodeArr(job_event_search);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getSearchTags (queryset) {
|
|
||||||
return qs.createSearchTagsFromQueryset(queryset)
|
|
||||||
.filter(tag => !tag.startsWith('event'))
|
|
||||||
.filter(tag => !tag.startsWith('-event'))
|
|
||||||
.filter(tag => !tag.startsWith('page_size'))
|
|
||||||
.filter(tag => !tag.startsWith('order_by'));
|
|
||||||
}
|
|
||||||
|
|
||||||
function removeSearchTag (index) {
|
|
||||||
const searchTerm = vm.search.tags[index];
|
|
||||||
|
|
||||||
const currentQueryset = getCurrentQueryset();
|
|
||||||
const modifiedQueryset = qs.removeTermsFromQueryset(currentQueryset, searchTerm);
|
|
||||||
|
|
||||||
vm.search.tags = getSearchTags(modifiedQueryset);
|
|
||||||
|
|
||||||
$state.params.job_event_search = qs.encodeArr(modifiedQueryset);
|
|
||||||
$state.transitionTo($state.current, $state.params, searchReloadOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
function submitSearch () {
|
|
||||||
const searchInputQueryset = qs.getSearchInputQueryset(vm.search.value);
|
|
||||||
|
|
||||||
const currentQueryset = getCurrentQueryset();
|
|
||||||
const modifiedQueryset = qs.mergeQueryset(currentQueryset, searchInputQueryset);
|
|
||||||
|
|
||||||
vm.search.tags = getSearchTags(modifiedQueryset);
|
|
||||||
|
|
||||||
$state.params.job_event_search = qs.encodeArr(modifiedQueryset);
|
|
||||||
$state.transitionTo($state.current, $state.params, searchReloadOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
function clearSearch () {
|
|
||||||
vm.search.tags = [];
|
|
||||||
|
|
||||||
$state.params.job_event_search = '';
|
|
||||||
$state.transitionTo($state.current, $state.params, searchReloadOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
JobsIndexController.$inject = [
|
JobsIndexController.$inject = [
|
||||||
'resource',
|
'resource',
|
||||||
'JobPageService',
|
'JobPageService',
|
||||||
@@ -412,8 +329,6 @@ JobsIndexController.$inject = [
|
|||||||
'$scope',
|
'$scope',
|
||||||
'$compile',
|
'$compile',
|
||||||
'$q',
|
'$q',
|
||||||
'$state',
|
|
||||||
'QuerySet',
|
|
||||||
'JobStatusService',
|
'JobStatusService',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import EngineService from '~features/output/engine.service';
|
|||||||
import StatusService from '~features/output/status.service';
|
import StatusService from '~features/output/status.service';
|
||||||
|
|
||||||
import DetailsDirective from '~features/output/details.directive';
|
import DetailsDirective from '~features/output/details.directive';
|
||||||
import SearchKeyDirective from '~features/output/search-key.directive';
|
import SearchDirective from '~features/output/search.directive';
|
||||||
import StatsDirective from '~features/output/stats.directive';
|
import StatsDirective from '~features/output/stats.directive';
|
||||||
|
|
||||||
const Template = require('~features/output/index.view.html');
|
const Template = require('~features/output/index.view.html');
|
||||||
@@ -220,7 +220,7 @@ angular
|
|||||||
.service('JobEventEngine', EngineService)
|
.service('JobEventEngine', EngineService)
|
||||||
.service('JobStatusService', StatusService)
|
.service('JobStatusService', StatusService)
|
||||||
.directive('atJobDetails', DetailsDirective)
|
.directive('atJobDetails', DetailsDirective)
|
||||||
.directive('atSearchKey', SearchKeyDirective)
|
.directive('atJobSearch', SearchDirective)
|
||||||
.directive('atJobStats', StatsDirective)
|
.directive('atJobStats', StatsDirective)
|
||||||
.run(JobsRun);
|
.run(JobsRun);
|
||||||
|
|
||||||
|
|||||||
@@ -9,55 +9,8 @@
|
|||||||
<at-panel class="at-Stdout">
|
<at-panel class="at-Stdout">
|
||||||
<div class="at-Panel-headingTitle">{{ vm.title }}</div>
|
<div class="at-Panel-headingTitle">{{ vm.title }}</div>
|
||||||
<at-job-stats resource="vm.resource"></at-job-stats>
|
<at-job-stats resource="vm.resource"></at-job-stats>
|
||||||
<!-- search ===================================================================================== -->
|
<at-job-search></at-job-search>
|
||||||
<form ng-submit="vm.search.submitSearch()">
|
|
||||||
<div class="input-group">
|
|
||||||
<input type="text"
|
|
||||||
class="form-control at-Input"
|
|
||||||
ng-class="{ 'at-Input--rejected': vm.search.rejected }"
|
|
||||||
ng-model="vm.search.value"
|
|
||||||
ng-attr-placeholder="{{ vm.search.disabled ? 'CANNOT SEARCH RUNNING JOB' : 'SEARCH' }}"
|
|
||||||
ng-disabled="vm.search.disabled">
|
|
||||||
<span class="input-group-btn">
|
|
||||||
<button class="btn at-ButtonHollow--default at-Input-button"
|
|
||||||
ng-click="vm.search.submitSearch()"
|
|
||||||
ng-disabled="vm.search.disabled"
|
|
||||||
type="button">
|
|
||||||
<i class="fa fa-search"></i>
|
|
||||||
</button>
|
|
||||||
<button class="btn jobz-Button-searchKey"
|
|
||||||
ng-if="vm.search.key"
|
|
||||||
ng-disabled="vm.search.disabled"
|
|
||||||
ng-click="vm.search.toggleSearchKey()"
|
|
||||||
type="button"> key
|
|
||||||
</button>
|
|
||||||
<button class="btn at-ButtonHollow--default at-Input-button"
|
|
||||||
ng-if="!vm.search.key"
|
|
||||||
ng-disabled="vm.search.disabled"
|
|
||||||
ng-click="vm.search.toggleSearchKey()"
|
|
||||||
type="button"> key
|
|
||||||
</button>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<div class="jobz-tagz">
|
|
||||||
<div class="LabelList-tagContainer" ng-repeat="tag in vm.search.tags track by $index">
|
|
||||||
<div class="LabelList-tag LabelList-tag--deletable"><span class="LabelList-name">{{ tag }}</span></div>
|
|
||||||
<div class="LabelList-deleteContainer" ng-click="vm.search.removeSearchTag($index)">
|
|
||||||
<i class="fa fa-times LabelList-tagDelete"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div><a href class="jobz-searchClearAll" ng-click="vm.search.clearSearch()" ng-show="!(vm.search.tags | isEmpty)">CLEAR ALL</a></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<at-search-key
|
|
||||||
ng-show="vm.search.key"
|
|
||||||
fields="vm.search.searchKeyFields"
|
|
||||||
examples="vm.search.searchKeyExamples">
|
|
||||||
</at-search-key>
|
|
||||||
|
|
||||||
<!-- ============================================================================================ -->
|
|
||||||
<div class="at-Stdout-menuTop">
|
<div class="at-Stdout-menuTop">
|
||||||
<div class="pull-left" ng-click="vm.expand()">
|
<div class="pull-left" ng-click="vm.expand()">
|
||||||
<i class="at-Stdout-menuIcon fa"
|
<i class="at-Stdout-menuIcon fa"
|
||||||
|
|||||||
@@ -1,37 +0,0 @@
|
|||||||
const templateUrl = require('~features/output/search-key.partial.html');
|
|
||||||
|
|
||||||
function atSearchKeyLink (scope, el, attrs, controllers) {
|
|
||||||
const [atSearchKeyController] = controllers;
|
|
||||||
|
|
||||||
atSearchKeyController.init(scope);
|
|
||||||
}
|
|
||||||
|
|
||||||
function AtSearchKeyController () {
|
|
||||||
const vm = this || {};
|
|
||||||
|
|
||||||
vm.init = scope => {
|
|
||||||
vm.examples = scope.examples || [];
|
|
||||||
vm.fields = scope.fields || [];
|
|
||||||
vm.relatedFields = scope.relatedFields || [];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
AtSearchKeyController.$inject = ['$scope'];
|
|
||||||
|
|
||||||
function atSearchKey () {
|
|
||||||
return {
|
|
||||||
templateUrl,
|
|
||||||
restrict: 'E',
|
|
||||||
require: ['atSearchKey'],
|
|
||||||
controllerAs: 'vm',
|
|
||||||
link: atSearchKeyLink,
|
|
||||||
controller: AtSearchKeyController,
|
|
||||||
scope: {
|
|
||||||
examples: '=',
|
|
||||||
fields: '=',
|
|
||||||
relatedFields: '=',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export default atSearchKey;
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
<!-- todo: styling, css etc. - disposition according to project lib conventions -->
|
|
||||||
<div class="jobz-searchKeyPaneContainer">
|
|
||||||
<div class="jobz-searchKeyPane">
|
|
||||||
<div class="SmartSearch-keyRow">
|
|
||||||
<div class="SmartSearch-examples">
|
|
||||||
<div class="SmartSearch-examples--title"><b>EXAMPLES:</b></div>
|
|
||||||
<div class="SmartSearch-examples--search" ng-repeat="tag in vm.examples"> {{ tag }}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="SmartSearch-keyRow">
|
|
||||||
<b>FIELDS:</b>
|
|
||||||
<span ng-repeat="field in vm.fields">{{ field }}<span ng-if="!$last">, </span></span>
|
|
||||||
</div>
|
|
||||||
<div class="SmartSearch-keyRow">
|
|
||||||
<b>ADDITIONAL INFORMATION:</b>
|
|
||||||
For additional information on advanced search search syntax please see the Ansible Tower
|
|
||||||
<a ng-attr-href="undefined" target="_blank">documentation</a>.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
119
awx/ui/client/features/output/search.directive.js
Normal file
119
awx/ui/client/features/output/search.directive.js
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
const templateUrl = require('~features/output/search.partial.html');
|
||||||
|
|
||||||
|
const searchReloadOptions = { reload: true, inherit: false };
|
||||||
|
const searchKeyExamples = ['id:>1', 'task:set', 'created:>=2000-01-01'];
|
||||||
|
const searchKeyFields = ['changed', 'failed', 'host_name', 'stdout', 'task', 'role', 'playbook', 'play'];
|
||||||
|
|
||||||
|
let $state;
|
||||||
|
let status;
|
||||||
|
let qs;
|
||||||
|
|
||||||
|
let vm;
|
||||||
|
|
||||||
|
function toggleSearchKey () {
|
||||||
|
vm.key = !vm.key;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCurrentQueryset () {
|
||||||
|
const { job_event_search } = $state.params; // eslint-disable-line camelcase
|
||||||
|
|
||||||
|
return qs.decodeArr(job_event_search);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSearchTags (queryset) {
|
||||||
|
return qs.createSearchTagsFromQueryset(queryset)
|
||||||
|
.filter(tag => !tag.startsWith('event'))
|
||||||
|
.filter(tag => !tag.startsWith('-event'))
|
||||||
|
.filter(tag => !tag.startsWith('page_size'))
|
||||||
|
.filter(tag => !tag.startsWith('order_by'));
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeSearchTag (index) {
|
||||||
|
const searchTerm = vm.tags[index];
|
||||||
|
|
||||||
|
const currentQueryset = getCurrentQueryset();
|
||||||
|
const modifiedQueryset = qs.removeTermsFromQueryset(currentQueryset, searchTerm);
|
||||||
|
|
||||||
|
vm.tags = getSearchTags(modifiedQueryset);
|
||||||
|
|
||||||
|
$state.params.job_event_search = qs.encodeArr(modifiedQueryset);
|
||||||
|
$state.transitionTo($state.current, $state.params, searchReloadOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
function submitSearch () {
|
||||||
|
const searchInputQueryset = qs.getSearchInputQueryset(vm.value);
|
||||||
|
|
||||||
|
const currentQueryset = getCurrentQueryset();
|
||||||
|
const modifiedQueryset = qs.mergeQueryset(currentQueryset, searchInputQueryset);
|
||||||
|
|
||||||
|
vm.tags = getSearchTags(modifiedQueryset);
|
||||||
|
|
||||||
|
$state.params.job_event_search = qs.encodeArr(modifiedQueryset);
|
||||||
|
$state.transitionTo($state.current, $state.params, searchReloadOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearSearch () {
|
||||||
|
vm.tags = [];
|
||||||
|
|
||||||
|
$state.params.job_event_search = '';
|
||||||
|
$state.transitionTo($state.current, $state.params, searchReloadOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
function atJobSearchLink (scope, el, attrs, controllers) {
|
||||||
|
const [atJobSearchController] = controllers;
|
||||||
|
|
||||||
|
atJobSearchController.init(scope);
|
||||||
|
}
|
||||||
|
|
||||||
|
function AtJobSearchController (_$state_, _status_, _qs_) {
|
||||||
|
$state = _$state_;
|
||||||
|
status = _status_;
|
||||||
|
qs = _qs_;
|
||||||
|
|
||||||
|
vm = this || {};
|
||||||
|
|
||||||
|
vm.value = '';
|
||||||
|
vm.key = false;
|
||||||
|
vm.rejected = false;
|
||||||
|
vm.disabled = true;
|
||||||
|
vm.tags = getSearchTags(getCurrentQueryset());
|
||||||
|
|
||||||
|
vm.clearSearch = clearSearch;
|
||||||
|
vm.searchKeyExamples = searchKeyExamples;
|
||||||
|
vm.searchKeyFields = searchKeyFields;
|
||||||
|
vm.toggleSearchKey = toggleSearchKey;
|
||||||
|
vm.removeSearchTag = removeSearchTag;
|
||||||
|
vm.submitSearch = submitSearch;
|
||||||
|
|
||||||
|
vm.init = scope => {
|
||||||
|
vm.examples = scope.examples || searchKeyExamples;
|
||||||
|
vm.fields = scope.fields || searchKeyFields;
|
||||||
|
vm.relatedFields = scope.relatedFields || [];
|
||||||
|
|
||||||
|
scope.$watch(status.isRunning, value => { vm.disabled = value; });
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
AtJobSearchController.$inject = [
|
||||||
|
'$state',
|
||||||
|
'JobStatusService',
|
||||||
|
'QuerySet',
|
||||||
|
];
|
||||||
|
|
||||||
|
function atJobSearch () {
|
||||||
|
return {
|
||||||
|
templateUrl,
|
||||||
|
restrict: 'E',
|
||||||
|
require: ['atJobSearch'],
|
||||||
|
controllerAs: 'vm',
|
||||||
|
link: atJobSearchLink,
|
||||||
|
controller: AtJobSearchController,
|
||||||
|
scope: {
|
||||||
|
examples: '=',
|
||||||
|
fields: '=',
|
||||||
|
relatedFields: '=',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default atJobSearch;
|
||||||
61
awx/ui/client/features/output/search.partial.html
Normal file
61
awx/ui/client/features/output/search.partial.html
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
<!-- todo: styling, css etc. - disposition according to project lib conventions -->
|
||||||
|
<form ng-submit="vm.submitSearch()">
|
||||||
|
<div class="input-group">
|
||||||
|
<input type="text"
|
||||||
|
class="form-control at-Input"
|
||||||
|
ng-class="{ 'at-Input--rejected': vm.rejected }"
|
||||||
|
ng-model="vm.value"
|
||||||
|
ng-attr-placeholder="{{ vm.disabled ? 'CANNOT SEARCH RUNNING JOB' : 'SEARCH' }}"
|
||||||
|
ng-disabled="vm.disabled">
|
||||||
|
<span class="input-group-btn">
|
||||||
|
<button class="btn at-ButtonHollow--default at-Input-button"
|
||||||
|
ng-click="vm.submitSearch()"
|
||||||
|
ng-disabled="vm.disabled"
|
||||||
|
type="button">
|
||||||
|
<i class="fa fa-search"></i>
|
||||||
|
</button>
|
||||||
|
<button class="btn jobz-Button-searchKey"
|
||||||
|
ng-if="vm.key"
|
||||||
|
ng-disabled="vm.disabled"
|
||||||
|
ng-click="vm.toggleSearchKey()"
|
||||||
|
type="button"> key
|
||||||
|
</button>
|
||||||
|
<button class="btn at-ButtonHollow--default at-Input-button"
|
||||||
|
ng-if="!vm.key"
|
||||||
|
ng-disabled="vm.disabled"
|
||||||
|
ng-click="vm.toggleSearchKey()"
|
||||||
|
type="button"> key
|
||||||
|
</button>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div class="jobz-tagz">
|
||||||
|
<div class="LabelList-tagContainer" ng-repeat="tag in vm.tags track by $index">
|
||||||
|
<div class="LabelList-tag LabelList-tag--deletable"><span class="LabelList-name">{{ tag }}</span></div>
|
||||||
|
<div class="LabelList-deleteContainer" ng-click="vm.removeSearchTag($index)">
|
||||||
|
<i class="fa fa-times LabelList-tagDelete"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div><a href class="jobz-searchClearAll" ng-click="vm.clearSearch()" ng-show="!(vm.tags | isEmpty)">CLEAR ALL</a></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="jobz-searchKeyPaneContainer" ng-show="vm.key">
|
||||||
|
<div class="jobz-searchKeyPane">
|
||||||
|
<div class="SmartSearch-keyRow">
|
||||||
|
<div class="SmartSearch-examples">
|
||||||
|
<div class="SmartSearch-examples--title"><b>EXAMPLES:</b></div>
|
||||||
|
<div class="SmartSearch-examples--search" ng-repeat="tag in vm.examples"> {{ tag }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="SmartSearch-keyRow">
|
||||||
|
<b>FIELDS:</b>
|
||||||
|
<span ng-repeat="field in vm.fields">{{ field }}<span ng-if="!$last">, </span></span>
|
||||||
|
</div>
|
||||||
|
<div class="SmartSearch-keyRow">
|
||||||
|
<b>ADDITIONAL INFORMATION:</b>
|
||||||
|
For additional information on advanced search search syntax please see the Ansible Tower
|
||||||
|
<a ng-attr-href="undefined" target="_blank">documentation</a>.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
Reference in New Issue
Block a user