mirror of
https://github.com/ZwareBear/awx.git
synced 2026-04-12 19:11:49 -05:00
implement new style jobs list in ui
This commit is contained in:
@@ -6,6 +6,7 @@ import atFeaturesApplications from '~features/applications';
|
|||||||
import atFeaturesCredentials from '~features/credentials';
|
import atFeaturesCredentials from '~features/credentials';
|
||||||
import atFeaturesTemplates from '~features/templates';
|
import atFeaturesTemplates from '~features/templates';
|
||||||
import atFeaturesUsers from '~features/users';
|
import atFeaturesUsers from '~features/users';
|
||||||
|
import atFeaturesJobs from '~features/jobs';
|
||||||
|
|
||||||
const MODULE_NAME = 'at.features';
|
const MODULE_NAME = 'at.features';
|
||||||
|
|
||||||
@@ -16,7 +17,8 @@ angular.module(MODULE_NAME, [
|
|||||||
atFeaturesApplications,
|
atFeaturesApplications,
|
||||||
atFeaturesCredentials,
|
atFeaturesCredentials,
|
||||||
atFeaturesTemplates,
|
atFeaturesTemplates,
|
||||||
atFeaturesUsers
|
atFeaturesUsers,
|
||||||
|
atFeaturesJobs
|
||||||
]);
|
]);
|
||||||
|
|
||||||
export default MODULE_NAME;
|
export default MODULE_NAME;
|
||||||
|
|||||||
13
awx/ui/client/features/jobs/index.js
Normal file
13
awx/ui/client/features/jobs/index.js
Normal file
@@ -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;
|
||||||
19
awx/ui/client/features/jobs/index.view.html
Normal file
19
awx/ui/client/features/jobs/index.view.html
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<div class="tab-pane" id="jobs-page">
|
||||||
|
<at-panel ng-cloak id="htmlTemplate">
|
||||||
|
<div>
|
||||||
|
<div ng-hide="$state.is('jobs.schedules')">
|
||||||
|
<at-panel-heading hide-dismiss="true">
|
||||||
|
<translate>JOBS</translate>
|
||||||
|
</at-panel-heading>
|
||||||
|
<div ui-view="jobsList"></div>
|
||||||
|
</div>
|
||||||
|
<div ng-hide="!$state.is('jobs.schedules')">
|
||||||
|
<at-panel-heading hide-dismiss="true">
|
||||||
|
<translate>SCHEDULES</translate>
|
||||||
|
</at-panel-heading>
|
||||||
|
<div ui-view="schedulesList"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</at-panel>
|
||||||
|
<div ng-include="'/static/partials/logviewer.html'"></div>
|
||||||
|
</div>
|
||||||
67
awx/ui/client/features/jobs/jobs.route.js
Normal file
67
awx/ui/client/features/jobs/jobs.route.js
Normal file
@@ -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'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
20
awx/ui/client/features/jobs/jobs.strings.js
Normal file
20
awx/ui/client/features/jobs/jobs.strings.js
Normal file
@@ -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;
|
||||||
137
awx/ui/client/features/jobs/jobsList.controller.js
Normal file
137
awx/ui/client/features/jobs/jobsList.controller.js
Normal file
@@ -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 = `<div class="Prompt-bodyQuery">${strings.get('deleteResource.CONFIRM', 'job')}</div>`;
|
||||||
|
|
||||||
|
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;
|
||||||
82
awx/ui/client/features/jobs/jobsList.view.html
Normal file
82
awx/ui/client/features/jobs/jobsList.view.html
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
<at-panel-body>
|
||||||
|
<div class="at-List-toolbar">
|
||||||
|
<smart-search
|
||||||
|
class="at-List-search"
|
||||||
|
django-model="jobs"
|
||||||
|
base-path="unified_jobs"
|
||||||
|
iterator="job"
|
||||||
|
list="list"
|
||||||
|
dataset="job_dataset"
|
||||||
|
collection="collection"
|
||||||
|
search-tags="searchTags"
|
||||||
|
query-set="querySet">
|
||||||
|
</smart-search>
|
||||||
|
</div>
|
||||||
|
<at-list results="jobs">
|
||||||
|
<!-- TODO: implement resources are missing red indicator as present in mockup -->
|
||||||
|
<at-row ng-repeat="job in jobs" job-id="{{ job.id }}">
|
||||||
|
<div class="at-Row-items">
|
||||||
|
<!-- TODO: include workflow tab as well -->
|
||||||
|
<at-row-item
|
||||||
|
status="{{ job.status }}"
|
||||||
|
status-tip="Job {{job.status}}. Click for details."
|
||||||
|
header-value="{{ job.name }}"
|
||||||
|
header-link="{{ vm.getLink(job) }}"
|
||||||
|
header-tag="{{ vm.jobTypes[job.type] }}">
|
||||||
|
</at-row-item>
|
||||||
|
<at-row-item
|
||||||
|
label-value="{{:: vm.strings.get('list.ROW_ITEM_LABEL_STARTED') }}"
|
||||||
|
value="{{ job.started | longDate }}"
|
||||||
|
inline="true">
|
||||||
|
</at-row-item>
|
||||||
|
<at-row-item
|
||||||
|
label-value="{{:: vm.strings.get('list.ROW_ITEM_LABEL_FINISHED') }}"
|
||||||
|
value="{{ job.finished | longDate }}"
|
||||||
|
inline="true">
|
||||||
|
</at-row-item>
|
||||||
|
<at-row-item
|
||||||
|
label-value="{{:: vm.strings.get('list.ROW_ITEM_LABEL_LAUNCHED_BY') }}"
|
||||||
|
value="{{ job.summary_fields.created_by.username }}"
|
||||||
|
value-link="/#/users/{{ job.summary_fields.created_by.id }}">
|
||||||
|
</at-row-item>
|
||||||
|
<at-row-item
|
||||||
|
label-value="{{:: vm.strings.get('list.ROW_ITEM_LABEL_JOB_TEMPLATE') }}"
|
||||||
|
value="{{ job.summary_fields.job_template.name }}"
|
||||||
|
value-link="/#/templates/job_template/{{ job.summary_fields.job_template.id }}">
|
||||||
|
</at-row-item>
|
||||||
|
<at-row-item
|
||||||
|
label-value="{{:: vm.strings.get('list.ROW_ITEM_LABEL_INVENTORY') }}"
|
||||||
|
value="{{ job.summary_fields.inventory.name }}"
|
||||||
|
value-link="/#/inventories/{{ job.summary_fields.inventory.id }}">
|
||||||
|
</at-row-item>
|
||||||
|
<at-row-item
|
||||||
|
label-value="{{:: vm.strings.get('list.ROW_ITEM_LABEL_PROJECT') }}"
|
||||||
|
value="{{ job.summary_fields.project.name }}"
|
||||||
|
value-link="/#/projects/{{ job.summary_fields.project.id }}">
|
||||||
|
</at-row-item>
|
||||||
|
<at-row-item
|
||||||
|
label-value="{{:: vm.strings.get('list.ROW_ITEM_LABEL_CREDENTIALS') }}"
|
||||||
|
tag-values="job.summary_fields.credentials"
|
||||||
|
tags-are-creds="true">
|
||||||
|
</at-row-item>
|
||||||
|
<labels-list class="LabelList" show-delete="false" is-row-item="true">
|
||||||
|
</labels-list>
|
||||||
|
</div>
|
||||||
|
<div class="at-Row-actions">
|
||||||
|
<at-relaunch
|
||||||
|
ng-show="job.summary_fields.user_capabilities.start">
|
||||||
|
</at-relaunch>
|
||||||
|
<at-row-action icon="fa-trash" ng-click="vm.deleteJob(job)"
|
||||||
|
ng-show="job.summary_fields.user_capabilities.delete">
|
||||||
|
</at-row-action>
|
||||||
|
</div>
|
||||||
|
</at-row>
|
||||||
|
</at-list>
|
||||||
|
<paginate
|
||||||
|
collection="collection"
|
||||||
|
dataset="job_dataset"
|
||||||
|
iterator="job"
|
||||||
|
base-path="unified_jobs"
|
||||||
|
query-set="querySet">
|
||||||
|
</paginate>
|
||||||
|
</at-panel-body>
|
||||||
@@ -151,6 +151,10 @@
|
|||||||
line-height: @at-height-list-row-item;
|
line-height: @at-height-list-row-item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.at-RowItem-status {
|
||||||
|
margin-right: @at-margin-right-list-row-item-status;
|
||||||
|
}
|
||||||
|
|
||||||
.at-RowItem--isHeader {
|
.at-RowItem--isHeader {
|
||||||
color: @at-color-body-text;
|
color: @at-color-body-text;
|
||||||
margin-bottom: @at-margin-bottom-list-header;
|
margin-bottom: @at-margin-bottom-list-header;
|
||||||
@@ -263,6 +267,16 @@
|
|||||||
margin: 2px 20px 0 0;
|
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) {
|
@media screen and (max-width: @at-breakpoint-compact-list) {
|
||||||
.at-Row-actions {
|
.at-Row-actions {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@@ -271,4 +285,14 @@
|
|||||||
.at-RowAction {
|
.at-RowAction {
|
||||||
margin: @at-margin-list-row-action-mobile;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,10 +7,13 @@ function atRowItem () {
|
|||||||
transclude: true,
|
transclude: true,
|
||||||
templateUrl,
|
templateUrl,
|
||||||
scope: {
|
scope: {
|
||||||
|
inline: '@',
|
||||||
badge: '@',
|
badge: '@',
|
||||||
headerValue: '@',
|
headerValue: '@',
|
||||||
headerLink: '@',
|
headerLink: '@',
|
||||||
headerTag: '@',
|
headerTag: '@',
|
||||||
|
status: '@',
|
||||||
|
statusTip: '@',
|
||||||
labelValue: '@',
|
labelValue: '@',
|
||||||
labelLink: '@',
|
labelLink: '@',
|
||||||
labelState: '@',
|
labelState: '@',
|
||||||
|
|||||||
@@ -1,5 +1,13 @@
|
|||||||
<div class="at-RowItem" ng-class="{'at-RowItem--isHeader': headerValue}"
|
<div class="at-RowItem" ng-class="{'at-RowItem--isHeader': headerValue, 'at-RowItem--inline': inline}"
|
||||||
ng-show="headerValue || value || (smartStatus && smartStatus.summary_fields.recent_jobs.length) || (tagValues && tagValues.length)">
|
ng-show="status || headerValue || value || (smartStatus && smartStatus.summary_fields.recent_jobs.length) || (tagValues && tagValues.length)">
|
||||||
|
<div class="at-RowItem-status" ng-if="status">
|
||||||
|
<a ng-if="headerLink" ng-href="{{ headerLink }}"
|
||||||
|
aw-tool-tip="{{ statusTip }}" aw-tip-watch="statusTip"
|
||||||
|
data-placement="top">
|
||||||
|
<i class="fa icon-job-{{ status }}"></i>
|
||||||
|
</a>
|
||||||
|
<i ng-if="!headerLink" class="fa icon-job-{{ status }}"></i>
|
||||||
|
</div>
|
||||||
<div class="at-RowItem-header" ng-if="headerValue && headerLink">
|
<div class="at-RowItem-header" ng-if="headerValue && headerLink">
|
||||||
<a ng-href="{{ headerLink }}">{{ headerValue }}</a>
|
<a ng-href="{{ headerLink }}">{{ headerValue }}</a>
|
||||||
</div>
|
</div>
|
||||||
@@ -41,4 +49,4 @@
|
|||||||
{{ tag.name }}
|
{{ tag.name }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
21
awx/ui/client/lib/models/UnifiedJob.js
Normal file
21
awx/ui/client/lib/models/UnifiedJob.js
Normal file
@@ -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;
|
||||||
@@ -23,6 +23,7 @@ import UnifiedJobTemplate from '~models/UnifiedJobTemplate';
|
|||||||
import WorkflowJob from '~models/WorkflowJob';
|
import WorkflowJob from '~models/WorkflowJob';
|
||||||
import WorkflowJobTemplate from '~models/WorkflowJobTemplate';
|
import WorkflowJobTemplate from '~models/WorkflowJobTemplate';
|
||||||
import WorkflowJobTemplateNode from '~models/WorkflowJobTemplateNode';
|
import WorkflowJobTemplateNode from '~models/WorkflowJobTemplateNode';
|
||||||
|
import UnifiedJob from '~models/UnifiedJob';
|
||||||
|
|
||||||
const MODULE_NAME = 'at.lib.models';
|
const MODULE_NAME = 'at.lib.models';
|
||||||
|
|
||||||
@@ -49,6 +50,7 @@ angular
|
|||||||
.service('OrganizationModel', Organization)
|
.service('OrganizationModel', Organization)
|
||||||
.service('ProjectModel', Project)
|
.service('ProjectModel', Project)
|
||||||
.service('ScheduleModel', Schedule)
|
.service('ScheduleModel', Schedule)
|
||||||
|
.service('UnifiedJobModel', UnifiedJob)
|
||||||
.service('UnifiedJobTemplateModel', UnifiedJobTemplate)
|
.service('UnifiedJobTemplateModel', UnifiedJobTemplate)
|
||||||
.service('WorkflowJobModel', WorkflowJob)
|
.service('WorkflowJobModel', WorkflowJob)
|
||||||
.service('WorkflowJobTemplateModel', WorkflowJobTemplate)
|
.service('WorkflowJobTemplateModel', WorkflowJobTemplate)
|
||||||
|
|||||||
@@ -262,6 +262,9 @@
|
|||||||
@at-margin-right-list-row-item-tag-icon: 8px;
|
@at-margin-right-list-row-item-tag-icon: 8px;
|
||||||
@at-margin-left-list-row-item-tag-container: -10px;
|
@at-margin-left-list-row-item-tag-container: -10px;
|
||||||
@at-margin-list-row-action-mobile: 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-divider: @at-margin-panel;
|
||||||
@at-height-input: 30px;
|
@at-height-input: 30px;
|
||||||
|
|||||||
@@ -86,4 +86,4 @@ InstanceJobsController.$inject = [
|
|||||||
'InstanceModel'
|
'InstanceModel'
|
||||||
];
|
];
|
||||||
|
|
||||||
export default InstanceJobsController;
|
export default InstanceJobsController;
|
||||||
|
|||||||
@@ -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'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -5,15 +5,11 @@
|
|||||||
*************************************************/
|
*************************************************/
|
||||||
|
|
||||||
import jobsList from './jobs-list.controller';
|
import jobsList from './jobs-list.controller';
|
||||||
import jobsRoute from './jobs.route';
|
|
||||||
import DeleteJob from './factories/delete-job.factory';
|
import DeleteJob from './factories/delete-job.factory';
|
||||||
import AllJobsList from './all-jobs.list';
|
import AllJobsList from './all-jobs.list';
|
||||||
|
|
||||||
export default
|
export default
|
||||||
angular.module('JobsModule', [])
|
angular.module('JobsModule', [])
|
||||||
.run(['$stateExtender', function($stateExtender) {
|
|
||||||
$stateExtender.addState(jobsRoute);
|
|
||||||
}])
|
|
||||||
.controller('JobsList', jobsList)
|
.controller('JobsList', jobsList)
|
||||||
.factory('DeleteJob', DeleteJob)
|
.factory('DeleteJob', DeleteJob)
|
||||||
.factory('AllJobsList', AllJobsList);
|
.factory('AllJobsList', AllJobsList);
|
||||||
|
|||||||
@@ -349,7 +349,7 @@ export default
|
|||||||
}]
|
}]
|
||||||
},
|
},
|
||||||
views: {
|
views: {
|
||||||
'list@jobs': {
|
'schedulesList@jobs': {
|
||||||
templateProvider: function(ScheduleList, generateList){
|
templateProvider: function(ScheduleList, generateList){
|
||||||
let html = generateList.build({
|
let html = generateList.build({
|
||||||
list: ScheduleList,
|
list: ScheduleList,
|
||||||
|
|||||||
@@ -95,6 +95,11 @@ export default
|
|||||||
if (scope.$parent.$parent.template) {
|
if (scope.$parent.$parent.template) {
|
||||||
scope.labels = scope.$parent.$parent.template.summary_fields.labels.results.slice(0, 5);
|
scope.labels = scope.$parent.$parent.template.summary_fields.labels.results.slice(0, 5);
|
||||||
scope.count = scope.$parent.$parent.template.summary_fields.labels.count;
|
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 {
|
} else {
|
||||||
scope.$watchCollection(scope.$parent.list.iterator, function() {
|
scope.$watchCollection(scope.$parent.list.iterator, function() {
|
||||||
// To keep the array of labels fresh, we need to set up a watcher - otherwise, the
|
// To keep the array of labels fresh, we need to set up a watcher - otherwise, the
|
||||||
|
|||||||
Reference in New Issue
Block a user