Merge pull request #4976 from mabashian/launch-job-with-prompts

Launch job with prompts
This commit is contained in:
Michael Abashian
2017-01-27 10:44:56 -05:00
committed by GitHub
24 changed files with 355 additions and 160 deletions

View File

@@ -25,8 +25,7 @@
label: 'organization', label: 'organization',
ngBind: 'team.summary_fields.organization.name', ngBind: 'team.summary_fields.organization.name',
sourceModel: 'organization', sourceModel: 'organization',
sourceField: 'name', sourceField: 'name'
searchable: true
} }
} }

View File

@@ -42,8 +42,7 @@ export default [ 'i18n', function(i18n){
sourceModel: 'inventory', sourceModel: 'inventory',
sourceField: 'name', sourceField: 'name',
columnClass: 'col-lg-5 col-md-4 col-sm-4 hidden-xs elllipsis', columnClass: 'col-lg-5 col-md-4 col-sm-4 hidden-xs elllipsis',
linkTo: "{{ '/#/inventories/' + host.inventory_id }}", linkTo: "{{ '/#/inventories/' + host.inventory_id }}"
searchable: false
}, },
enabled: { enabled: {
label: i18n._('Status'), label: i18n._('Status'),

View File

@@ -461,15 +461,13 @@ export default
label: i18n._('Role'), label: i18n._('Role'),
type: 'role', type: 'role',
noSort: true, noSort: true,
class: 'col-lg-4 col-md-4 col-sm-4 col-xs-4', class: 'col-lg-4 col-md-4 col-sm-4 col-xs-4'
searchable: false
}, },
team_roles: { team_roles: {
label: i18n._('Team Roles'), label: i18n._('Team Roles'),
type: 'team_roles', type: 'team_roles',
noSort: true, noSort: true,
class: 'col-lg-5 col-md-5 col-sm-5 col-xs-4', class: 'col-lg-5 col-md-5 col-sm-5 col-xs-4'
searchable: false
} }
} }
} }

View File

@@ -88,15 +88,13 @@ export default
label: i18n._('Role'), label: i18n._('Role'),
type: 'role', type: 'role',
noSort: true, noSort: true,
class: 'col-lg-4 col-md-4 col-sm-4 col-xs-4', class: 'col-lg-4 col-md-4 col-sm-4 col-xs-4'
searchable: false
}, },
team_roles: { team_roles: {
label: i18n._('Team Roles'), label: i18n._('Team Roles'),
type: 'team_roles', type: 'team_roles',
noSort: true, noSort: true,
class: 'col-lg-5 col-md-5 col-sm-5 col-xs-4', class: 'col-lg-5 col-md-5 col-sm-5 col-xs-4'
searchable: false
} }
} }
}, },

View File

@@ -98,8 +98,7 @@ export default
label: i18n._('Role'), label: i18n._('Role'),
type: 'role', type: 'role',
noSort: true, noSort: true,
class: 'col-lg-4 col-md-4 col-sm-4 col-xs-4', class: 'col-lg-4 col-md-4 col-sm-4 col-xs-4'
searchable: false
} }
} }
}, },

View File

@@ -63,9 +63,11 @@
export default export default
[ '$scope', '$location', 'GetBasePath', 'Empty', 'Wait', 'Rest', 'ProcessErrors', [ '$scope', '$location', 'GetBasePath', 'Empty', 'Wait', 'Rest', 'ProcessErrors',
'LaunchJob', '$state', 'generateList', 'InventoryList', 'CredentialList', 'ParseTypeChange', 'GetSurveyQuestions', 'LaunchJob', '$state', 'generateList', 'InventoryList', 'CredentialList', 'ParseTypeChange',
'GetSurveyQuestions',
function($scope, $location, GetBasePath, Empty, Wait, Rest, ProcessErrors, function($scope, $location, GetBasePath, Empty, Wait, Rest, ProcessErrors,
LaunchJob, $state, GenerateList, InventoryList, CredentialList, ParseTypeChange, GetSurveyQuestions) { LaunchJob, $state, GenerateList, InventoryList, CredentialList, ParseTypeChange,
GetSurveyQuestions) {
var launch_url; var launch_url;
@@ -296,100 +298,10 @@ export default
$scope.getListsAndSurvey = function() { $scope.getListsAndSurvey = function() {
if($scope.ask_inventory_on_launch) { if($scope.ask_inventory_on_launch) {
// @issue: OLD SEARCH $scope.includeInventoryList = true;
// var inventory_url = GetBasePath('inventory');
var invList = _.cloneDeep(InventoryList);
invList.fields.status.searchable = false;
invList.fields.organization.searchable = false;
invList.fields.has_inventory_sources.searchable = false;
invList.fields.has_active_failures.searchable = false;
invList.fields.inventory_sources_with_failures.searchable = false;
GenerateList.inject(invList, {
mode: 'lookup',
id: 'job-submission-inventory-lookup',
scope: $scope,
input_type: 'radio'
});
// @issue: OLD SEARCH
// SearchInit({
// scope: $scope,
// set: InventoryList.name,
// list: InventoryList,
// url: inventory_url
// });
//
// PaginateInit({
// scope: $scope,
// list: InventoryList,
// url: inventory_url,
// mode: 'lookup'
// });
//
// $scope.search(InventoryList.iterator);
$scope.$watchCollection('inventories', function () {
if($scope.selected_inventory) {
// Loop across the inventories and see if one of them should be "checked"
$scope.inventories.forEach(function(row, i) {
if (row.id === $scope.selected_inventory.id) {
$scope.inventories[i].checked = 1;
}
else {
$scope.inventories[i].checked = 0;
}
});
}
});
} }
if($scope.ask_credential_on_launch) { if($scope.ask_credential_on_launch) {
// @issue: OLD SEARCH $scope.includeCredentialList = true;
// var credential_url = GetBasePath('credentials') + '?kind=ssh';
var credList = _.cloneDeep(CredentialList);
credList.basePath = GetBasePath('credentials') + '?kind=ssh';
credList.fields.description.searchable = false;
credList.fields.kind.searchable = false;
GenerateList.inject(credList, {
mode: 'lookup',
id: 'job-submission-credential-lookup',
scope: $scope,
input_type: 'radio'
});
// @issue: OLD SEARCH
// SearchInit({
// scope: $scope,
// set: CredentialList.name,
// list: CredentialList,
// url: credential_url
// });
//
// PaginateInit({
// scope: $scope,
// list: CredentialList,
// url: credential_url,
// mode: 'lookup'
// });
//
// $scope.search(CredentialList.iterator);
$scope.$watchCollection('credentials', function () {
if($scope.selected_credential) {
// Loop across the inventories and see if one of them should be "checked"
$scope.credentials.forEach(function(row, i) {
if (row.id === $scope.selected_credential.id) {
$scope.credentials[i].checked = 1;
}
else {
$scope.credentials[i].checked = 0;
}
});
}
});
} }
if($scope.survey_enabled) { if($scope.survey_enabled) {
GetSurveyQuestions({ GetSurveyQuestions({
@@ -562,5 +474,14 @@ export default
$scope.parseTypeChange('parseType', 'jobLaunchVariables'); $scope.parseTypeChange('parseType', 'jobLaunchVariables');
}; };
$scope.$on('inventorySelected', function(evt, selectedRow){
$scope.selected_inventory = _.cloneDeep(selectedRow);
});
$scope.$on('credentialSelected', function(evt, selectedRow){
$scope.selected_credential = _.cloneDeep(selectedRow);
updateRequiredPasswords();
});
} }
]; ];

View File

@@ -29,7 +29,7 @@
<button class="btn btn-xs JobSubmission-revertButton" ng-hide="selected_inventory.id === defaults.inventory.id" ng-click="revertToDefaultInventory()">REVERT TO DEFAULT</button> <button class="btn btn-xs JobSubmission-revertButton" ng-hide="selected_inventory.id === defaults.inventory.id" ng-click="revertToDefaultInventory()">REVERT TO DEFAULT</button>
</div> </div>
</div> </div>
<div id="job-submission-inventory-lookup"></div> <job-sub-inv-list ng-if="includeInventoryList"></job-sub-inv-list>
</div> </div>
</div> </div>
<div ng-if="ask_credential_on_launch || password_needed" ng-show="step === 'credential'" class="JobSubmission-form"> <div ng-if="ask_credential_on_launch || password_needed" ng-show="step === 'credential'" class="JobSubmission-form">
@@ -44,7 +44,7 @@
<button class="btn btn-xs JobSubmission-revertButton" ng-hide="selected_credential.id === defaults.credential.id" ng-click="revertToDefaultCredential()">REVERT TO DEFAULT</button> <button class="btn btn-xs JobSubmission-revertButton" ng-hide="selected_credential.id === defaults.credential.id" ng-click="revertToDefaultCredential()">REVERT TO DEFAULT</button>
</div> </div>
</div> </div>
<div id="job-submission-credential-lookup"></div> <job-sub-cred-list ng-if="includeCredentialList"></job-sub-cred-list>
<div ng-show="ssh_password_required || ssh_key_unlock_required || become_password_required || vault_password_required"> <div ng-show="ssh_password_required || ssh_key_unlock_required || become_password_required || vault_password_required">
<div class="JobSubmission-instructions">Launching this job requires the passwords listed below. Enter and confirm each password before continuing.</div> <div class="JobSubmission-instructions">Launching this job requires the passwords listed below. Enter and confirm each password before continuing.</div>
<form name="forms.credentialpasswords" autocomplete="off" novalidate> <form name="forms.credentialpasswords" autocomplete="off" novalidate>

View File

@@ -0,0 +1,32 @@
/*************************************************
* Copyright (c) 2017 Ansible, Inc.
*
* All Rights Reserved
*************************************************/
export default
[ '$scope',
function($scope) {
$scope.toggle_row = function(rowId) {
let list = $scope.list;
let count = 0;
$scope[list.name].forEach(function(row) {
if (row.id === rowId) {
if (row.checked) {
row.success_class = 'success';
} else {
row.checked = true;
row.success_class = '';
}
$scope.$emit('credentialSelected', row);
} else {
row.checked = 0;
row.success_class = '';
}
if (row.checked) {
count++;
}
});
};
}
];

View File

@@ -0,0 +1,63 @@
/*************************************************
* Copyright (c) 2016 Ansible, Inc.
*
* All Rights Reserved
*************************************************/
import jobSubCredListController from './job-sub-cred-list.controller';
export default [ 'templateUrl', 'QuerySet', 'GetBasePath', 'generateList', '$compile', 'CredentialList',
function(templateUrl, qs, GetBasePath, GenerateList, $compile, CredentialList) {
return {
scope: {},
templateUrl: templateUrl('job-submission/lists/credential/job-sub-cred-list'),
controller: jobSubCredListController,
restrict: 'E',
link: function(scope) {
scope.credential_default_params = {
order_by: 'name',
page_size: 5,
kind: 'ssh'
};
scope.credential_queryset = {
order_by: 'name',
page_size: 5,
kind: 'ssh'
};
// Fire off the initial search
qs.search(GetBasePath('credentials'), scope.credential_default_params)
.then(function(res) {
scope.credential_dataset = res.data;
scope.credentials = scope.credential_dataset.results;
var credList = _.cloneDeep(CredentialList);
let html = GenerateList.build({
list: credList,
input_type: 'radio',
mode: 'lookup'
});
scope.list = credList;
$('#job-submission-credential-lookup').append($compile(html)(scope));
scope.$watchCollection('credentials', function () {
if(scope.selected_credential) {
// Loop across the inventories and see if one of them should be "checked"
scope.credentials.forEach(function(row, i) {
if (row.id === scope.selected_credential.id) {
scope.credentials[i].checked = 1;
}
else {
scope.credentials[i].checked = 0;
}
});
}
});
});
}
};
}];

View File

@@ -0,0 +1,3 @@
<div>
<div id="job-submission-credential-lookup"></div>
</div>

View File

@@ -0,0 +1,32 @@
/*************************************************
* Copyright (c) 2017 Ansible, Inc.
*
* All Rights Reserved
*************************************************/
export default
[ '$scope',
function($scope) {
$scope.toggle_row = function(rowId) {
let list = $scope.list;
let count = 0;
$scope[list.name].forEach(function(row) {
if (row.id === rowId) {
if (row.checked) {
row.success_class = 'success';
} else {
row.checked = true;
row.success_class = '';
}
$scope.$emit('inventorySelected', row);
} else {
row.checked = 0;
row.success_class = '';
}
if (row.checked) {
count++;
}
});
};
}
];

View File

@@ -0,0 +1,60 @@
/*************************************************
* Copyright (c) 2016 Ansible, Inc.
*
* All Rights Reserved
*************************************************/
import jobSubInvListController from './job-sub-inv-list.controller';
export default [ 'templateUrl', 'QuerySet', 'GetBasePath', 'generateList', '$compile', 'InventoryList',
function(templateUrl, qs, GetBasePath, GenerateList, $compile, InventoryList) {
return {
scope: {},
templateUrl: templateUrl('job-submission/lists/inventory/job-sub-inv-list'),
controller: jobSubInvListController,
restrict: 'E',
link: function(scope) {
scope.inventory_default_params = {
order_by: 'name',
page_size: 5
};
scope.inventory_queryset = {
order_by: 'name',
page_size: 5
};
// Fire off the initial search
qs.search(GetBasePath('inventory'), scope.inventory_default_params)
.then(function(res) {
scope.inventory_dataset = res.data;
scope.inventories = scope.inventory_dataset.results;
var invList = _.cloneDeep(InventoryList);
let html = GenerateList.build({
list: invList,
input_type: 'radio',
mode: 'lookup'
});
scope.list = invList;
$('#job-submission-inventory-lookup').append($compile(html)(scope));
scope.$watchCollection('inventories', function () {
if(scope.selected_inventory) {
// Loop across the inventories and see if one of them should be "checked"
scope.inventories.forEach(function(row, i) {
if (row.id === scope.selected_inventory.id) {
scope.inventories[i].checked = 1;
}
else {
scope.inventories[i].checked = 0;
}
});
}
});
});
}
};
}];

View File

@@ -0,0 +1,3 @@
<div>
<div id="job-submission-inventory-lookup"></div>
</div>

View File

@@ -8,10 +8,14 @@ import InitiatePlaybookRun from './job-submission-factories/initiateplaybookrun.
import LaunchJob from './job-submission-factories/launchjob.factory'; import LaunchJob from './job-submission-factories/launchjob.factory';
import GetSurveyQuestions from './job-submission-factories/getsurveyquestions.factory'; import GetSurveyQuestions from './job-submission-factories/getsurveyquestions.factory';
import submitJob from './job-submission.directive'; import submitJob from './job-submission.directive';
import credentialList from './lists/credential/job-sub-cred-list.directive';
import inventoryList from './lists/inventory/job-sub-inv-list.directive';
export default export default
angular.module('jobSubmission', []) angular.module('jobSubmission', [])
.factory('InitiatePlaybookRun', InitiatePlaybookRun) .factory('InitiatePlaybookRun', InitiatePlaybookRun)
.factory('LaunchJob', LaunchJob) .factory('LaunchJob', LaunchJob)
.factory('GetSurveyQuestions', GetSurveyQuestions) .factory('GetSurveyQuestions', GetSurveyQuestions)
.directive('submitJob', submitJob); .directive('submitJob', submitJob)
.directive('jobSubCredList', credentialList)
.directive('jobSubInvList', inventoryList);

View File

@@ -20,7 +20,6 @@ export default ['i18n', function(i18n){
status: { status: {
label: '', label: '',
iconOnly: true, iconOnly: true,
searchable: false,
nosort: true, nosort: true,
icon: 'icon-job-{{ notification_template.status }}', icon: 'icon-job-{{ notification_template.status }}',
awPopOver: '{{ notification_template.template_status_html }}', awPopOver: '{{ notification_template.template_status_html }}',

View File

@@ -25,7 +25,7 @@ export default ['i18n', function(i18n){
key: true, key: true,
label: i18n._('Name'), label: i18n._('Name'),
columnClass: 'col-md-3 col-sm-9 col-xs-9', columnClass: 'col-md-3 col-sm-9 col-xs-9',
linkTo: '/#/notification_templates/{{notifier.id}}', linkTo: '/#/notification_templates/{{notifier.id}}'
}, },
notification_type: { notification_type: {
label: i18n._('Type'), label: i18n._('Type'),
@@ -42,8 +42,7 @@ export default ['i18n', function(i18n){
awToolTip: "{{ schedule.play_tip }}", awToolTip: "{{ schedule.play_tip }}",
dataTipWatch: "schedule.play_tip", dataTipWatch: "schedule.play_tip",
dataPlacement: "right", dataPlacement: "right",
searchable: false, nosort: true
nosort: true,
}, },
notification_templates_error: { notification_templates_error: {
label: i18n._('Failure'), label: i18n._('Failure'),
@@ -54,8 +53,7 @@ export default ['i18n', function(i18n){
awToolTip: "{{ schedule.play_tip }}", awToolTip: "{{ schedule.play_tip }}",
dataTipWatch: "schedule.play_tip", dataTipWatch: "schedule.play_tip",
dataPlacement: "right", dataPlacement: "right",
searchable: false, nosort: true
nosort: true,
} }
}, },
actions: { actions: {

View File

@@ -1,7 +1,7 @@
export default ['$scope', '$state', 'QuerySet', 'GetBasePath', export default ['$scope', '$state', 'QuerySet', 'GetBasePath',
function($scope, $state, qs, GetBasePath) { function($scope, $state, qs, GetBasePath) {
let queryset, path, order_by; let queryset, path;
function isDescending(str) { function isDescending(str) {
if (str){ if (str){
@@ -16,13 +16,14 @@ export default ['$scope', '$state', 'QuerySet', 'GetBasePath',
return str.charAt(0) === '-' ? `${str.substring(1, str.length)}` : `-${str}`; return str.charAt(0) === '-' ? `${str.substring(1, str.length)}` : `-${str}`;
} }
$scope.orderByIcon = function() { $scope.orderByIcon = function() {
order_by = $state.params[`${$scope.columnIterator}_search`].order_by; let order_by = $scope.querySet ? $scope.querySet.order_by : $state.params[`${$scope.columnIterator}_search`].order_by;
// column sort is inactive // column sort is inactive
if (order_by !== $scope.columnField && order_by !== invertOrderBy($scope.columnField)) { if (order_by !== $scope.columnField && order_by !== invertOrderBy($scope.columnField)) {
return 'fa-sort'; return 'fa-sort';
} }
// column sort is active (governed by order_by) and descending // column sort is active (governed by order_by) and descending
else if (isDescending($state.params[`${$scope.columnIterator}_search`].order_by)) {
else if (isDescending(order_by)) {
return 'fa-sort-down'; return 'fa-sort-down';
} }
// column sort is active governed by order_by) and asscending // column sort is active governed by order_by) and asscending
@@ -32,7 +33,7 @@ export default ['$scope', '$state', 'QuerySet', 'GetBasePath',
}; };
$scope.toggleColumnOrderBy = function() { $scope.toggleColumnOrderBy = function() {
let order_by = $state.params[`${$scope.columnIterator}_search`].order_by; let order_by = $scope.querySet ? $scope.querySet.order_by : $state.params[`${$scope.columnIterator}_search`].order_by;
if (order_by === $scope.columnField || order_by === invertOrderBy($scope.columnField)) { if (order_by === $scope.columnField || order_by === invertOrderBy($scope.columnField)) {
order_by = invertOrderBy(order_by); order_by = invertOrderBy(order_by);
@@ -41,11 +42,24 @@ export default ['$scope', '$state', 'QuerySet', 'GetBasePath',
else { else {
order_by = $scope.columnField; order_by = $scope.columnField;
} }
if($scope.querySet) {
queryset = _.merge($state.params[`${$scope.columnIterator}_search`], { order_by: order_by }); // merging $scope.querySet seems to destroy our initial reference which
// kills the two-way binding here. To fix that, clone the queryset first
// and merge with that object.
let origQuerySet = _.cloneDeep($scope.querySet);
queryset = _.merge(origQuerySet, { order_by: order_by });
}
else {
queryset = _.merge($state.params[`${$scope.columnIterator}_search`], { order_by: order_by });
}
path = GetBasePath($scope.basePath) || $scope.basePath; path = GetBasePath($scope.basePath) || $scope.basePath;
$state.go('.', { [$scope.columnIterator + '_search']: queryset }, {notify: false}); if(!$scope.querySet) {
$state.go('.', { [$scope.columnIterator + '_search']: queryset }, {notify: false});
}
qs.search(path, queryset).then((res) =>{ qs.search(path, queryset).then((res) =>{
if($scope.querySet) {
$scope.querySet = queryset;
}
$scope.dataset = res.data; $scope.dataset = res.data;
$scope.collection = res.data.results; $scope.collection = res.data.results;
}); });

View File

@@ -12,6 +12,7 @@ export default ['templateUrl', function(templateUrl) {
columnIterator: '@', columnIterator: '@',
columnField: '@', columnField: '@',
columnLabel: '@', columnLabel: '@',
querySet: '='
}, },
controller: 'ColumnSortController', controller: 'ColumnSortController',
templateUrl: templateUrl('shared/column-sort/column-sort') templateUrl: templateUrl('shared/column-sort/column-sort')

View File

@@ -64,7 +64,6 @@
* | linkTo | Wraps the field value with an &lt;a&gt; element. Set to the value of the href attribute. | * | linkTo | Wraps the field value with an &lt;a&gt; element. Set to the value of the href attribute. |
* | ngClick | Wraps the field value with an &lt;a&gt; and adds the ng-click directive. Set to the JS expression that ng-click will evaluate. | * | ngClick | Wraps the field value with an &lt;a&gt; and adds the ng-click directive. Set to the JS expression that ng-click will evaluate. |
* | nosort | true or false. Setting to false removes the ability to sort the table by the column. | * | nosort | true or false. Setting to false removes the ability to sort the table by the column. |
* | searchable | true or fasel. Set to false if the field should not be included as in option in the search widget. |
* | searchOnly | true or false. Set to true if the field should be included in the search widget but not included as a column in the generated HTML &lt;table&gt;. | * | searchOnly | true or false. Set to true if the field should be included in the search widget but not included as a column in the generated HTML &lt;table&gt;. |
* | searchOptions | Array of { name: 'Descriptive Name', value: 'api_value' } objects used to generate &lt;options&gt; for the &lt;select&gt; when searchType is 'select'. | * | searchOptions | Array of { name: 'Descriptive Name', value: 'api_value' } objects used to generate &lt;options&gt; for the &lt;select&gt; when searchType is 'select'. |
* | searchType | One of the available search types defined in helpers/search.js. | * | searchType | One of the available search types defined in helpers/search.js. |
@@ -200,18 +199,19 @@ export default ['$location', '$compile', '$rootScope', 'Attr', 'Icon',
} }
if (options.showSearch === undefined || options.showSearch === true) { if (options.showSearch === undefined || options.showSearch === true) {
html += ` html += `
<div <div ng-hide="${list.name}.length === 0 && (searchTags | isEmpty)">
ng-hide="${list.name}.length === 0 && (searchTags | isEmpty)"> <smart-search
<smart-search django-model="${list.name}"
django-model="${list.name}" search-size="${list.searchSize}"
search-size="${list.searchSize}" base-path="${list.basePath || list.name}"
base-path="${list.basePath || list.name}" iterator="${list.iterator}"
iterator="${list.iterator}" dataset="${list.iterator}_dataset"
dataset="${list.iterator}_dataset" list="list"
list="list" collection="${list.name}"
collection="${list.name}" default-params="${list.iterator}_default_params"
search-tags="searchTags"> query-set="${list.iterator}_queryset"
</smart-search> search-tags="searchTags">
</smart-search>
</div> </div>
`; `;
} }
@@ -450,7 +450,8 @@ export default ['$location', '$compile', '$rootScope', 'Attr', 'Icon',
base-path="${list.basePath || list.name}" base-path="${list.basePath || list.name}"
collection="${list.name}" collection="${list.name}"
dataset="${list.iterator}_dataset" dataset="${list.iterator}_dataset"
iterator="${list.iterator}"> iterator="${list.iterator}"
query-set="${list.iterator}_queryset">
</paginate></div>`; </paginate></div>`;
} }
@@ -499,7 +500,8 @@ export default ['$location', '$compile', '$rootScope', 'Attr', 'Icon',
column-iterator="${list.iterator}" column-iterator="${list.iterator}"
column-no-sort="${list.fields[fld].nosort}" column-no-sort="${list.fields[fld].nosort}"
column-label="${list.fields[fld].label}" column-label="${list.fields[fld].label}"
column-custom-class="${customClass}"> column-custom-class="${customClass}"
query-set="${list.iterator}_queryset">
</th>`; </th>`;
} }
} }
@@ -514,7 +516,8 @@ export default ['$location', '$compile', '$rootScope', 'Attr', 'Icon',
column-iterator="${list.iterator}" column-iterator="${list.iterator}"
column-no-sort="${list.fields.name.nosort}" column-no-sort="${list.fields.name.nosort}"
column-label="${list.fields.name.label}" column-label="${list.fields.name.label}"
column-custom-class="${customClass}"> column-custom-class="${customClass}"
query-set="${list.iterator}_queryset">
</th>`; </th>`;
if(list.fields.info) { if(list.fields.info) {
@@ -529,7 +532,8 @@ export default ['$location', '$compile', '$rootScope', 'Attr', 'Icon',
column-iterator="${list.iterator}" column-iterator="${list.iterator}"
column-no-sort="${list.fields.info.nosort}" column-no-sort="${list.fields.info.nosort}"
column-label="${list.fields.info.label}" column-label="${list.fields.info.label}"
column-custom-class="${customClass}"> column-custom-class="${customClass}"
query-set="${list.iterator}_queryset">
</th>`; </th>`;
} }
} }

View File

@@ -1,8 +1,18 @@
export default ['$scope', '$stateParams', '$state', '$filter', 'GetBasePath', 'QuerySet', export default ['$scope', '$stateParams', '$state', '$filter', 'GetBasePath', 'QuerySet',
function($scope, $stateParams, $state, $filter, GetBasePath, qs) { function($scope, $stateParams, $state, $filter, GetBasePath, qs) {
let pageSize = $stateParams[`${$scope.iterator}_search`].page_size || 20, let pageSize,
queryset, path; queryset, path;
// TODO: can we clean this if/else up?
if($scope.querySet) {
pageSize = $scope.querySet.page_size || 20;
}
else {
// Pull the page size from the url
pageSize = $stateParams[`${$scope.iterator}_search`].page_size || 20;
}
$scope.pageSize = pageSize; $scope.pageSize = pageSize;
function init() { function init() {
@@ -18,11 +28,27 @@ export default ['$scope', '$stateParams', '$state', '$filter', 'GetBasePath', 'Q
return; return;
} }
path = GetBasePath($scope.basePath) || $scope.basePath; path = GetBasePath($scope.basePath) || $scope.basePath;
queryset = _.merge($stateParams[`${$scope.iterator}_search`], { page: page }); if($scope.querySet) {
$state.go('.', { // merging $scope.querySet seems to destroy our initial reference which
[$scope.iterator + '_search']: queryset // kills the two-way binding here. To fix that, clone the queryset first
}, {notify: false}); // and merge with that object.
let origQuerySet = _.cloneDeep($scope.querySet);
queryset = _.merge(origQuerySet, { page: page });
}
else {
queryset = _.merge($stateParams[`${$scope.iterator}_search`], { page: page });
}
if(!$scope.querySet) {
$state.go('.', {
[$scope.iterator + '_search']: queryset
}, {notify: false});
}
qs.search(path, queryset).then((res) => { qs.search(path, queryset).then((res) => {
if($scope.querySet) {
// Update the query set
$scope.querySet = queryset;
}
$scope.dataset = res.data; $scope.dataset = res.data;
$scope.collection = res.data.results; $scope.collection = res.data.results;
}); });
@@ -31,7 +57,12 @@ export default ['$scope', '$stateParams', '$state', '$filter', 'GetBasePath', 'Q
}; };
$scope.current = function() { $scope.current = function() {
return parseInt($stateParams[`${$scope.iterator}_search`].page || '1'); if($scope.querySet) {
return parseInt($scope.querySet.page || '1');
}
else {
return parseInt($stateParams[`${$scope.iterator}_search`].page || '1');
}
}; };
$scope.last = function() { $scope.last = function() {

View File

@@ -7,7 +7,8 @@ export default ['templateUrl',
collection: '=', collection: '=',
dataset: '=', dataset: '=',
iterator: '@', iterator: '@',
basePath: '@' basePath: '@',
querySet: '='
}, },
controller: 'PaginateController', controller: 'PaginateController',
templateUrl: templateUrl('shared/paginate/paginate') templateUrl: templateUrl('shared/paginate/paginate')

View File

@@ -2,12 +2,26 @@ export default ['$stateParams', '$scope', '$state', 'QuerySet', 'GetBasePath', '
function($stateParams, $scope, $state, QuerySet, GetBasePath, qs, SmartSearchService) { function($stateParams, $scope, $state, QuerySet, GetBasePath, qs, SmartSearchService) {
let path, relations, let path, relations,
defaults,
queryset,
stateChangeSuccessListener;
if($scope.defaultParams) {
defaults = $scope.defaultParams;
}
else {
// steps through the current tree of $state configurations, grabs default search params // steps through the current tree of $state configurations, grabs default search params
defaults = _.find($state.$current.path, (step) => { defaults = _.find($state.$current.path, (step) => {
return step.params.hasOwnProperty(`${$scope.iterator}_search`); return step.params.hasOwnProperty(`${$scope.iterator}_search`);
}).params[`${$scope.iterator}_search`].config.value, }).params[`${$scope.iterator}_search`].config.value;
queryset = $stateParams[`${$scope.iterator}_search`], }
stateChangeSuccessListener;
if($scope.querySet) {
queryset = _.cloneDeep($scope.querySet);
}
else {
queryset = $stateParams[`${$scope.iterator}_search`];
}
// build $scope.tags from $stateParams.QuerySet, build fieldset key // build $scope.tags from $stateParams.QuerySet, build fieldset key
init(); init();
@@ -109,8 +123,13 @@ export default ['$stateParams', '$scope', '$state', 'QuerySet', 'GetBasePath', '
let cleared = _.cloneDeep(defaults); let cleared = _.cloneDeep(defaults);
delete cleared.page; delete cleared.page;
queryset = cleared; queryset = cleared;
$state.go('.', {[$scope.iterator + '_search']: queryset}, {notify: false}); if(!$scope.querySet) {
$state.go('.', {[$scope.iterator + '_search']: queryset}, {notify: false});
}
qs.search(path, queryset).then((res) => { qs.search(path, queryset).then((res) => {
if($scope.querySet) {
$scope.querySet = queryset;
}
$scope.dataset = res.data; $scope.dataset = res.data;
$scope.collection = res.data.results; $scope.collection = res.data.results;
}); });
@@ -152,9 +171,14 @@ export default ['$stateParams', '$scope', '$state', 'QuerySet', 'GetBasePath', '
delete queryset[key]; delete queryset[key];
} }
}); });
$state.go('.', { if(!$scope.querySet) {
[$scope.iterator + '_search']: queryset }, {notify: false}); $state.go('.', {
[$scope.iterator + '_search']: queryset }, {notify: false});
}
qs.search(path, queryset).then((res) => { qs.search(path, queryset).then((res) => {
if($scope.querySet) {
$scope.querySet = queryset;
}
$scope.dataset = res.data; $scope.dataset = res.data;
$scope.collection = res.data.results; $scope.collection = res.data.results;
}); });
@@ -231,9 +255,14 @@ export default ['$stateParams', '$scope', '$state', 'QuerySet', 'GetBasePath', '
// https://ui-router.github.io/docs/latest/interfaces/params.paramdeclaration.html#dynamic // https://ui-router.github.io/docs/latest/interfaces/params.paramdeclaration.html#dynamic
// This transition will not reload controllers/resolves/views // This transition will not reload controllers/resolves/views
// but will register new $stateParams[$scope.iterator + '_search'] terms // but will register new $stateParams[$scope.iterator + '_search'] terms
$state.go('.', { if(!$scope.querySet) {
[$scope.iterator + '_search']: queryset }, {notify: false}); $state.go('.', {
[$scope.iterator + '_search']: queryset }, {notify: false});
}
qs.search(path, queryset).then((res) => { qs.search(path, queryset).then((res) => {
if($scope.querySet) {
$scope.querySet = queryset;
}
$scope.dataset = res.data; $scope.dataset = res.data;
$scope.collection = res.data.results; $scope.collection = res.data.results;
}) })
@@ -251,9 +280,14 @@ export default ['$stateParams', '$scope', '$state', 'QuerySet', 'GetBasePath', '
// https://ui-router.github.io/docs/latest/interfaces/params.paramdeclaration.html#dynamic // https://ui-router.github.io/docs/latest/interfaces/params.paramdeclaration.html#dynamic
// This transition will not reload controllers/resolves/views // This transition will not reload controllers/resolves/views
// but will register new $stateParams[$scope.iterator + '_search'] terms // but will register new $stateParams[$scope.iterator + '_search'] terms
$state.go('.', { if(!$scope.querySet) {
[$scope.iterator + '_search']: queryset }, {notify: false}); $state.go('.', {
[$scope.iterator + '_search']: queryset }, {notify: false});
}
qs.search(path, queryset).then((res) => { qs.search(path, queryset).then((res) => {
if($scope.querySet) {
$scope.querySet = queryset;
}
$scope.dataset = res.data; $scope.dataset = res.data;
$scope.collection = res.data.results; $scope.collection = res.data.results;
}); });

View File

@@ -15,7 +15,9 @@ export default ['templateUrl',
dataset: '=', dataset: '=',
collection: '=', collection: '=',
searchTags: '=', searchTags: '=',
disableSearch: '=' disableSearch: '=',
defaultParams: '=',
querySet: '='
}, },
controller: 'SmartSearchController', controller: 'SmartSearchController',
templateUrl: templateUrl('shared/smart-search/smart-search') templateUrl: templateUrl('shared/smart-search/smart-search')

View File

@@ -784,7 +784,7 @@ export default [ '$state','moment',
} }
}); });
scope.$on('refreshWorkflowChart', function(){console.log(scope.treeData); scope.$on('refreshWorkflowChart', function(){
if(scope.treeData) { if(scope.treeData) {
update(); update();
} }