From 95f80ce512836cce319c4b1b2e4bc4c8c0c19beb Mon Sep 17 00:00:00 2001 From: John Mitchell Date: Thu, 22 Mar 2018 18:56:22 -0400 Subject: [PATCH 1/4] implement new style jobs list in ui --- awx/ui/client/features/index.js | 4 +- awx/ui/client/features/jobs/index.js | 13 ++ awx/ui/client/features/jobs/index.view.html | 19 +++ awx/ui/client/features/jobs/jobs.route.js | 67 +++++++++ awx/ui/client/features/jobs/jobs.strings.js | 20 +++ .../features/jobs/jobsList.controller.js | 137 ++++++++++++++++++ .../client/features/jobs/jobsList.view.html | 82 +++++++++++ awx/ui/client/lib/components/list/_index.less | 24 +++ .../lib/components/list/row-item.directive.js | 3 + .../lib/components/list/row-item.partial.html | 14 +- awx/ui/client/lib/models/UnifiedJob.js | 21 +++ awx/ui/client/lib/models/index.js | 2 + awx/ui/client/lib/theme/_variables.less | 3 + .../instance-jobs/instance-jobs.controller.js | 2 +- awx/ui/client/src/jobs/jobs.route.js | 59 -------- awx/ui/client/src/jobs/main.js | 4 - awx/ui/client/src/scheduler/main.js | 2 +- .../templates/labels/labelsList.directive.js | 5 + 18 files changed, 412 insertions(+), 69 deletions(-) create mode 100644 awx/ui/client/features/jobs/index.js create mode 100644 awx/ui/client/features/jobs/index.view.html create mode 100644 awx/ui/client/features/jobs/jobs.route.js create mode 100644 awx/ui/client/features/jobs/jobs.strings.js create mode 100644 awx/ui/client/features/jobs/jobsList.controller.js create mode 100644 awx/ui/client/features/jobs/jobsList.view.html create mode 100644 awx/ui/client/lib/models/UnifiedJob.js delete mode 100644 awx/ui/client/src/jobs/jobs.route.js diff --git a/awx/ui/client/features/index.js b/awx/ui/client/features/index.js index 01216e575f..763894c93c 100644 --- a/awx/ui/client/features/index.js +++ b/awx/ui/client/features/index.js @@ -6,6 +6,7 @@ import atFeaturesApplications from '~features/applications'; import atFeaturesCredentials from '~features/credentials'; import atFeaturesTemplates from '~features/templates'; import atFeaturesUsers from '~features/users'; +import atFeaturesJobs from '~features/jobs'; const MODULE_NAME = 'at.features'; @@ -16,7 +17,8 @@ angular.module(MODULE_NAME, [ atFeaturesApplications, atFeaturesCredentials, atFeaturesTemplates, - atFeaturesUsers + atFeaturesUsers, + atFeaturesJobs ]); export default MODULE_NAME; diff --git a/awx/ui/client/features/jobs/index.js b/awx/ui/client/features/jobs/index.js new file mode 100644 index 0000000000..7212944ddc --- /dev/null +++ b/awx/ui/client/features/jobs/index.js @@ -0,0 +1,13 @@ +import JobsStrings from './jobs.strings'; +import jobsRoute from './jobs.route'; + +const MODULE_NAME = 'at.features.jobs'; + +angular + .module(MODULE_NAME, []) + .service('JobsStrings', JobsStrings) + .run(['$stateExtender', ($stateExtender) => { + $stateExtender.addState(jobsRoute); + }]); + +export default MODULE_NAME; diff --git a/awx/ui/client/features/jobs/index.view.html b/awx/ui/client/features/jobs/index.view.html new file mode 100644 index 0000000000..054e26c2ba --- /dev/null +++ b/awx/ui/client/features/jobs/index.view.html @@ -0,0 +1,19 @@ +
+ +
+
+ + JOBS + +
+
+
+ + SCHEDULES + +
+
+
+
+
+
diff --git a/awx/ui/client/features/jobs/jobs.route.js b/awx/ui/client/features/jobs/jobs.route.js new file mode 100644 index 0000000000..4aed40d11d --- /dev/null +++ b/awx/ui/client/features/jobs/jobs.route.js @@ -0,0 +1,67 @@ +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'); + +export default { + searchPrefix: 'job', + name: 'jobs', + url: '/jobs', + ncyBreadcrumb: { + label: N_('JOBS') + }, + params: { + job_search: { + value: { + not__launch_type: 'sync', + order_by: '-finished' + }, + dynamic: true, + squash: false + } + }, + data: { + socket: { + groups: { + jobs: ['status_changed'], + schedules: ['changed'] + } + } + }, + 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')); + } + ], + }, + views: { + '@': { + templateUrl: indexTemplate + }, + 'jobsList@jobs': { + templateUrl: jobsListTemplate, + controller: jobsListController, + controllerAs: 'vm' + } + } +}; diff --git a/awx/ui/client/features/jobs/jobs.strings.js b/awx/ui/client/features/jobs/jobs.strings.js new file mode 100644 index 0000000000..a21c2b62e9 --- /dev/null +++ b/awx/ui/client/features/jobs/jobs.strings.js @@ -0,0 +1,20 @@ +function JobsStrings (BaseString) { + BaseString.call(this, 'jobs'); + + const { t } = this; + const ns = this.jobs; + + ns.list = { + ROW_ITEM_LABEL_STARTED: t.s('Started'), + ROW_ITEM_LABEL_FINISHED: t.s('Finished'), + ROW_ITEM_LABEL_LAUNCHED_BY: t.s('Launched By'), + ROW_ITEM_LABEL_JOB_TEMPLATE: t.s('Job Template'), + ROW_ITEM_LABEL_INVENTORY: t.s('Inventory'), + ROW_ITEM_LABEL_PROJECT: t.s('Project'), + ROW_ITEM_LABEL_CREDENTIALS: t.s('Credentials'), + }; +} + +JobsStrings.$inject = ['BaseStringService']; + +export default JobsStrings; diff --git a/awx/ui/client/features/jobs/jobsList.controller.js b/awx/ui/client/features/jobs/jobsList.controller.js new file mode 100644 index 0000000000..b78a1b77b6 --- /dev/null +++ b/awx/ui/client/features/jobs/jobsList.controller.js @@ -0,0 +1,137 @@ +/** *********************************************** + * Copyright (c) 2018 Ansible, Inc. + * + * All Rights Reserved + ************************************************ */ +const mapChoices = choices => Object + .assign(...choices.map(([k, v]) => ({ [k]: v }))); + +function ListJobsController ( + $scope, + $state, + Dataset, + resolvedModels, + strings, + qs, + Prompt, + $filter, + ProcessErrors, + Wait, + Rest +) { + const vm = this || {}; + const [unifiedJob] = resolvedModels; + + vm.strings = strings; + + // smart-search + const name = 'jobs'; + const iterator = 'job'; + const key = 'job_dataset'; + + $scope.list = { iterator, name }; + $scope.collection = { iterator, basePath: 'unified_jobs' }; + $scope[key] = Dataset.data; + $scope[name] = Dataset.data.results; + $scope.$on('updateDataset', (e, dataset) => { + $scope[key] = dataset; + $scope[name] = dataset.results; + }); + $scope.$on('ws-jobs', () => { + qs.search(unifiedJob.path, $state.params.job_search) + .then(({ data }) => { + $scope.$emit('updateDataset', data); + }); + }); + + vm.jobTypes = mapChoices(unifiedJob + .options('actions.GET.type.choices')); + + vm.getLink = ({ type, id }) => { + let link; + + switch (type) { + case 'job': + link = `/#/jobs/${id}`; + break; + case 'ad_hoc_command': + link = `/#/ad_hoc_commands/${id}`; + break; + case 'system_job': + link = `/#/management_jobs/${id}`; + break; + case 'project_update': + link = `/#/scm_update/${id}`; + break; + case 'inventory_update': + link = `/#/inventory_sync/${id}`; + break; + case 'workflow_job': + link = `/#/workflows/${id}`; + break; + default: + link = ''; + break; + } + + return link; + }; + + vm.deleteJob = (job) => { + const action = () => { + $('#prompt-modal').modal('hide'); + Wait('start'); + Rest.setUrl(job.url); + Rest.destroy() + .then(() => { + let reloadListStateParams = null; + + if ($scope.jobs.length === 1 && $state.params.job_search && + !_.isEmpty($state.params.job_search.page) && + $state.params.job_search.page !== '1') { + const page = `${(parseInt(reloadListStateParams + .job_search.page, 10) - 1)}`; + reloadListStateParams = _.cloneDeep($state.params); + reloadListStateParams.job_search.page = page; + } + + $state.go('.', reloadListStateParams, { reload: true }); + }) + .catch(({ data, status }) => { + ProcessErrors($scope, data, status, null, { + hdr: strings.get('error.HEADER'), + msg: strings.get('error.CALL', { path: `${job.url}`, status }) + }); + }) + .finally(() => { + Wait('stop'); + }); + }; + + const deleteModalBody = `
${strings.get('deleteResource.CONFIRM', 'job')}
`; + + Prompt({ + hdr: strings.get('deleteResource.HEADER'), + resourceName: $filter('sanitize')(job.name), + body: deleteModalBody, + action, + actionText: 'DELETE' + }); + }; +} + +ListJobsController.$inject = [ + '$scope', + '$state', + 'Dataset', + 'resolvedModels', + 'JobsStrings', + 'QuerySet', + 'Prompt', + '$filter', + 'ProcessErrors', + 'Wait', + 'Rest' +]; + +export default ListJobsController; diff --git a/awx/ui/client/features/jobs/jobsList.view.html b/awx/ui/client/features/jobs/jobsList.view.html new file mode 100644 index 0000000000..85f54bbfdc --- /dev/null +++ b/awx/ui/client/features/jobs/jobsList.view.html @@ -0,0 +1,82 @@ + +
+ + +
+ + + +
+ + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+
+
+ + +
diff --git a/awx/ui/client/lib/components/list/_index.less b/awx/ui/client/lib/components/list/_index.less index b4eac97d30..d053764fe0 100644 --- a/awx/ui/client/lib/components/list/_index.less +++ b/awx/ui/client/lib/components/list/_index.less @@ -151,6 +151,10 @@ line-height: @at-height-list-row-item; } +.at-RowItem-status { + margin-right: @at-margin-right-list-row-item-status; +} + .at-RowItem--isHeader { color: @at-color-body-text; margin-bottom: @at-margin-bottom-list-header; @@ -263,6 +267,16 @@ margin: 2px 20px 0 0; } +.at-RowItem--inline { + display: inline-flex; + margin-right: @at-margin-right-list-row-item-inline; + + .at-RowItem-label { + width: auto; + margin-right: @at-margin-right-list-row-item-inline-label; + } +} + @media screen and (max-width: @at-breakpoint-compact-list) { .at-Row-actions { flex-direction: column; @@ -271,4 +285,14 @@ .at-RowAction { margin: @at-margin-list-row-action-mobile; } + + .at-RowItem--inline { + display: flex; + margin-right: inherit; + + .at-RowItem-label { + width: @at-width-list-row-item-label; + margin-right: inherit; + } + } } diff --git a/awx/ui/client/lib/components/list/row-item.directive.js b/awx/ui/client/lib/components/list/row-item.directive.js index e07820468e..296aa28249 100644 --- a/awx/ui/client/lib/components/list/row-item.directive.js +++ b/awx/ui/client/lib/components/list/row-item.directive.js @@ -7,10 +7,13 @@ function atRowItem () { transclude: true, templateUrl, scope: { + inline: '@', badge: '@', headerValue: '@', headerLink: '@', headerTag: '@', + status: '@', + statusTip: '@', labelValue: '@', labelLink: '@', labelState: '@', diff --git a/awx/ui/client/lib/components/list/row-item.partial.html b/awx/ui/client/lib/components/list/row-item.partial.html index ca58947b79..d504f0f928 100644 --- a/awx/ui/client/lib/components/list/row-item.partial.html +++ b/awx/ui/client/lib/components/list/row-item.partial.html @@ -1,5 +1,13 @@ -
+
+
+ + + + +
@@ -41,4 +49,4 @@ {{ tag.name }}
- \ No newline at end of file + diff --git a/awx/ui/client/lib/models/UnifiedJob.js b/awx/ui/client/lib/models/UnifiedJob.js new file mode 100644 index 0000000000..13078f8fa2 --- /dev/null +++ b/awx/ui/client/lib/models/UnifiedJob.js @@ -0,0 +1,21 @@ +let Base; + +function UnifiedJobModel (method, resource, config) { + Base.call(this, 'unified_jobs'); + + this.Constructor = UnifiedJobModel; + + return this.create(method, resource, config); +} + +function UnifiedJobModelLoader (BaseModel) { + Base = BaseModel; + + return UnifiedJobModel; +} + +UnifiedJobModelLoader.$inject = [ + 'BaseModel' +]; + +export default UnifiedJobModelLoader; diff --git a/awx/ui/client/lib/models/index.js b/awx/ui/client/lib/models/index.js index 3efc8d5299..fb902fb91c 100644 --- a/awx/ui/client/lib/models/index.js +++ b/awx/ui/client/lib/models/index.js @@ -23,6 +23,7 @@ import UnifiedJobTemplate from '~models/UnifiedJobTemplate'; import WorkflowJob from '~models/WorkflowJob'; import WorkflowJobTemplate from '~models/WorkflowJobTemplate'; import WorkflowJobTemplateNode from '~models/WorkflowJobTemplateNode'; +import UnifiedJob from '~models/UnifiedJob'; const MODULE_NAME = 'at.lib.models'; @@ -49,6 +50,7 @@ angular .service('OrganizationModel', Organization) .service('ProjectModel', Project) .service('ScheduleModel', Schedule) + .service('UnifiedJobModel', UnifiedJob) .service('UnifiedJobTemplateModel', UnifiedJobTemplate) .service('WorkflowJobModel', WorkflowJob) .service('WorkflowJobTemplateModel', WorkflowJobTemplate) diff --git a/awx/ui/client/lib/theme/_variables.less b/awx/ui/client/lib/theme/_variables.less index 2d640a0ccd..918f67342c 100644 --- a/awx/ui/client/lib/theme/_variables.less +++ b/awx/ui/client/lib/theme/_variables.less @@ -262,6 +262,9 @@ @at-margin-right-list-row-item-tag-icon: 8px; @at-margin-left-list-row-item-tag-container: -10px; @at-margin-list-row-action-mobile: 10px; +@at-margin-right-list-row-item-status: @at-space-2x; +@at-margin-right-list-row-item-inline: @at-space-4x; +@at-margin-right-list-row-item-inline-label: @at-space-2x; @at-height-divider: @at-margin-panel; @at-height-input: 30px; 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 index 492c256e1d..bdabf14436 100644 --- 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 @@ -86,4 +86,4 @@ InstanceJobsController.$inject = [ 'InstanceModel' ]; -export default InstanceJobsController; \ No newline at end of file +export default InstanceJobsController; diff --git a/awx/ui/client/src/jobs/jobs.route.js b/awx/ui/client/src/jobs/jobs.route.js deleted file mode 100644 index 27d6631153..0000000000 --- a/awx/ui/client/src/jobs/jobs.route.js +++ /dev/null @@ -1,59 +0,0 @@ -/************************************************* - * Copyright (c) 2016 Ansible, Inc. - * - * All Rights Reserved - *************************************************/ - - import { N_ } from '../i18n'; - import {templateUrl} from '../shared/template-url/template-url.factory'; - -export default { - searchPrefix: 'job', - name: 'jobs', - url: '/jobs', - ncyBreadcrumb: { - label: N_("JOBS") - }, - params: { - job_search: { - value: { - not__launch_type: 'sync', - order_by: '-finished' - }, - dynamic: true, - squash: false - } - }, - data: { - socket: { - "groups": { - "jobs": ["status_changed"], - "schedules": ["changed"] - } - } - }, - resolve: { - Dataset: ['AllJobsList', 'QuerySet', '$stateParams', 'GetBasePath', (list, qs, $stateParams, GetBasePath) => { - let path = GetBasePath(list.basePath) || GetBasePath(list.name); - return qs.search(path, $stateParams[`${list.iterator}_search`]); - }], - ListDefinition: ['AllJobsList', (list) => { - return list; - }] - }, - views: { - '@': { - templateUrl: templateUrl('jobs/jobs') - }, - 'list@jobs': { - templateProvider: function(AllJobsList, generateList) { - let html = generateList.build({ - list: AllJobsList, - mode: 'edit' - }); - return html; - }, - controller: 'JobsList' - } - } -}; diff --git a/awx/ui/client/src/jobs/main.js b/awx/ui/client/src/jobs/main.js index 7aaf97035c..2bb8f0a7a5 100644 --- a/awx/ui/client/src/jobs/main.js +++ b/awx/ui/client/src/jobs/main.js @@ -5,15 +5,11 @@ *************************************************/ import jobsList from './jobs-list.controller'; -import jobsRoute from './jobs.route'; import DeleteJob from './factories/delete-job.factory'; import AllJobsList from './all-jobs.list'; export default angular.module('JobsModule', []) - .run(['$stateExtender', function($stateExtender) { - $stateExtender.addState(jobsRoute); - }]) .controller('JobsList', jobsList) .factory('DeleteJob', DeleteJob) .factory('AllJobsList', AllJobsList); diff --git a/awx/ui/client/src/scheduler/main.js b/awx/ui/client/src/scheduler/main.js index 7671614054..93357de409 100644 --- a/awx/ui/client/src/scheduler/main.js +++ b/awx/ui/client/src/scheduler/main.js @@ -349,7 +349,7 @@ export default }] }, views: { - 'list@jobs': { + 'schedulesList@jobs': { templateProvider: function(ScheduleList, generateList){ let html = generateList.build({ list: ScheduleList, diff --git a/awx/ui/client/src/templates/labels/labelsList.directive.js b/awx/ui/client/src/templates/labels/labelsList.directive.js index 208c111b80..8402a14dd2 100644 --- a/awx/ui/client/src/templates/labels/labelsList.directive.js +++ b/awx/ui/client/src/templates/labels/labelsList.directive.js @@ -95,6 +95,11 @@ export default if (scope.$parent.$parent.template) { scope.labels = scope.$parent.$parent.template.summary_fields.labels.results.slice(0, 5); scope.count = scope.$parent.$parent.template.summary_fields.labels.count; + } else if (scope.$parent.$parent.job) { + if (_.has(scope, '$parent.$parent.job.summary_fields.labels.results')) { + scope.labels = scope.$parent.$parent.job.summary_fields.labels.results.slice(0, 5); + scope.count = scope.$parent.$parent.job.summary_fields.labels.count; + } } else { scope.$watchCollection(scope.$parent.list.iterator, function() { // To keep the array of labels fresh, we need to set up a watcher - otherwise, the From babad0b86818944224f8d9f61b4bec26380a2562 Mon Sep 17 00:00:00 2001 From: John Mitchell Date: Fri, 23 Mar 2018 14:53:20 -0400 Subject: [PATCH 2/4] move all jobs views to using new view --- awx/ui/client/features/jobs/index.js | 2 +- .../client/features/jobs/jobsList.view.html | 2 +- .../jobs/routes/instanceGroupJobs.route.js | 64 ++++++++ .../jobs/routes/instanceJobs.route.js | 64 ++++++++ .../routes/inventoryCompletedJobs.route.js | 63 ++++++++ .../features/jobs/{ => routes}/jobs.route.js | 4 +- .../jobs/routes/portalModeAllJobs.route.js | 50 ++++++ .../jobs/routes/portalModeMyJobs.route.js | 53 +++++++ .../routes/templateCompletedJobs.route.js | 60 ++++++++ awx/ui/client/src/app.js | 2 - .../instance-groups.partial.html | 2 +- .../instance-jobs/instance-jobs.controller.js | 89 ----------- .../jobs/jobs-list.partial.html | 86 ----------- .../instance-groups/jobs/jobs.controller.js | 100 ------------ .../src/instance-groups/jobs/jobs.list.js | 76 --------- .../src/instance-groups/jobs/jobs.strings.js | 30 ---- .../jobs/jobsListContainer.controller.js | 36 +++++ .../jobs/jobsListContainer.partial.html | 11 ++ awx/ui/client/src/instance-groups/main.js | 80 +--------- .../src/inventories-hosts/inventories/main.js | 4 +- .../completed-jobs/completed-jobs.list.js | 86 ----------- .../completed-jobs/completed-jobs.route.js | 60 -------- .../related/completed-jobs/main.js | 11 -- .../smart-inventory/smart-inventory.form.js | 26 +--- .../standard-inventory/inventory.form.js | 26 +--- awx/ui/client/src/jobs/all-jobs.list.js | 115 -------------- .../src/jobs/factories/delete-job.factory.js | 145 ------------------ .../client/src/jobs/jobs-list.controller.js | 143 ----------------- awx/ui/client/src/jobs/jobs.partial.html | 23 --- awx/ui/client/src/jobs/main.js | 15 -- awx/ui/client/src/management-jobs/main.js | 2 - .../management-jobs/management-jobs.list.js | 43 ------ .../jobs/portal-mode-all-jobs.route.js | 49 ------ .../jobs/portal-mode-my-jobs.route.js | 51 ------ awx/ui/client/src/portal-mode/main.js | 12 +- .../src/portal-mode/portal-jobs.list.js | 50 ------ .../portal-mode-jobs.controller.js | 105 ------------- .../portal-mode/portal-mode-jobs.partial.html | 26 ---- .../src/templates/completed-jobs.list.js | 87 ----------- .../job_templates/job-template.form.js | 13 +- awx/ui/client/src/templates/main.js | 9 +- 41 files changed, 437 insertions(+), 1538 deletions(-) create mode 100644 awx/ui/client/features/jobs/routes/instanceGroupJobs.route.js create mode 100644 awx/ui/client/features/jobs/routes/instanceJobs.route.js create mode 100644 awx/ui/client/features/jobs/routes/inventoryCompletedJobs.route.js rename awx/ui/client/features/jobs/{ => routes}/jobs.route.js (94%) create mode 100644 awx/ui/client/features/jobs/routes/portalModeAllJobs.route.js create mode 100644 awx/ui/client/features/jobs/routes/portalModeMyJobs.route.js create mode 100644 awx/ui/client/features/jobs/routes/templateCompletedJobs.route.js delete mode 100644 awx/ui/client/src/instance-groups/instances/instance-jobs/instance-jobs.controller.js delete mode 100644 awx/ui/client/src/instance-groups/jobs/jobs-list.partial.html delete mode 100644 awx/ui/client/src/instance-groups/jobs/jobs.controller.js delete mode 100644 awx/ui/client/src/instance-groups/jobs/jobs.list.js delete mode 100644 awx/ui/client/src/instance-groups/jobs/jobs.strings.js create mode 100644 awx/ui/client/src/instance-groups/jobs/jobsListContainer.controller.js create mode 100644 awx/ui/client/src/instance-groups/jobs/jobsListContainer.partial.html delete mode 100644 awx/ui/client/src/inventories-hosts/inventories/related/completed-jobs/completed-jobs.list.js delete mode 100644 awx/ui/client/src/inventories-hosts/inventories/related/completed-jobs/completed-jobs.route.js delete mode 100644 awx/ui/client/src/inventories-hosts/inventories/related/completed-jobs/main.js delete mode 100644 awx/ui/client/src/jobs/all-jobs.list.js delete mode 100644 awx/ui/client/src/jobs/factories/delete-job.factory.js delete mode 100644 awx/ui/client/src/jobs/jobs-list.controller.js delete mode 100644 awx/ui/client/src/jobs/jobs.partial.html delete mode 100644 awx/ui/client/src/jobs/main.js delete mode 100644 awx/ui/client/src/management-jobs/management-jobs.list.js delete mode 100644 awx/ui/client/src/portal-mode/jobs/portal-mode-all-jobs.route.js delete mode 100644 awx/ui/client/src/portal-mode/jobs/portal-mode-my-jobs.route.js delete mode 100644 awx/ui/client/src/portal-mode/portal-jobs.list.js delete mode 100644 awx/ui/client/src/portal-mode/portal-mode-jobs.controller.js delete mode 100644 awx/ui/client/src/portal-mode/portal-mode-jobs.partial.html delete mode 100644 awx/ui/client/src/templates/completed-jobs.list.js 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) ]) }; From f3329c8cce3c2dab611845a5e5f15762140b7adc Mon Sep 17 00:00:00 2001 From: John Mitchell Date: Fri, 23 Mar 2018 17:00:41 -0400 Subject: [PATCH 3/4] fix instance groups sub jobs lists --- .../jobs/routes/instanceGroupJobs.route.js | 8 ++++---- .../jobs/routes/instanceJobs.route.js | 10 +++++----- awx/ui/client/lib/components/tabs/_index.less | 6 +++++- .../instance-groups.partial.html | 4 +++- ...anceGroupsJobsListContainer.controller.js} | 6 ++++-- ...tanceGroupsJobsListContainer.partial.html} | 2 +- .../instanceJobsListContainer.controller.js | 20 +++++++++++++++++++ .../instanceJobsListContainer.partial.html | 6 ++++++ 8 files changed, 48 insertions(+), 14 deletions(-) rename awx/ui/client/src/instance-groups/jobs/{jobsListContainer.controller.js => instanceGroupsJobsListContainer.controller.js} (78%) rename awx/ui/client/src/instance-groups/jobs/{jobsListContainer.partial.html => instanceGroupsJobsListContainer.partial.html} (89%) create mode 100644 awx/ui/client/src/instance-groups/jobs/instanceJobsListContainer.controller.js create mode 100644 awx/ui/client/src/instance-groups/jobs/instanceJobsListContainer.partial.html diff --git a/awx/ui/client/features/jobs/routes/instanceGroupJobs.route.js b/awx/ui/client/features/jobs/routes/instanceGroupJobs.route.js index c6a6f08d92..fe86b78774 100644 --- a/awx/ui/client/features/jobs/routes/instanceGroupJobs.route.js +++ b/awx/ui/client/features/jobs/routes/instanceGroupJobs.route.js @@ -1,9 +1,9 @@ -import listContainerController from '~src/instance-groups/jobs/jobsListContainer.controller'; +import listContainerController from '~src/instance-groups/jobs/instanceGroupsJobsListContainer.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'); +const listContainerTemplate = require('~src/instance-groups/jobs/instanceGroupsJobsListContainer.partial.html'); export default { name: 'instanceGroups.jobs', @@ -22,12 +22,12 @@ export default { } }, views: { - 'jobsContainer@instanceGroups': { + 'instanceGroupsJobsContainer@instanceGroups': { templateUrl: listContainerTemplate, controller: listContainerController, controllerAs: 'vm' }, - 'jobsList@instanceGroups': { + 'jobsList@instanceGroups.jobs': { templateUrl: jobsListTemplate, controller: jobsListController, controllerAs: 'vm' diff --git a/awx/ui/client/features/jobs/routes/instanceJobs.route.js b/awx/ui/client/features/jobs/routes/instanceJobs.route.js index 76fed1f1b0..06019bcf22 100644 --- a/awx/ui/client/features/jobs/routes/instanceJobs.route.js +++ b/awx/ui/client/features/jobs/routes/instanceJobs.route.js @@ -1,24 +1,24 @@ -import listContainerController from '~src/instance-groups/jobs/jobsListContainer.controller'; +import listContainerController from '~src/instance-groups/jobs/instanceJobsListContainer.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'); +const listContainerTemplate = require('~src/instance-groups/jobs/instanceJobsListContainer.partial.html'); export default { name: 'instanceGroups.instanceJobs', url: '/:instance_group_id/instances/:instance_id/jobs', ncyBreadcrumb: { - parent: 'instanceGroups.instances', + parent: 'instanceGroups.edit', label: N_('JOBS') }, views: { - 'jobsContainer@instances': { + 'instanceJobsContainer@instanceGroups': { templateUrl: listContainerTemplate, controller: listContainerController, controllerAs: 'vm' }, - 'jobsList@instances': { + 'jobsList@instanceGroups.instanceJobs': { templateUrl: jobsListTemplate, controller: jobsListController, controllerAs: 'vm' diff --git a/awx/ui/client/lib/components/tabs/_index.less b/awx/ui/client/lib/components/tabs/_index.less index 84b33c2134..e999a75613 100644 --- a/awx/ui/client/lib/components/tabs/_index.less +++ b/awx/ui/client/lib/components/tabs/_index.less @@ -29,4 +29,8 @@ .at-TabGroup + .at-Panel-body { margin-top: 20px; -} \ No newline at end of file +} + +.at-TabGroup--padBelow { + margin-bottom: 20px; +} 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 680f8b1ded..bdc05274b6 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,9 @@
-
+
+ +
diff --git a/awx/ui/client/src/instance-groups/jobs/jobsListContainer.controller.js b/awx/ui/client/src/instance-groups/jobs/instanceGroupsJobsListContainer.controller.js similarity index 78% rename from awx/ui/client/src/instance-groups/jobs/jobsListContainer.controller.js rename to awx/ui/client/src/instance-groups/jobs/instanceGroupsJobsListContainer.controller.js index 6ccb6775ff..118fc9284b 100644 --- a/awx/ui/client/src/instance-groups/jobs/jobsListContainer.controller.js +++ b/awx/ui/client/src/instance-groups/jobs/instanceGroupsJobsListContainer.controller.js @@ -7,20 +7,22 @@ function InstanceGroupJobsContainerController (strings, $state) { const instanceGroupId = $state.params.instance_group_id; vm.panelTitle = 'Jobs' + vm.strings = strings; vm.tab = { details: { _go: 'instanceGroups.edit', - _params: { instanceGroupId }, + _params: { instance_group_id: instanceGroupId }, _label: strings.get('tab.DETAILS') }, instances: { _go: 'instanceGroups.instances', - _params: { instanceGroupId }, + _params: { instance_group_id: instanceGroupId }, _label: strings.get('tab.INSTANCES') }, jobs: { _active: true, + _params: { instance_group_id: instanceGroupId }, _label: strings.get('tab.JOBS') } }; diff --git a/awx/ui/client/src/instance-groups/jobs/jobsListContainer.partial.html b/awx/ui/client/src/instance-groups/jobs/instanceGroupsJobsListContainer.partial.html similarity index 89% rename from awx/ui/client/src/instance-groups/jobs/jobsListContainer.partial.html rename to awx/ui/client/src/instance-groups/jobs/instanceGroupsJobsListContainer.partial.html index 9eab62c32f..8b3f6e5bfd 100644 --- a/awx/ui/client/src/instance-groups/jobs/jobsListContainer.partial.html +++ b/awx/ui/client/src/instance-groups/jobs/instanceGroupsJobsListContainer.partial.html @@ -2,7 +2,7 @@ {{ 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/instanceJobsListContainer.controller.js b/awx/ui/client/src/instance-groups/jobs/instanceJobsListContainer.controller.js new file mode 100644 index 0000000000..650b8e28cf --- /dev/null +++ b/awx/ui/client/src/instance-groups/jobs/instanceJobsListContainer.controller.js @@ -0,0 +1,20 @@ + +function InstanceGroupJobsContainerController (strings, $state) { + const vm = this || {}; + + init(); + function init() { + const instanceGroupId = $state.params.instance_group_id; + + vm.panelTitle = 'Jobs' + vm.strings = strings; + } + +} + +InstanceGroupJobsContainerController.$inject = [ + 'InstanceGroupsStrings', + '$state' +]; + +export default InstanceGroupJobsContainerController; diff --git a/awx/ui/client/src/instance-groups/jobs/instanceJobsListContainer.partial.html b/awx/ui/client/src/instance-groups/jobs/instanceJobsListContainer.partial.html new file mode 100644 index 0000000000..1104ee9548 --- /dev/null +++ b/awx/ui/client/src/instance-groups/jobs/instanceJobsListContainer.partial.html @@ -0,0 +1,6 @@ + + + {{ vm.panelTitle }} + +
+
From 01982e7eabffb4c5707dd63a8e3359edbb552184 Mon Sep 17 00:00:00 2001 From: John Mitchell Date: Mon, 26 Mar 2018 10:07:47 -0400 Subject: [PATCH 4/4] utilize transation for instance groups jobs sub panels titles and fix a few linting errors --- .../src/instance-groups/instance-groups.strings.js | 6 +++++- .../jobs/instanceGroupsJobsListContainer.controller.js | 2 +- .../jobs/instanceJobsListContainer.controller.js | 9 +++------ awx/ui/client/src/management-jobs/main.js | 2 +- tower-license | 1 + 5 files changed, 11 insertions(+), 9 deletions(-) create mode 160000 tower-license diff --git a/awx/ui/client/src/instance-groups/instance-groups.strings.js b/awx/ui/client/src/instance-groups/instance-groups.strings.js index 79a21e075e..5ec8f411e6 100644 --- a/awx/ui/client/src/instance-groups/instance-groups.strings.js +++ b/awx/ui/client/src/instance-groups/instance-groups.strings.js @@ -23,8 +23,12 @@ function InstanceGroupsStrings (BaseString) { IS_OFFLINE: t.s('Unavailable to run jobs.'), IS_OFFLINE_LABEL: t.s('Unavailable') }; + + ns.jobs = { + PANEL_TITLE: t.s('Jobs') + }; } InstanceGroupsStrings.$inject = ['BaseStringService']; -export default InstanceGroupsStrings; \ No newline at end of file +export default InstanceGroupsStrings; diff --git a/awx/ui/client/src/instance-groups/jobs/instanceGroupsJobsListContainer.controller.js b/awx/ui/client/src/instance-groups/jobs/instanceGroupsJobsListContainer.controller.js index 118fc9284b..62fb924efe 100644 --- a/awx/ui/client/src/instance-groups/jobs/instanceGroupsJobsListContainer.controller.js +++ b/awx/ui/client/src/instance-groups/jobs/instanceGroupsJobsListContainer.controller.js @@ -6,7 +6,7 @@ function InstanceGroupJobsContainerController (strings, $state) { function init() { const instanceGroupId = $state.params.instance_group_id; - vm.panelTitle = 'Jobs' + vm.panelTitle = strings.get('jobs.PANEL_TITLE'); vm.strings = strings; vm.tab = { diff --git a/awx/ui/client/src/instance-groups/jobs/instanceJobsListContainer.controller.js b/awx/ui/client/src/instance-groups/jobs/instanceJobsListContainer.controller.js index 650b8e28cf..306249f842 100644 --- a/awx/ui/client/src/instance-groups/jobs/instanceJobsListContainer.controller.js +++ b/awx/ui/client/src/instance-groups/jobs/instanceJobsListContainer.controller.js @@ -1,20 +1,17 @@ -function InstanceGroupJobsContainerController (strings, $state) { +function InstanceGroupJobsContainerController (strings) { const vm = this || {}; init(); function init() { - const instanceGroupId = $state.params.instance_group_id; - - vm.panelTitle = 'Jobs' + vm.panelTitle = strings.get('jobs.PANEL_TITLE'); vm.strings = strings; } } InstanceGroupJobsContainerController.$inject = [ - 'InstanceGroupsStrings', - '$state' + 'InstanceGroupsStrings' ]; export default InstanceGroupJobsContainerController; diff --git a/awx/ui/client/src/management-jobs/main.js b/awx/ui/client/src/management-jobs/main.js index 7b850261b9..ef291e1ee5 100644 --- a/awx/ui/client/src/management-jobs/main.js +++ b/awx/ui/client/src/management-jobs/main.js @@ -13,4 +13,4 @@ export default managementJobsCard.name, managementJobsScheduler.name, managementJobsNotifications.name - ]) + ]); diff --git a/tower-license b/tower-license new file mode 160000 index 0000000000..009cc73a80 --- /dev/null +++ b/tower-license @@ -0,0 +1 @@ +Subproject commit 009cc73a80e5123143e9c780c7011903d4c2a331