diff --git a/awx/ui/client/features/jobs/index.js b/awx/ui/client/features/jobs/index.js index 7212944ddc..c26f2b9d8f 100644 --- a/awx/ui/client/features/jobs/index.js +++ b/awx/ui/client/features/jobs/index.js @@ -1,5 +1,5 @@ import JobsStrings from './jobs.strings'; -import jobsRoute from './jobs.route'; +import jobsRoute from './routes/jobs.route'; const MODULE_NAME = 'at.features.jobs'; diff --git a/awx/ui/client/features/jobs/jobsList.view.html b/awx/ui/client/features/jobs/jobsList.view.html index 85f54bbfdc..6031a956ab 100644 --- a/awx/ui/client/features/jobs/jobsList.view.html +++ b/awx/ui/client/features/jobs/jobsList.view.html @@ -63,7 +63,7 @@
- { + const models = [ + new UnifiedJob(['options']), + ]; + return Promise.all(models); + }, + ], + Dataset: [ + '$stateParams', + 'Wait', + 'GetBasePath', + 'QuerySet', + ($stateParams, Wait, GetBasePath, qs) => { + const groupId = $stateParams.instance_group_id; + + const searchParam = $stateParams.job_search; + + const searchPath = `api/v2/instance_groups/${groupId}/jobs`; + + Wait('start'); + return qs.search(searchPath, searchParam) + .finally(() => Wait('stop')); + } + ] + } +}; diff --git a/awx/ui/client/features/jobs/routes/instanceJobs.route.js b/awx/ui/client/features/jobs/routes/instanceJobs.route.js new file mode 100644 index 0000000000..76fed1f1b0 --- /dev/null +++ b/awx/ui/client/features/jobs/routes/instanceJobs.route.js @@ -0,0 +1,64 @@ +import listContainerController from '~src/instance-groups/jobs/jobsListContainer.controller'; +import { N_ } from '../../../src/i18n'; +import jobsListController from '../jobsList.controller'; + +const jobsListTemplate = require('~features/jobs/jobsList.view.html'); +const listContainerTemplate = require('~src/instance-groups/jobs/jobsListContainer.partial.html'); + +export default { + name: 'instanceGroups.instanceJobs', + url: '/:instance_group_id/instances/:instance_id/jobs', + ncyBreadcrumb: { + parent: 'instanceGroups.instances', + label: N_('JOBS') + }, + views: { + 'jobsContainer@instances': { + templateUrl: listContainerTemplate, + controller: listContainerController, + controllerAs: 'vm' + }, + 'jobsList@instances': { + templateUrl: jobsListTemplate, + controller: jobsListController, + controllerAs: 'vm' + }, + }, + params: { + job_search: { + value: { + page_size: '10', + order_by: '-finished' + }, + dynamic: true + }, + }, + resolve: { + resolvedModels: [ + 'UnifiedJobModel', + (UnifiedJob) => { + const models = [ + new UnifiedJob(['options']), + ]; + return Promise.all(models); + }, + ], + Dataset: [ + '$stateParams', + 'Wait', + 'GetBasePath', + 'QuerySet', + ($stateParams, Wait, GetBasePath, qs) => { + const instanceId = $stateParams.instance_id; + + const searchParam = $stateParams.job_search; + + const searchPath = `api/v2/instances/${instanceId}/jobs`; + + Wait('start'); + return qs.search(searchPath, searchParam) + .finally(() => Wait('stop')); + } + ] + } +}; diff --git a/awx/ui/client/features/jobs/routes/inventoryCompletedJobs.route.js b/awx/ui/client/features/jobs/routes/inventoryCompletedJobs.route.js new file mode 100644 index 0000000000..333359c6f6 --- /dev/null +++ b/awx/ui/client/features/jobs/routes/inventoryCompletedJobs.route.js @@ -0,0 +1,63 @@ +import { N_ } from '../../../src/i18n'; +import jobsListController from '../jobsList.controller'; + +const jobsListTemplate = require('~features/jobs/jobsList.view.html'); + +export default { + url: '/completed_jobs', + params: { + job_search: { + value: { + page_size: '20', + or__job__inventory: '', + or__adhoccommand__inventory: '', + or__inventoryupdate__inventory_source__inventory: '', + order_by: '-id' + }, + dynamic: true, + squash: '' + } + }, + ncyBreadcrumb: { + label: N_('JOBS') + }, + views: { + related: { + templateUrl: jobsListTemplate, + controller: jobsListController, + controllerAs: 'vm' + } + }, + resolve: { + resolvedModels: [ + 'UnifiedJobModel', + (UnifiedJob) => { + const models = [ + new UnifiedJob(['options']), + ]; + return Promise.all(models); + }, + ], + Dataset: [ + '$stateParams', + 'Wait', + 'GetBasePath', + 'QuerySet', + ($stateParams, Wait, GetBasePath, qs) => { + const inventoryId = $stateParams.inventory_id ? + $stateParams.inventory_id : $stateParams.smartinventory_id; + + const searchParam = _.assign($stateParams.job_search, { + or__job__inventory: inventoryId, + or__adhoccommand__inventory: inventoryId, + or__inventoryupdate__inventory_source__inventory: inventoryId }); + + const searchPath = GetBasePath('unified_jobs'); + + Wait('start'); + return qs.search(searchPath, searchParam) + .finally(() => Wait('stop')); + } + ] + } +}; diff --git a/awx/ui/client/features/jobs/jobs.route.js b/awx/ui/client/features/jobs/routes/jobs.route.js similarity index 94% rename from awx/ui/client/features/jobs/jobs.route.js rename to awx/ui/client/features/jobs/routes/jobs.route.js index 4aed40d11d..c3ee0b4fef 100644 --- a/awx/ui/client/features/jobs/jobs.route.js +++ b/awx/ui/client/features/jobs/routes/jobs.route.js @@ -1,5 +1,5 @@ -import { N_ } from '../../src/i18n'; -import jobsListController from './jobsList.controller'; +import { N_ } from '../../../src/i18n'; +import jobsListController from '../jobsList.controller'; const indexTemplate = require('~features/jobs/index.view.html'); const jobsListTemplate = require('~features/jobs/jobsList.view.html'); diff --git a/awx/ui/client/features/jobs/routes/portalModeAllJobs.route.js b/awx/ui/client/features/jobs/routes/portalModeAllJobs.route.js new file mode 100644 index 0000000000..9595da3547 --- /dev/null +++ b/awx/ui/client/features/jobs/routes/portalModeAllJobs.route.js @@ -0,0 +1,50 @@ +import jobsListController from '../jobsList.controller'; + +const jobsListTemplate = require('~features/jobs/jobsList.view.html'); + +export default { + name: 'portalMode.allJobs', + url: '/alljobs?{job_search:queryset}', + params: { + job_search: { + value: { + page_size: '20', + order_by: '-finished' + }, + dynamic: true + } + }, + views: { + 'jobs@portalMode': { + templateUrl: jobsListTemplate, + controller: jobsListController, + controllerAs: 'vm' + } + }, + resolve: { + resolvedModels: [ + 'UnifiedJobModel', + (UnifiedJob) => { + const models = [ + new UnifiedJob(['options']), + ]; + return Promise.all(models); + }, + ], + Dataset: [ + '$stateParams', + 'Wait', + 'GetBasePath', + 'QuerySet', + ($stateParams, Wait, GetBasePath, qs) => { + const searchParam = $stateParams.job_search; + + const searchPath = GetBasePath('unified_jobs'); + + Wait('start'); + return qs.search(searchPath, searchParam) + .finally(() => Wait('stop')); + } + ] + } +}; diff --git a/awx/ui/client/features/jobs/routes/portalModeMyJobs.route.js b/awx/ui/client/features/jobs/routes/portalModeMyJobs.route.js new file mode 100644 index 0000000000..07506a553f --- /dev/null +++ b/awx/ui/client/features/jobs/routes/portalModeMyJobs.route.js @@ -0,0 +1,53 @@ +import jobsListController from '../jobsList.controller'; + +const jobsListTemplate = require('~features/jobs/jobsList.view.html'); + +export default { + name: 'portalMode.myJobs', + url: '/myjobs?{job_search:queryset}', + params: { + job_search: { + value: { + page_size: '20', + order_by: '-finished', + created_by: null + }, + dynamic: true + } + }, + views: { + 'jobs@portalMode': { + templateUrl: jobsListTemplate, + controller: jobsListController, + controllerAs: 'vm' + } + }, + resolve: { + resolvedModels: [ + 'UnifiedJobModel', + (UnifiedJob) => { + const models = [ + new UnifiedJob(['options']), + ]; + return Promise.all(models); + }, + ], + Dataset: [ + '$stateParams', + 'Wait', + 'GetBasePath', + 'QuerySet', + '$rootScope', + ($stateParams, Wait, GetBasePath, qs, $rootScope) => { + const searchParam = _.assign($stateParams.job_search, { + created_by: $rootScope.current_user.id }); + + const searchPath = GetBasePath('unified_jobs'); + + Wait('start'); + return qs.search(searchPath, searchParam) + .finally(() => Wait('stop')); + } + ] + } +}; diff --git a/awx/ui/client/features/jobs/routes/templateCompletedJobs.route.js b/awx/ui/client/features/jobs/routes/templateCompletedJobs.route.js new file mode 100644 index 0000000000..3fc69a5ffe --- /dev/null +++ b/awx/ui/client/features/jobs/routes/templateCompletedJobs.route.js @@ -0,0 +1,60 @@ +import { N_ } from '../../../src/i18n'; +import jobsListController from '../jobsList.controller'; + +const jobsListTemplate = require('~features/jobs/jobsList.view.html'); + +export default { + url: '/completed_jobs', + name: 'templates.editJobTemplate.completed_jobs', + params: { + job_search: { + value: { + page_size: '20', + job__job_template: '', + order_by: '-id' + }, + dynamic: true, + squash: '' + } + }, + ncyBreadcrumb: { + label: N_('COMPLETED JOBS') + }, + views: { + related: { + templateUrl: jobsListTemplate, + controller: jobsListController, + controllerAs: 'vm' + } + }, + resolve: { + resolvedModels: [ + 'UnifiedJobModel', + (UnifiedJob) => { + const models = [ + new UnifiedJob(['options']), + ]; + return Promise.all(models); + }, + ], + Dataset: [ + '$stateParams', + 'Wait', + 'GetBasePath', + 'QuerySet', + ($stateParams, Wait, GetBasePath, qs) => { + const templateId = $stateParams.job_template_id ? + $stateParams.job_template_id : $stateParams.job_template_id; + + const searchParam = _.assign($stateParams + .job_search, { job__job_template: templateId }); + + const searchPath = GetBasePath('unified_jobs'); + + Wait('start'); + return qs.search(searchPath, searchParam) + .finally(() => Wait('stop')); + } + ] + } +}; diff --git a/awx/ui/client/src/app.js b/awx/ui/client/src/app.js index ab93141b7d..5e67b3a381 100644 --- a/awx/ui/client/src/app.js +++ b/awx/ui/client/src/app.js @@ -33,7 +33,6 @@ import login from './login/main'; import activityStream from './activity-stream/main'; import standardOut from './standard-out/main'; import Templates from './templates/main'; -import jobs from './jobs/main'; import teams from './teams/main'; import users from './users/main'; import projects from './projects/main'; @@ -92,7 +91,6 @@ angular standardOut.name, Templates.name, portalMode.name, - jobs.name, teams.name, users.name, projects.name, diff --git a/awx/ui/client/src/instance-groups/instance-groups.partial.html b/awx/ui/client/src/instance-groups/instance-groups.partial.html index 217efd98d0..680f8b1ded 100644 --- a/awx/ui/client/src/instance-groups/instance-groups.partial.html +++ b/awx/ui/client/src/instance-groups/instance-groups.partial.html @@ -7,7 +7,7 @@
-
+
diff --git a/awx/ui/client/src/instance-groups/instances/instance-jobs/instance-jobs.controller.js b/awx/ui/client/src/instance-groups/instances/instance-jobs/instance-jobs.controller.js deleted file mode 100644 index bdabf14436..0000000000 --- a/awx/ui/client/src/instance-groups/instances/instance-jobs/instance-jobs.controller.js +++ /dev/null @@ -1,89 +0,0 @@ - -function InstanceJobsController ($scope, $filter, $state, model, strings, jobStrings, Instance) { - const vm = this || {}; - let { instance } = model; - const instance_id = instance.get('id'); - - init(); - - function init(){ - vm.strings = strings; - vm.jobStrings = jobStrings; - vm.queryset = { page_size: '10', order_by: '-finished'}; - vm.jobs = instance.get('related.jobs.results'); - vm.dataset = instance.get('related.jobs'); - vm.count = instance.get('related.jobs.count'); - vm.panelTitle = `${jobStrings.get('list.PANEL_TITLE')} | ${instance.get('hostname')}`; - - vm.tab = { - details: {_hide: true}, - instances: {_hide: true}, - jobs: {_hide: true} - }; - } - - vm.getTime = function(time) { - let val = ""; - if (time) { - val += $filter('longDate')(time); - } - if (val === "") { - val = undefined; - } - return val; - }; - - $scope.isSuccessful = function (status) { - return (status === "successful"); - }; - - $scope.viewjobResults = function(job) { - var goTojobResults = function(state) { - $state.go(state, { id: job.id }, { reload: true }); - }; - switch (job.type) { - case 'job': - goTojobResults('jobResult'); - break; - case 'ad_hoc_command': - goTojobResults('adHocJobStdout'); - break; - case 'system_job': - goTojobResults('managementJobStdout'); - break; - case 'project_update': - goTojobResults('scmUpdateStdout'); - break; - case 'inventory_update': - goTojobResults('inventorySyncStdout'); - break; - case 'workflow_job': - goTojobResults('workflowResults'); - break; - } - }; - - $scope.$on('ws-jobs', () => { - new Instance(['get', 'options'], [instance_id, instance_id]) - .then((data) => { - return data.extend('get', 'jobs', {params: {page_size: "10", order_by: "-finished"}}); - }) - .then((data) => { - instance = data; - init(); - }); - }); - -} - -InstanceJobsController.$inject = [ - '$scope', - '$filter', - '$state', - 'resolvedModels', - 'InstanceGroupsStrings', - 'JobStrings', - 'InstanceModel' -]; - -export default InstanceJobsController; diff --git a/awx/ui/client/src/instance-groups/jobs/jobs-list.partial.html b/awx/ui/client/src/instance-groups/jobs/jobs-list.partial.html deleted file mode 100644 index 8fdea7b2da..0000000000 --- a/awx/ui/client/src/instance-groups/jobs/jobs-list.partial.html +++ /dev/null @@ -1,86 +0,0 @@ - - - {{ vm.panelTitle }} - - - {{:: vm.strings.get('tab.DETAILS') }} - {{:: vm.strings.get('tab.INSTANCES') }} - {{:: vm.strings.get('tab.JOBS') }} - - - -
- - -
- - -
- - - -
-
- - - - - - - - - - - - - - - - -
-
-
- - -
-
diff --git a/awx/ui/client/src/instance-groups/jobs/jobs.controller.js b/awx/ui/client/src/instance-groups/jobs/jobs.controller.js deleted file mode 100644 index 0b54a962b8..0000000000 --- a/awx/ui/client/src/instance-groups/jobs/jobs.controller.js +++ /dev/null @@ -1,100 +0,0 @@ - -function InstanceGroupJobsController ($scope, $filter, $state, model, strings, jobStrings, InstanceGroup) { - const vm = this || {}; - let { instanceGroup } = model; - const instance_group_id = instanceGroup.get('id'); - - init(); - - function init(){ - vm.strings = strings; - vm.jobStrings = jobStrings; - vm.queryset = { page_size: '10', order_by: '-finished', instance_group_id: instance_group_id }; - vm.jobs = instanceGroup.get('related.jobs.results'); - vm.dataset = instanceGroup.get('related.jobs'); - vm.count = instanceGroup.get('related.jobs.count'); - vm.panelTitle = instanceGroup.get('name'); - - vm.tab = { - details: { - _go: 'instanceGroups.edit', - _params: { instance_group_id }, - _label: strings.get('tab.DETAILS') - }, - instances: { - _go: 'instanceGroups.instances', - _params: { instance_group_id }, - _label: strings.get('tab.INSTANCES') - }, - jobs: { - _active: true, - _label: strings.get('tab.JOBS') - } - }; - } - - vm.getTime = function(time) { - let val = ""; - if (time) { - val += $filter('longDate')(time); - } - if (val === "") { - val = undefined; - } - return val; - }; - - $scope.isSuccessful = function (status) { - return (status === "successful"); - }; - - vm.viewjobResults = function(job) { - var goTojobResults = function(state) { - $state.go(state, { id: job.id }, { reload: true }); - }; - switch (job.type) { - case 'job': - goTojobResults('jobResult'); - break; - case 'ad_hoc_command': - goTojobResults('adHocJobStdout'); - break; - case 'system_job': - goTojobResults('managementJobStdout'); - break; - case 'project_update': - goTojobResults('scmUpdateStdout'); - break; - case 'inventory_update': - goTojobResults('inventorySyncStdout'); - break; - case 'workflow_job': - goTojobResults('workflowResults'); - break; - } - }; - - $scope.$on('ws-jobs', () => { - new InstanceGroup(['get', 'options'], [instance_group_id, instance_group_id]) - .then((instance_group) => { - return instance_group.extend('get', 'jobs', {params: {page_size: "10", order_by: "-finished"}}); - }) - .then((instance_group) => { - instanceGroup = instance_group; - init(); - }); - }); - -} - -InstanceGroupJobsController.$inject = [ - '$scope', - '$filter', - '$state', - 'resolvedModels', - 'InstanceGroupsStrings', - 'JobStrings', - 'InstanceGroupModel' -]; - -export default InstanceGroupJobsController; \ No newline at end of file diff --git a/awx/ui/client/src/instance-groups/jobs/jobs.list.js b/awx/ui/client/src/instance-groups/jobs/jobs.list.js deleted file mode 100644 index 59e14ba19b..0000000000 --- a/awx/ui/client/src/instance-groups/jobs/jobs.list.js +++ /dev/null @@ -1,76 +0,0 @@ -export default ['i18n', function (i18n) { - return { - name: 'jobs', - iterator: 'job', - basePath: 'api/v2/instance_groups/{{$stateParams.instance_group_id}}/jobs/', - index: false, - hover: false, - well: true, - emptyListText: i18n._('No jobs have yet run.'), - listTitle: false, - - fields: { - status: { - label: '', - columnClass: 'col-lg-1 col-md-1 col-sm-2 col-xs-2 List-staticColumn--smallStatus', - dataTipWatch: 'job.status_tip', - awToolTip: "{{ job.status_tip }}", - awTipPlacement: "right", - dataTitle: "{{ job.status_popover_title }}", - icon: 'icon-job-{{ job.status }}', - iconOnly: true, - ngClick: "viewjobResults(job)", - nosort: true - }, - id: { - label: i18n._('ID'), - ngClick: "viewjobResults(job)", - columnClass: 'col-lg-1 col-md-1 col-sm-2 col-xs-2 List-staticColumnAdjacent', - awToolTip: "{{ job.status_tip }}", - dataPlacement: 'top', - noLink: true - }, - name: { - label: i18n._('Name'), - columnClass: 'col-lg-2 col-md-3 col-sm-4 col-xs-6', - ngClick: "viewjobResults(job)", - badgePlacement: 'right', - badgeCustom: true, - nosort: true, - badgeIcon: ` - - W - - ` - }, - type: { - label: i18n._('Type'), - ngBind: 'job.type_label', - columnClass: "col-lg-2 hidden-md hidden-sm hidden-xs", - nosort: true - }, - finished: { - label: i18n._('Finished'), - noLink: true, - filter: "longDate", - columnClass: "col-lg-2 col-md-3 col-sm-3 hidden-xs", - key: true, - desc: true, - nosort: true - }, - labels: { - label: i18n._('Labels'), - type: 'labels', - nosort: true, - showDelete: false, - columnClass: 'List-tableCell col-lg-4 col-md-4 hidden-sm hidden-xs', - sourceModel: 'labels', - sourceField: 'name' - }, - } - }; -}]; diff --git a/awx/ui/client/src/instance-groups/jobs/jobs.strings.js b/awx/ui/client/src/instance-groups/jobs/jobs.strings.js deleted file mode 100644 index 8ecffd5a0a..0000000000 --- a/awx/ui/client/src/instance-groups/jobs/jobs.strings.js +++ /dev/null @@ -1,30 +0,0 @@ -function JobStrings (BaseString) { - BaseString.call(this, 'jobs'); - - const { t } = this; - const ns = this.jobs; - - ns.state = { - LIST_BREADCRUMB_LABEL: t.s('JOBS') - }; - - ns.list = { - PANEL_TITLE: t.s('JOBS'), - ADD_BUTTON_LABEL: t.s('ADD'), - ADD_DD_JT_LABEL: t.s('Job Template'), - ADD_DD_WF_LABEL: t.s('Workflow Template'), - ROW_ITEM_LABEL_ACTIVITY: t.s('Activity'), - ROW_ITEM_LABEL_INVENTORY: t.s('Inventory'), - ROW_ITEM_LABEL_PROJECT: t.s('Project'), - ROW_ITEM_LABEL_TEMPLATE: t.s('Template'), - ROW_ITEM_LABEL_CREDENTIALS: t.s('Credentials'), - ROW_ITEM_LABEL_MODIFIED: t.s('Last Modified'), - ROW_ITEM_LABEL_RAN: t.s('Last Ran'), - ROW_ITEM_LABEL_STARTED: t.s('Started'), - ROW_ITEM_LABEL_FINISHED: t.s('Finished') - }; -} - -JobStrings.$inject = ['BaseStringService']; - -export default JobStrings; diff --git a/awx/ui/client/src/instance-groups/jobs/jobsListContainer.controller.js b/awx/ui/client/src/instance-groups/jobs/jobsListContainer.controller.js new file mode 100644 index 0000000000..6ccb6775ff --- /dev/null +++ b/awx/ui/client/src/instance-groups/jobs/jobsListContainer.controller.js @@ -0,0 +1,36 @@ + +function InstanceGroupJobsContainerController (strings, $state) { + const vm = this || {}; + + init(); + function init() { + const instanceGroupId = $state.params.instance_group_id; + + vm.panelTitle = 'Jobs' + + vm.tab = { + details: { + _go: 'instanceGroups.edit', + _params: { instanceGroupId }, + _label: strings.get('tab.DETAILS') + }, + instances: { + _go: 'instanceGroups.instances', + _params: { instanceGroupId }, + _label: strings.get('tab.INSTANCES') + }, + jobs: { + _active: true, + _label: strings.get('tab.JOBS') + } + }; + } + +} + +InstanceGroupJobsContainerController.$inject = [ + 'InstanceGroupsStrings', + '$state' +]; + +export default InstanceGroupJobsContainerController; diff --git a/awx/ui/client/src/instance-groups/jobs/jobsListContainer.partial.html b/awx/ui/client/src/instance-groups/jobs/jobsListContainer.partial.html new file mode 100644 index 0000000000..9eab62c32f --- /dev/null +++ b/awx/ui/client/src/instance-groups/jobs/jobsListContainer.partial.html @@ -0,0 +1,11 @@ + + + {{ vm.panelTitle }} + + + {{:: vm.strings.get('tab.DETAILS') }} + {{:: vm.strings.get('tab.INSTANCES') }} + {{:: vm.strings.get('tab.JOBS') }} + +
+
diff --git a/awx/ui/client/src/instance-groups/main.js b/awx/ui/client/src/instance-groups/main.js index f241df97cb..2314aee41a 100644 --- a/awx/ui/client/src/instance-groups/main.js +++ b/awx/ui/client/src/instance-groups/main.js @@ -15,10 +15,6 @@ import InstanceGroupsListController from './list/instance-groups-list.controller import InstancesTemplate from './instances/instances-list.partial.html'; import InstanceListController from './instances/instances.controller'; -import JobsTemplate from './jobs/jobs-list.partial.html'; -import InstanceGroupJobsListController from './jobs/jobs.controller'; -import InstanceJobsListController from './instances/instance-jobs/instance-jobs.controller'; - import InstanceModalTemplate from './instances/instance-modal.partial.html'; import InstanceModalController from './instances/instance-modal.controller.js'; @@ -26,7 +22,9 @@ import list from './instance-groups.list'; import service from './instance-groups.service'; import InstanceGroupsStrings from './instance-groups.strings'; -import JobStrings from './jobs/jobs.strings'; + +import instanceGroupJobsRoute from '~features/jobs/routes/instanceGroupJobs.route.js'; +import instanceJobsRoute from '~features/jobs/routes/instanceJobs.route.js'; const MODULE_NAME = 'instanceGroups'; @@ -255,73 +253,8 @@ function InstanceGroupsRun ($stateExtender, strings, ComponentsStrings) { resolvedModels: InstanceGroupsResolve }); - $stateExtender.addState({ - name: 'instanceGroups.instanceJobs', - url: '/:instance_group_id/instances/:instance_id/jobs', - ncyBreadcrumb: { - parent: 'instanceGroups.instances', - label: ComponentsStrings.get('layout.JOBS') - }, - views: { - 'instanceJobs@instanceGroups': { - templateUrl: JobsTemplate, - controller: 'InstanceJobsListController', - controllerAs: 'vm' - }, - }, - params: { - job_search: { - value: { - page_size: '10', - order_by: '-finished' - }, - dynamic: true - }, - }, - data: { - socket: { - "groups": { - "jobs": ["status_changed"], - } - } - }, - resolvedModels: InstanceGroupsResolve - }); - - $stateExtender.addState({ - name: 'instanceGroups.jobs', - url: '/:instance_group_id/jobs', - ncyBreadcrumb: { - parent: 'instanceGroups.edit', - label: ComponentsStrings.get('layout.JOBS') - }, - params: { - job_search: { - value: { - page_size: '10', - order_by: '-finished' - }, - dynamic: true - } - }, - data: { - socket: { - "groups": { - "jobs": ["status_changed"], - } - } - }, - views: { - 'jobs@instanceGroups': { - templateUrl: JobsTemplate, - controller: 'InstanceGroupJobsListController', - controllerAs: 'vm' - }, - }, - resolve: { - resolvedModels: InstanceGroupsResolve - } - }); + $stateExtender.addState(instanceJobsRoute); + $stateExtender.addState(instanceGroupJobsRoute); } InstanceGroupsRun.$inject = [ @@ -334,16 +267,13 @@ angular.module(MODULE_NAME, []) .service('InstanceGroupsService', service) .factory('InstanceGroupList', list) .controller('InstanceGroupsListController', InstanceGroupsListController) - .controller('InstanceGroupJobsListController', InstanceGroupJobsListController) .controller('InstanceListController', InstanceListController) - .controller('InstanceJobsListController', InstanceJobsListController) .directive('instanceListPolicy', InstanceListPolicy) .directive('instanceGroupsMultiselect', instanceGroupsMultiselect) .directive('instanceGroupsModal', instanceGroupsModal) .directive('capacityAdjuster', CapacityAdjuster) .directive('capacityBar', CapacityBar) .service('InstanceGroupsStrings', InstanceGroupsStrings) - .service('JobStrings', JobStrings) .run(InstanceGroupsRun); export default MODULE_NAME; diff --git a/awx/ui/client/src/inventories-hosts/inventories/main.js b/awx/ui/client/src/inventories-hosts/inventories/main.js index cf10245ffe..66ff152d23 100644 --- a/awx/ui/client/src/inventories-hosts/inventories/main.js +++ b/awx/ui/client/src/inventories-hosts/inventories/main.js @@ -8,12 +8,11 @@ import adhoc from './adhoc/main'; import group from './related/groups/main'; import sources from './related/sources/main'; import relatedHost from './related/hosts/main'; -import inventoryCompletedJobs from './related/completed-jobs/main'; import inventoryList from './list/main'; import InventoryList from './inventory.list'; import adHocRoute from './adhoc/adhoc.route'; import insights from './insights/main'; -import completedJobsRoute from './related/completed-jobs/completed-jobs.route'; +import completedJobsRoute from '~features/jobs/routes/inventoryCompletedJobs.route.js'; import inventorySourceEditRoute from './related/sources/edit/sources-edit.route'; import inventorySourceEditNotificationsRoute from './related/sources/edit/sources-notifications.route'; import inventorySourceAddRoute from './related/sources/add/sources-add.route'; @@ -53,7 +52,6 @@ angular.module('inventory', [ group.name, sources.name, relatedHost.name, - inventoryCompletedJobs.name, inventoryList.name, insights.name, SmartInventory.name, diff --git a/awx/ui/client/src/inventories-hosts/inventories/related/completed-jobs/completed-jobs.list.js b/awx/ui/client/src/inventories-hosts/inventories/related/completed-jobs/completed-jobs.list.js deleted file mode 100644 index 5ab048c55e..0000000000 --- a/awx/ui/client/src/inventories-hosts/inventories/related/completed-jobs/completed-jobs.list.js +++ /dev/null @@ -1,86 +0,0 @@ -/************************************************* - * Copyright (c) 2015 Ansible, Inc. - * - * All Rights Reserved - *************************************************/ - - -export default ['i18n', function(i18n) { - return { - // These tooltip fields are consumed to build disabled related tabs tooltips in the form > add view - awToolTip: i18n._('Please save and run a job to view.'), - dataPlacement: 'top', - name: 'completed_jobs', - basePath: 'unified_jobs', - iterator: 'completed_job', - search: { - "or__job__inventory": '' - }, - editTitle: i18n._('COMPLETED JOBS'), - index: false, - hover: true, - well: true, - emptyListText: i18n._('No completed jobs'), - - fields: { - status: { - label: '', - columnClass: 'List-staticColumn--smallStatus', - awToolTip: "{{ completed_job.status_tip }}", - awTipPlacement: "right", - dataTitle: "{{ completed_job.status_popover_title }}", - icon: 'icon-job-{{ completed_job.status }}', - iconOnly: true, - uiSref: '{{completed_job.linkToDetails}}', - nosort: true - }, - id: { - label: i18n._('ID'), - uiSref: '{{completed_job.linkToDetails}}', - columnClass: 'col-lg-1 col-md-1 col-sm-2 col-xs-2 List-staticColumnAdjacent', - awToolTip: "{{ completed_job.status_tip }}", - dataPlacement: 'top' - }, - name: { - label: i18n._('Name'), - columnClass: 'col-lg-4 col-md-4 col-sm-4 col-xs-6', - uiSref: '{{completed_job.linkToDetails}}', - awToolTip: "{{ completed_job.name | sanitize }}", - dataPlacement: 'top' - }, - type: { - label: i18n._('Type'), - ngBind: 'completed_job.type_label', - link: false, - columnClass: "col-lg-2 col-md-2 hidden-sm hidden-xs", - }, - finished: { - label: i18n._('Finished'), - noLink: true, - filter: "longDate", - columnClass: "col-lg-3 col-md-3 col-sm-3 hidden-xs", - key: true, - desc: true - } - }, - - actions: { }, - - fieldActions: { - - columnClass: 'col-lg-2 col-md-2 col-sm-3 col-xs-4', - - submit: { - ngShow: "!completed_job.type == 'system_job' || completed_job.summary_fields.user_capabilities.start", - // uses the at-relaunch directive - relaunch: true - }, - "delete": { - mode: 'all', - ngClick: 'deleteJob(completed_job.id)', - awToolTip: i18n._('Delete the job'), - dataPlacement: 'top', - ngShow: 'completed_job.summary_fields.user_capabilities.delete' - } - } - };}]; diff --git a/awx/ui/client/src/inventories-hosts/inventories/related/completed-jobs/completed-jobs.route.js b/awx/ui/client/src/inventories-hosts/inventories/related/completed-jobs/completed-jobs.route.js deleted file mode 100644 index 9c150aa5b2..0000000000 --- a/awx/ui/client/src/inventories-hosts/inventories/related/completed-jobs/completed-jobs.route.js +++ /dev/null @@ -1,60 +0,0 @@ -import { N_ } from '../../../../i18n'; - -export default { - url: "/completed_jobs", - params: { - completed_job_search: { - value: { - page_size: '20', - or__job__inventory:"", - or__adhoccommand__inventory:"", - or__inventoryupdate__inventory_source__inventory:"", - order_by: "-id" - }, - dynamic: true, - squash:"" - } - }, - ncyBreadcrumb: { - label: N_("COMPLETED JOBS") - }, - views: { - 'related': { - templateProvider: function(FormDefinition, GenerateForm) { - let html = GenerateForm.buildCollection({ - mode: 'edit', - related: 'completed_jobs', - form: typeof(FormDefinition) === 'function' ? - FormDefinition() : FormDefinition - }); - return html; - }, - controller: 'JobsList' - } - }, - resolve: { - ListDefinition: ['InventoryCompletedJobsList', (InventoryCompletedJobsList) => { - return InventoryCompletedJobsList; - }], - Dataset: ['InventoryCompletedJobsList', 'QuerySet', '$stateParams', 'GetBasePath', '$interpolate', '$rootScope', - (list, qs, $stateParams, GetBasePath, $interpolate, $rootScope) => { - // allow related list definitions to use interpolated $rootScope / $stateParams in basePath field - let path, interpolator; - if (GetBasePath(list.basePath)) { - path = GetBasePath(list.basePath); - } else { - interpolator = $interpolate(list.basePath); - path = interpolator({ $rootScope: $rootScope, $stateParams: $stateParams }); - } - - let inventory_id = $stateParams.inventory_id ? $stateParams.inventory_id : $stateParams.smartinventory_id; - - $stateParams[`${list.iterator}_search`].or__job__inventory = inventory_id; - $stateParams[`${list.iterator}_search`].or__adhoccommand__inventory = inventory_id; - $stateParams[`${list.iterator}_search`].or__inventoryupdate__inventory_source__inventory = inventory_id; - - return qs.search(path, $stateParams[`${list.iterator}_search`]); - } - ] - } -}; diff --git a/awx/ui/client/src/inventories-hosts/inventories/related/completed-jobs/main.js b/awx/ui/client/src/inventories-hosts/inventories/related/completed-jobs/main.js deleted file mode 100644 index 7326b4c18b..0000000000 --- a/awx/ui/client/src/inventories-hosts/inventories/related/completed-jobs/main.js +++ /dev/null @@ -1,11 +0,0 @@ -/************************************************* - * Copyright (c) 2017 Ansible, Inc. - * - * All Rights Reserved - *************************************************/ - -import list from './completed-jobs.list'; - -export default - angular.module('inventoryCompletedJobs', []) - .factory('InventoryCompletedJobsList', list); diff --git a/awx/ui/client/src/inventories-hosts/inventories/smart-inventory/smart-inventory.form.js b/awx/ui/client/src/inventories-hosts/inventories/smart-inventory/smart-inventory.form.js index 08fc29dd60..46df8595b0 100644 --- a/awx/ui/client/src/inventories-hosts/inventories/smart-inventory/smart-inventory.form.js +++ b/awx/ui/client/src/inventories-hosts/inventories/smart-inventory/smart-inventory.form.js @@ -4,25 +4,7 @@ * All Rights Reserved *************************************************/ -export default ['i18n', 'InventoryCompletedJobsList', function(i18n, InventoryCompletedJobsList) { - - var completed_jobs_object = { - name: 'completed_jobs', - index: false, - basePath: "unified_jobs", - title: i18n._('Completed Jobs'), - iterator: 'completed_job', - generateList: true, - skipGenerator: true, - search: { - "or__job__inventory": '' - }, - ngClick: "$state.go('inventories.editSmartInventory.completed_jobs')" - }; - - let clone = _.clone(InventoryCompletedJobsList); - completed_jobs_object = angular.extend(clone, completed_jobs_object); - +export default ['i18n', function(i18n) { return { addTitle: i18n._('NEW SMART INVENTORY'), @@ -169,7 +151,11 @@ export default ['i18n', 'InventoryCompletedJobsList', function(i18n, InventoryCo ngClick: "$state.go('inventories.editSmartInventory.hosts');", skipGenerator: true }, - completed_jobs: completed_jobs_object + completed_jobs: { + title: i18n._('Completed Jobs'), + skipGenerator: true, + ngClick: "$state.go('inventories.editSmartInventory.completed_jobs')" + } } }; diff --git a/awx/ui/client/src/inventories-hosts/inventories/standard-inventory/inventory.form.js b/awx/ui/client/src/inventories-hosts/inventories/standard-inventory/inventory.form.js index d07b53ec8e..ab8d562088 100644 --- a/awx/ui/client/src/inventories-hosts/inventories/standard-inventory/inventory.form.js +++ b/awx/ui/client/src/inventories-hosts/inventories/standard-inventory/inventory.form.js @@ -10,25 +10,8 @@ * @description This form is for adding/editing an inventory */ -export default ['i18n', 'InventoryCompletedJobsList', -function(i18n, InventoryCompletedJobsList) { - - var completed_jobs_object = { - name: 'completed_jobs', - index: false, - basePath: "unified_jobs", - include: "InventoryCompletedJobsList", - title: i18n._('Completed Jobs'), - iterator: 'completed_job', - generateList: true, - skipGenerator: true, - search: { - "or__job__inventory": '' - } - }; - let clone = _.clone(InventoryCompletedJobsList); - completed_jobs_object = angular.extend(clone, completed_jobs_object); - +export default ['i18n', +function(i18n) { return { addTitle: i18n._('NEW INVENTORY'), @@ -185,7 +168,10 @@ function(i18n, InventoryCompletedJobsList) { iterator: 'inventory_source', skipGenerator: true }, - completed_jobs: completed_jobs_object + completed_jobs: { + title: i18n._('Completed Jobs'), + skipGenerator: true + } }, relatedButtons: { remediate_inventory: { diff --git a/awx/ui/client/src/jobs/all-jobs.list.js b/awx/ui/client/src/jobs/all-jobs.list.js deleted file mode 100644 index 08cb3b99f7..0000000000 --- a/awx/ui/client/src/jobs/all-jobs.list.js +++ /dev/null @@ -1,115 +0,0 @@ -/************************************************* - * Copyright (c) 2015 Ansible, Inc. - * - * All Rights Reserved - *************************************************/ - - -export default ['i18n', function(i18n) { - return { - - name: 'jobs', - basePath: 'unified_jobs', - iterator: 'job', - editTitle: i18n._('ALL JOBS'), - index: false, - hover: true, - well: false, - emptyListText: i18n._('No jobs have yet run.'), - title: false, - - fields: { - status: { - label: '', - columnClass: 'col-lg-1 col-md-1 col-sm-2 col-xs-2 List-staticColumn--smallStatus', - dataTipWatch: 'job.status_tip', - awToolTip: "{{ job.status_tip }}", - awTipPlacement: "right", - dataTitle: "{{ job.status_popover_title }}", - icon: 'icon-job-{{ job.status }}', - iconOnly: true, - uiSref: '{{job.linkToDetails}}', - nosort: true - }, - id: { - label: 'ID', - columnClass: 'col-lg-1 col-md-1 col-sm-2 col-xs-2 List-staticColumnAdjacent', - awToolTip: "{{ job.status_tip }}", - dataPlacement: 'top', - noLink: true - }, - name: { - label: i18n._('Name'), - columnClass: 'col-lg-2 col-md-3 col-sm-4 col-xs-6', - uiSref: '{{job.linkToDetails}}', - badgePlacement: 'right', - badgeCustom: true, - badgeIcon: ` - - W - - ` - }, - type: { - label: i18n._('Type'), - ngBind: 'job.type_label', - link: false, - columnClass: "col-lg-2 hidden-md hidden-sm hidden-xs", - columnShow: "showJobType", - }, - finished: { - label: i18n._('Finished'), - noLink: true, - filter: "longDate", - columnClass: "col-lg-2 col-md-3 col-sm-3 hidden-xs", - key: true, - desc: true - }, - labels: { - label: i18n._('Labels'), - type: 'labels', - nosort: true, - showDelete: false, - columnClass: 'List-tableCell col-lg-4 col-md-4 hidden-sm hidden-xs', - sourceModel: 'labels', - sourceField: 'name' - }, - }, - - actions: { }, - - fieldActions: { - - columnClass: 'col-lg-2 col-md-2 col-sm-3 col-xs-4', - "view": { - mode: "all", - ngClick: "viewjobResults(job)", - awToolTip: i18n._("View the job"), - dataPlacement: "top" - }, - submit: { - ngShow: "!(job.type == 'system_job') && job.summary_fields.user_capabilities.start", - // uses the at-relaunch directive - relaunch: true, - }, - cancel: { - mode: 'all', - ngClick: 'deleteJob(job.id)', - awToolTip: i18n._('Cancel the job'), - dataPlacement: 'top', - ngShow: "(job.status === 'running'|| job.status === 'waiting' || job.status === 'pending') && job.summary_fields.user_capabilities.start" - }, - "delete": { - mode: 'all', - ngClick: 'deleteJob(job.id)', - awToolTip: i18n._('Delete the job'), - dataPlacement: 'top', - ngShow: "(job.status !== 'running' && job.status !== 'waiting' && job.status !== 'pending') && job.summary_fields.user_capabilities.delete" - } - } - }; -}]; diff --git a/awx/ui/client/src/jobs/factories/delete-job.factory.js b/awx/ui/client/src/jobs/factories/delete-job.factory.js deleted file mode 100644 index 3900fc0da1..0000000000 --- a/awx/ui/client/src/jobs/factories/delete-job.factory.js +++ /dev/null @@ -1,145 +0,0 @@ - export default - function DeleteJob($state, Find, Rest, Wait, ProcessErrors, Prompt, Alert, - $filter, i18n) { - return function(params) { - var scope = params.scope, - id = params.id, - job = params.job, - callback = params.callback, - action, jobs, url, action_label, hdr; - - if (!job) { - if (scope.completed_jobs) { - jobs = scope.completed_jobs; - } - else if (scope.running_jobs) { - jobs = scope.running_jobs; - } - else if (scope.queued_jobs) { - jobs = scope.queued_jobs; - } - else if (scope.all_jobs) { - jobs = scope.all_jobs; - } - else if (scope.jobs) { - jobs = scope.jobs; - } - job = Find({list: jobs, key: 'id', val: id }); - } - - if (job.status === 'pending' || job.status === 'running' || job.status === 'waiting') { - url = job.related.cancel; - action_label = 'cancel'; - hdr = i18n._('Cancel'); - } else { - url = job.url; - action_label = 'delete'; - hdr = i18n._('Delete'); - } - - action = function () { - Wait('start'); - Rest.setUrl(url); - if (action_label === 'cancel') { - Rest.post() - .then(() => { - $('#prompt-modal').modal('hide'); - if (callback) { - scope.$emit(callback, action_label); - } - else { - $state.reload(); - Wait('stop'); - } - }) - .catch(({obj, status}) => { - Wait('stop'); - $('#prompt-modal').modal('hide'); - if (status === 403) { - Alert('Error', obj.detail); - } - // Ignore the error. The job most likely already finished. - // ProcessErrors(scope, data, status, null, { hdr: 'Error!', msg: 'Call to ' + url + - // ' failed. POST returned status: ' + status }); - }); - } else { - Rest.destroy() - .then(() => { - $('#prompt-modal').modal('hide'); - if (callback) { - scope.$emit(callback, action_label); - } - else { - let reloadListStateParams = null; - - if(scope.jobs.length === 1 && $state.params.job_search && !_.isEmpty($state.params.job_search.page) && $state.params.job_search.page !== '1') { - reloadListStateParams = _.cloneDeep($state.params); - reloadListStateParams.job_search.page = (parseInt(reloadListStateParams.job_search.page)-1).toString(); - } - - $state.go('.', reloadListStateParams, {reload: true}); - Wait('stop'); - } - }) - .catch(({obj, status}) => { - Wait('stop'); - $('#prompt-modal').modal('hide'); - if (status === 403) { - Alert('Error', obj.detail); - } - // Ignore the error. The job most likely already finished. - //ProcessErrors(scope, data, status, null, { hdr: 'Error!', msg: 'Call to ' + url + - // ' failed. DELETE returned status: ' + status }); - }); - } - }; - - if (scope.removeCancelNotAllowed) { - scope.removeCancelNotAllowed(); - } - scope.removeCancelNotAllowed = scope.$on('CancelNotAllowed', function() { - Wait('stop'); - Alert('Job Completed', 'The request to cancel the job could not be submitted. The job already completed.', 'alert-info'); - }); - - if (scope.removeCancelJob) { - scope.removeCancelJob(); - } - scope.removeCancelJob = scope.$on('CancelJob', function() { - var cancelBody = "
" + i18n._("Are you sure you want to submit the request to cancel this job?") + "
"; - var deleteBody = "
" + i18n._("Are you sure you want to delete this job?") + "
"; - Prompt({ - hdr: hdr, - resourceName: `#${job.id} ` + $filter('sanitize')(job.name), - body: (action_label === 'cancel' || job.status === 'new') ? cancelBody : deleteBody, - action: action, - actionText: (action_label === 'cancel' || job.status === 'new') ? i18n._("OK") : i18n._("DELETE") - }); - }); - - if (action_label === 'cancel') { - Rest.setUrl(url); - Rest.get() - .then(({data}) => { - if (data.can_cancel) { - scope.$emit('CancelJob'); - } - else { - scope.$emit('CancelNotAllowed'); - } - }) - .catch(({data, status}) => { - ProcessErrors(scope, data, status, null, { hdr: 'Error!', msg: 'Call to ' + url + - ' failed. GET returned: ' + status }); - }); - } - else { - scope.$emit('CancelJob'); - } - }; - } - -DeleteJob.$inject = - [ '$state', 'Find', 'Rest', 'Wait', - 'ProcessErrors', 'Prompt', 'Alert', '$filter', 'i18n' - ]; diff --git a/awx/ui/client/src/jobs/jobs-list.controller.js b/awx/ui/client/src/jobs/jobs-list.controller.js deleted file mode 100644 index 9707c87d87..0000000000 --- a/awx/ui/client/src/jobs/jobs-list.controller.js +++ /dev/null @@ -1,143 +0,0 @@ -/************************************************* - * Copyright (c) 2015 Ansible, Inc. - * - * All Rights Reserved - *************************************************/ - -/** - * @ngdoc function - * @name controllers.function:Jobs - * @description This controller's for the jobs page - */ - - export default ['$state', '$rootScope', '$scope', '$stateParams', 'Find', 'DeleteJob', - 'GetBasePath', 'Dataset', 'QuerySet', 'ListDefinition', '$interpolate', - function($state, $rootScope, $scope, $stateParams, Find, DeleteJob, - GetBasePath, Dataset, qs, ListDefinition, $interpolate) { - - var list = ListDefinition; - - init(); - - function init() { - // search init - $scope.list = list; - $scope[`${list.iterator}_dataset`] = Dataset.data; - $scope[list.name] = $scope[`${list.iterator}_dataset`].results; - - $scope.showJobType = true; - } - - $scope.$on(`${list.iterator}_options`, function(event, data){ - $scope.options = data.data.actions.GET; - optionsRequestDataProcessing(); - }); - - $scope.$watchCollection(`${$scope.list.name}`, function() { - optionsRequestDataProcessing(); - } - ); - - // iterate over the list and add fields like type label, after the - // OPTIONS request returns, or the list is sorted/paginated/searched - function optionsRequestDataProcessing(){ - - if($scope[list.name] && $scope[list.name].length > 0) { - $scope[list.name].forEach(function(item, item_idx) { - var itm = $scope[list.name][item_idx]; - - switch (item.type) { - case 'job': - item.linkToDetails = `jobResult({id: ${item.id}})`; - break; - case 'ad_hoc_command': - item.linkToDetails = `adHocJobStdout({id: ${item.id}})`; - break; - case 'system_job': - item.linkToDetails = `managementJobStdout({id: ${item.id}})`; - break; - case 'project_update': - item.linkToDetails = `scmUpdateStdout({id: ${item.id}})`; - break; - case 'inventory_update': - item.linkToDetails = `inventorySyncStdout({id: ${item.id}})`; - break; - case 'workflow_job': - item.linkToDetails = `workflowResults({id: ${item.id}})`; - break; - } - - if(item.summary_fields && item.summary_fields.source_workflow_job && - item.summary_fields.source_workflow_job.id){ - item.workflow_result_link = `/#/workflows/${item.summary_fields.source_workflow_job.id}`; - } - - // Set the item type label - if (list.fields.type && $scope.options && - $scope.options.hasOwnProperty('type')) { - $scope.options.type.choices.forEach(function(choice) { - if (choice[0] === item.type) { - itm.type_label = choice[1]; - } - }); - } - buildTooltips(itm); - }); - } - } - function buildTooltips(job) { - job.status_tip = 'Job ' + job.status + ". Click for details."; - } - - $scope.deleteJob = function(id) { - DeleteJob({ scope: $scope, id: id }); - }; - - $scope.viewjobResults = function(job) { - - var goTojobResults = function(state) { - $state.go(state, { id: job.id }, { reload: true }); - }; - switch (job.type) { - case 'job': - goTojobResults('jobResult'); - break; - case 'ad_hoc_command': - goTojobResults('adHocJobStdout'); - break; - case 'system_job': - goTojobResults('managementJobStdout'); - break; - case 'project_update': - goTojobResults('scmUpdateStdout'); - break; - case 'inventory_update': - goTojobResults('inventorySyncStdout'); - break; - case 'workflow_job': - goTojobResults('workflowResults'); - break; - } - - }; - - $scope.$on('ws-jobs', function(){ - let path; - if (GetBasePath(list.basePath) || GetBasePath(list.name)) { - path = GetBasePath(list.basePath) || GetBasePath(list.name); - } else { - // completed jobs base path involves $stateParams - let interpolator = $interpolate(list.basePath); - path = interpolator({ $rootScope: $rootScope, $stateParams: $stateParams }); - } - qs.search(path, $state.params[`${list.iterator}_search`]) - .then(function(searchResponse) { - $scope[`${list.iterator}_dataset`] = searchResponse.data; - $scope[list.name] = $scope[`${list.iterator}_dataset`].results; - }); - }); - - $scope.$on('ws-schedules', function(){ - $state.reload(); - }); -}]; diff --git a/awx/ui/client/src/jobs/jobs.partial.html b/awx/ui/client/src/jobs/jobs.partial.html deleted file mode 100644 index 46f7b09761..0000000000 --- a/awx/ui/client/src/jobs/jobs.partial.html +++ /dev/null @@ -1,23 +0,0 @@ -
-
-
-
-
- - -
-
- -
-
-
-
-
-
-
diff --git a/awx/ui/client/src/jobs/main.js b/awx/ui/client/src/jobs/main.js deleted file mode 100644 index 2bb8f0a7a5..0000000000 --- a/awx/ui/client/src/jobs/main.js +++ /dev/null @@ -1,15 +0,0 @@ -/************************************************* - * Copyright (c) 2017 Ansible, Inc. - * - * All Rights Reserved - *************************************************/ - -import jobsList from './jobs-list.controller'; -import DeleteJob from './factories/delete-job.factory'; -import AllJobsList from './all-jobs.list'; - -export default - angular.module('JobsModule', []) - .controller('JobsList', jobsList) - .factory('DeleteJob', DeleteJob) - .factory('AllJobsList', AllJobsList); diff --git a/awx/ui/client/src/management-jobs/main.js b/awx/ui/client/src/management-jobs/main.js index 12d25fbc6b..7b850261b9 100644 --- a/awx/ui/client/src/management-jobs/main.js +++ b/awx/ui/client/src/management-jobs/main.js @@ -6,7 +6,6 @@ import managementJobsCard from './card/main'; import managementJobsScheduler from './scheduler/main'; -import list from './management-jobs.list'; import managementJobsNotifications from './notifications/main'; export default @@ -15,4 +14,3 @@ export default managementJobsScheduler.name, managementJobsNotifications.name ]) - .factory('managementJobsListObject', list); diff --git a/awx/ui/client/src/management-jobs/management-jobs.list.js b/awx/ui/client/src/management-jobs/management-jobs.list.js deleted file mode 100644 index 7ad1af547a..0000000000 --- a/awx/ui/client/src/management-jobs/management-jobs.list.js +++ /dev/null @@ -1,43 +0,0 @@ -/************************************************* - * Copyright (c) 2015 Ansible, Inc. - * - * All Rights Reserved - *************************************************/ - -export default function(){ - return { - name: 'configure_jobs', - iterator: 'configure_job', - index: false, - hover: true, - listTitle: 'MANAGEMENT JOBS', - - fields: { - name: { - label: 'Name', - columnClass: 'col-sm-4 col-xs-4', - awToolTip: '{{configure_job.description | sanitize}}', - dataPlacement: 'top' - } - }, - actions: { - - }, - fieldActions: { - submit: { - label: 'Launch', - mode: 'all', - ngClick: 'submitJob(configure_job.id, configure_job.name)', - awToolTip: 'Start a job using this template', - dataPlacement: 'top' - }, - schedule: { - label: 'Schedule', - mode: 'all', - ngClick: 'configureSchedule()', - awToolTip: 'Schedule job template runs', - dataPlacement: 'top', - } - } - }; -} diff --git a/awx/ui/client/src/portal-mode/jobs/portal-mode-all-jobs.route.js b/awx/ui/client/src/portal-mode/jobs/portal-mode-all-jobs.route.js deleted file mode 100644 index 582f806b89..0000000000 --- a/awx/ui/client/src/portal-mode/jobs/portal-mode-all-jobs.route.js +++ /dev/null @@ -1,49 +0,0 @@ -import { PortalModeJobsController } from '../portal-mode-jobs.controller'; - -// Using multiple named views requires a parent layout -// https://github.com/angular-ui/ui-router/wiki/Multiple-Named-Views -export default { - name: 'portalMode.allJobs', - url: '/alljobs?{job_search:queryset}', - ncyBreadcrumb: { - skip: true - }, - params: { - job_search: { - value: { - page_size: '20', - order_by: '-finished' - }, - dynamic: true - } - }, - data: { - socket: { - "groups": { - "jobs": ["status_changed"] - } - } - }, - views: { - 'jobs@portalMode': { - templateProvider: function(PortalJobsList, generateList) { - let html = generateList.build({ - list: PortalJobsList, - mode: 'edit' - }); - return html; - }, - controller: PortalModeJobsController - } - }, - resolve: { - jobsDataset: ['PortalJobsList', 'QuerySet', '$rootScope', '$stateParams', 'GetBasePath', - function(list, qs, $rootScope, $stateParams, GetBasePath) { - let path = GetBasePath(list.basePath) || GetBasePath(list.name); - return $rootScope.loginConfig.promise.then(() => { - return qs.search(path, $stateParams[`${list.iterator}_search`]); - }); - } - ] - } -}; diff --git a/awx/ui/client/src/portal-mode/jobs/portal-mode-my-jobs.route.js b/awx/ui/client/src/portal-mode/jobs/portal-mode-my-jobs.route.js deleted file mode 100644 index 9d5c0382f3..0000000000 --- a/awx/ui/client/src/portal-mode/jobs/portal-mode-my-jobs.route.js +++ /dev/null @@ -1,51 +0,0 @@ -import { PortalModeJobsController } from '../portal-mode-jobs.controller'; - -// Using multiple named views requires a parent layout -// https://github.com/angular-ui/ui-router/wiki/Multiple-Named-Views -export default { - name: 'portalMode.myJobs', - url: '/myjobs?{job_search:queryset}', - ncyBreadcrumb: { - skip: true - }, - params: { - job_search: { - value: { - page_size: '20', - order_by: '-finished', - created_by: null - }, - dynamic: true - } - }, - data: { - socket: { - "groups": { - "jobs": ["status_changed"] - } - } - }, - views: { - 'jobs@portalMode': { - templateProvider: function(PortalJobsList, generateList) { - let html = generateList.build({ - list: PortalJobsList, - mode: 'edit' - }); - return html; - }, - controller: PortalModeJobsController - } - }, - resolve: { - jobsDataset: ['PortalJobsList', 'QuerySet', '$rootScope', '$stateParams', 'GetBasePath', - function(list, qs, $rootScope, $stateParams, GetBasePath) { - let path = GetBasePath(list.basePath) || GetBasePath(list.name); - return $rootScope.loginConfig.promise.then(() => { - $stateParams[`${list.iterator}_search`].created_by = $rootScope.current_user.id; - return qs.search(path, $stateParams[`${list.iterator}_search`]); - }); - } - ] - } -}; diff --git a/awx/ui/client/src/portal-mode/main.js b/awx/ui/client/src/portal-mode/main.js index a88d3f86b9..e4e1dc2a2c 100644 --- a/awx/ui/client/src/portal-mode/main.js +++ b/awx/ui/client/src/portal-mode/main.js @@ -5,17 +5,15 @@ *************************************************/ import route from './portal-mode.route'; -import myJobsRoute from './jobs/portal-mode-my-jobs.route'; -import allJobsRoute from './jobs/portal-mode-all-jobs.route'; -import PortalJobsList from './portal-jobs.list'; +import myJobsRoute from '~features/jobs/routes/portalModeMyJobs.route.js'; +import allJobsRoute from '~features/jobs/routes/portalModeAllJobs.route.js'; import PortalJobTemplateList from './portal-job-templates.list'; export default angular.module('portalMode', []) - .factory('PortalJobsList', PortalJobsList) .factory('PortalJobTemplateList', PortalJobTemplateList) .run(['$stateExtender', function($stateExtender){ - $stateExtender.addState(route); - $stateExtender.addState(myJobsRoute); - $stateExtender.addState(allJobsRoute); + $stateExtender.addState(route); + $stateExtender.addState(myJobsRoute); + $stateExtender.addState(allJobsRoute); }]); diff --git a/awx/ui/client/src/portal-mode/portal-jobs.list.js b/awx/ui/client/src/portal-mode/portal-jobs.list.js deleted file mode 100644 index 24f9b2afe3..0000000000 --- a/awx/ui/client/src/portal-mode/portal-jobs.list.js +++ /dev/null @@ -1,50 +0,0 @@ -/************************************************* - * Copyright (c) 2015 Ansible, Inc. - * - * All Rights Reserved - *************************************************/ - - -export default ['i18n', function(i18n) { - return { - - name: 'jobs', - iterator: 'job', - editTitle: i18n._('JOBS'), - index: false, - hover: true, - well: true, - listTitle: i18n._('JOBS'), - emptyListText: i18n._('There are no jobs to display at this time'), - searchBarFullWidth: true, - - fields: { - status: { - label: '', - columnClass: 'List-staticColumn--smallStatus', - dataTitle: "{{ job.status_popover_title }}", - icon: 'icon-job-{{ job.status }}', - iconOnly: true, - nosort: true, - awTipPlacement: "top", - awToolTip: "{{ job.status_tip }}", - dataTipWatch: 'job.status_tip', - ngClick:"viewjobResults(job)", - }, - name: { - label: i18n._('Name'), - columnClass: 'col-lg-4 col-md-4 col-sm-4 col-xs-6 List-staticColumnAdjacent', - linkTo: '/#/jobs/{{job.id}}', - }, - finished: { - label: i18n._('Finished'), - noLink: true, - filter: "longDate", - key: true, - desc: true, - columnClass: "col-lg-4 col-md-4 col-sm-3" - } - }, - - actions: { } - };}]; diff --git a/awx/ui/client/src/portal-mode/portal-mode-jobs.controller.js b/awx/ui/client/src/portal-mode/portal-mode-jobs.controller.js deleted file mode 100644 index b297e126eb..0000000000 --- a/awx/ui/client/src/portal-mode/portal-mode-jobs.controller.js +++ /dev/null @@ -1,105 +0,0 @@ -/************************************************* - * Copyright (c) 2016 Ansible, Inc. - * - * All Rights Reserved - *************************************************/ - -export function PortalModeJobsController($scope, $state, qs, GetBasePath, PortalJobsList, Dataset) { - - var list = PortalJobsList; - - $scope.$on('ws-jobs', function() { - let path = GetBasePath(list.basePath) || GetBasePath(list.name); - qs.search(path, $state.params[`${list.iterator}_search`]) - .then(function(searchResponse) { - $scope[`${list.iterator}_dataset`] = searchResponse.data; - $scope[list.name] = $scope[`${list.iterator}_dataset`].results; - }); - }); - - init(); - - function init(data) { - let d = (!data) ? Dataset : data; - // search init - $scope.list = list; - $scope[`${list.iterator}_dataset`] = d.data; - $scope[list.name] = $scope[`${list.iterator}_dataset`].results; - - $scope.iterator = list.iterator; - } - - $scope.refresh = function() { - $state.go('.', null, {reload: true}); - }; - - $scope.$on(`${list.iterator}_options`, function(event, data){ - $scope.options = data.data.actions.GET; - optionsRequestDataProcessing(); - }); - - $scope.$watchCollection(`${$scope.list.name}`, function() { - optionsRequestDataProcessing(); - } - ); - - // iterate over the list and add fields like type label, after the - // OPTIONS request returns, or the list is sorted/paginated/searched - function optionsRequestDataProcessing(){ - - if($scope[list.name] && $scope[list.name].length > 0) { - $scope[list.name].forEach(function(item, item_idx) { - var itm = $scope[list.name][item_idx]; - - if(item.summary_fields && item.summary_fields.source_workflow_job && - item.summary_fields.source_workflow_job.id){ - item.workflow_result_link = `/#/workflows/${item.summary_fields.source_workflow_job.id}`; - } - - // Set the item type label - if (list.fields.type && $scope.options && - $scope.options.hasOwnProperty('type')) { - $scope.options.type.choices.forEach(function(choice) { - if (choice[0] === item.type) { - itm.type_label = choice[1]; - } - }); - } - buildTooltips(itm); - }); - } - } - function buildTooltips(job) { - job.status_tip = `Job ${job.status}. Click for details.`; - } - - $scope.viewjobResults = function(job) { - - var goTojobResults = function(state) { - $state.go(state, { id: job.id }, { reload: true }); - }; - switch (job.type) { - case 'job': - goTojobResults('jobResult'); - break; - case 'ad_hoc_command': - goTojobResults('adHocJobStdout'); - break; - case 'system_job': - goTojobResults('managementJobStdout'); - break; - case 'project_update': - goTojobResults('scmUpdateStdout'); - break; - case 'inventory_update': - goTojobResults('inventorySyncStdout'); - break; - case 'workflow_job': - goTojobResults('workflowResults'); - break; - } - - }; -} - -PortalModeJobsController.$inject = ['$scope', '$state', 'QuerySet', 'GetBasePath', 'PortalJobsList', 'jobsDataset']; diff --git a/awx/ui/client/src/portal-mode/portal-mode-jobs.partial.html b/awx/ui/client/src/portal-mode/portal-mode-jobs.partial.html deleted file mode 100644 index 8543683d7c..0000000000 --- a/awx/ui/client/src/portal-mode/portal-mode-jobs.partial.html +++ /dev/null @@ -1,26 +0,0 @@ -
-
-
- - -
-
- -
-
-
-
-
diff --git a/awx/ui/client/src/templates/completed-jobs.list.js b/awx/ui/client/src/templates/completed-jobs.list.js deleted file mode 100644 index 54ba53a48e..0000000000 --- a/awx/ui/client/src/templates/completed-jobs.list.js +++ /dev/null @@ -1,87 +0,0 @@ -/************************************************* - * Copyright (c) 2015 Ansible, Inc. - * - * All Rights Reserved - *************************************************/ - - -export default ['i18n', function(i18n) { - return { - // These tooltip fields are consumed to build disabled related tabs tooltips in the form > add view - awToolTip: i18n._('Please save and run a job to view.'), - dataPlacement: 'top', - name: 'completed_jobs', - basePath: 'api/v2/job_templates/{{$stateParams.job_template_id}}/jobs', - search: { - or__status__in: "successful,failed,error,canceled", - order_by: "-id" - }, - iterator: 'completed_job', - editTitle: i18n._('COMPLETED JOBS'), - index: false, - hover: true, - well: false, - emptyListText: i18n._('No completed jobs'), - - fields: { - status: { - label: '', - columnClass: 'List-staticColumn--smallStatus', - awToolTip: "{{ completed_job.status_tip }}", - awTipPlacement: "right", - dataTitle: "{{ completed_job.status_popover_title }}", - icon: 'icon-job-{{ completed_job.status }}', - iconOnly: true, - uiSref: '{{completed_job.linkToDetails}}', - nosort: true - }, - id: { - label: 'ID', - uiSref: '{{completed_job.linkToDetails}}', - columnClass: 'col-lg-1 col-md-1 col-sm-2 col-xs-2 List-staticColumnAdjacent', - awToolTip: "{{ completed_job.status_tip }}", - dataPlacement: 'top' - }, - name: { - label: i18n._('Name'), - columnClass: 'col-lg-4 col-md-4 col-sm-4 col-xs-6', - uiSref: '{{completed_job.linkToDetails}}', - awToolTip: "{{ completed_job.name | sanitize }}", - dataPlacement: 'top' - }, - type: { - label: i18n._('Type'), - ngBind: 'completed_job.type_label', - link: false, - columnClass: "col-lg-2 col-md-2 hidden-sm hidden-xs", - }, - finished: { - label: i18n._('Finished'), - noLink: true, - filter: "longDate", - columnClass: "col-lg-3 col-md-3 col-sm-3 hidden-xs", - key: true, - desc: true - } - }, - - actions: { }, - - fieldActions: { - - columnClass: 'col-lg-2 col-md-2 col-sm-3 col-xs-4', - - submit: { - ngShow: "!completed_job.type == 'system_job' || completed_job.summary_fields.user_capabilities.start", - // uses the at-relaunch directive - relaunch: true - }, - "delete": { - mode: 'all', - ngClick: 'deleteJob(completed_job.id)', - awToolTip: i18n._('Delete the job'), - dataPlacement: 'top', - ngShow: 'completed_job.summary_fields.user_capabilities.delete' - } - } - };}]; diff --git a/awx/ui/client/src/templates/job_templates/job-template.form.js b/awx/ui/client/src/templates/job_templates/job-template.form.js index 422d722c3a..fc24852e2d 100644 --- a/awx/ui/client/src/templates/job_templates/job-template.form.js +++ b/awx/ui/client/src/templates/job_templates/job-template.form.js @@ -11,8 +11,8 @@ */ -export default ['NotificationsList', 'CompletedJobsList', 'i18n', -function(NotificationsList, CompletedJobsList, i18n) { +export default ['NotificationsList', 'i18n', +function(NotificationsList, i18n) { return function() { var JobTemplateFormObject = { @@ -433,7 +433,9 @@ function(NotificationsList, CompletedJobsList, i18n) { include: "NotificationsList" }, "completed_jobs": { - include: "CompletedJobsList" + title: i18n._('Completed Jobs'), + skipGenerator: true, + ngClick: "$state.go('templates.editJobTemplate.completed_jobs')" } }, @@ -473,11 +475,6 @@ function(NotificationsList, CompletedJobsList, i18n) { JobTemplateFormObject.related[itm].ngClick = "$state.go('templates.editJobTemplate.notifications')"; JobTemplateFormObject.related[itm].generateList = true; // tell form generator to call list generator and inject a list } - if (JobTemplateFormObject.related[itm].include === "CompletedJobsList") { - JobTemplateFormObject.related[itm] = CompletedJobsList; - JobTemplateFormObject.related[itm].ngClick = "$state.go('templates.editJobTemplate.completed_jobs')"; - JobTemplateFormObject.related[itm].generateList = true; - } } return JobTemplateFormObject; diff --git a/awx/ui/client/src/templates/main.js b/awx/ui/client/src/templates/main.js index c2f2d0e9a6..f9280252a0 100644 --- a/awx/ui/client/src/templates/main.js +++ b/awx/ui/client/src/templates/main.js @@ -16,11 +16,11 @@ import workflowMaker from './workflows/workflow-maker/main'; import workflowControls from './workflows/workflow-controls/main'; import workflowService from './workflows/workflow.service'; import WorkflowForm from './workflows.form'; -import CompletedJobsList from './completed-jobs.list'; import InventorySourcesList from './inventory-sources.list'; import TemplateList from './templates.list'; import TemplatesStrings from './templates.strings'; import listRoute from '~features/templates/list.route.js'; +import templateCompletedJobsRoute from '~features/jobs/routes/templateCompletedJobs.route.js'; export default angular.module('templates', [surveyMaker.name, jobTemplates.name, labels.name, prompt.name, workflowAdd.name, workflowEdit.name, @@ -29,7 +29,6 @@ angular.module('templates', [surveyMaker.name, jobTemplates.name, labels.name, p .service('TemplatesService', templatesService) .service('WorkflowService', workflowService) .factory('WorkflowForm', WorkflowForm) - .factory('CompletedJobsList', CompletedJobsList) // TODO: currently being kept arround for rbac selection, templates within projects and orgs, etc. .factory('TemplateList', TemplateList) .value('InventorySourcesList', InventorySourcesList) @@ -151,10 +150,7 @@ angular.module('templates', [surveyMaker.name, jobTemplates.name, labels.name, p modes: ['edit'], form: 'JobTemplateForm', controllers: { - edit: 'JobTemplateEdit', - related: { - completed_jobs: 'JobsList' - } + edit: 'JobTemplateEdit' }, data: { activityStream: true, @@ -742,6 +738,7 @@ angular.module('templates', [surveyMaker.name, jobTemplates.name, labels.name, p return result.concat(definition.states); }, [ stateExtender.buildDefinition(listRoute), + stateExtender.buildDefinition(templateCompletedJobsRoute), stateExtender.buildDefinition(workflowMaker) ]) };