1
0
mirror of https://github.com/ansible/awx.git synced 2024-11-01 08:21:15 +03:00

Add Instance enable/disable toggle to list

This commit is contained in:
Marliana Lara 2018-01-30 15:25:36 -05:00 committed by Matthew Jones
parent 70786c53a7
commit e07f441e32
No known key found for this signature in database
GPG Key ID: 76A4C17A97590C1C
34 changed files with 328 additions and 342 deletions

View File

@ -78,11 +78,6 @@ function ComponentsStrings (BaseString) {
FOOTER_COPYRIGHT: t.s('Copyright © 2017 Red Hat, Inc.')
};
ns.capacityBar = {
IS_OFFLINE: t.s('Unavailable to run jobs.'),
IS_OFFLINE_LABEL: t.s('Unavailable')
};
ns.relaunch = {
DEFAULT: t.s('Relaunch using the same parameters'),
HOSTS: t.s('Relaunch using host parameters'),

View File

@ -119,14 +119,8 @@ function AtInputLookupController (baseInputController, $q, $state) {
vm.searchAfterDebounce();
};
vm.removeTag = (i) => {
let list;
if (!i.id) {
list = _.remove(scope.state._value, i);
} else {
list = _.remove(scope.state._value, i.id);
}
scope.state._value = list;
vm.removeTag = (tagToRemove) => {
_.remove(scope.state._value, (tag) => tag === tagToRemove);
};
}

View File

@ -1,45 +1,40 @@
<div class="col-sm-{{::col}} at-InputContainer">
<div class="form-group at-u-flat">
<at-input-label></at-input-label>
<div class="form-group at-u-flat">
<at-input-label></at-input-label>
<div class="input-group">
<span class="input-group-btn">
<button class="btn at-ButtonHollow--default at-Input-button"
ng-disabled="state._disabled || form.disabled"
ng-click="vm.lookup()">
<i class="fa fa-search"></i>
</button>
</span>
<div class="input-group">
<span class="input-group-btn">
<button class="btn at-ButtonHollow--default at-Input-button"
ng-disabled="state._disabled || form.disabled"
ng-click="vm.lookup()">
<i class="fa fa-search"></i>
</button>
</span>
<input type="text"
class="form-control at-Input"
ng-class="{ 'at-Input--rejected': state._rejected }"
ng-model="state._displayValue"
ng-attr-tabindex="{{ tab || undefined }}"
ng-attr-placeholder="{{::state._placeholder || undefined }}"
ng-change="vm.searchOnInput()"
ng-hide="state._lookupTags"
ng-disabled="state._disabled || form.disabled">
<!-- Refactor / Add conditional -->
<input type="text"
class="form-control at-Input"
ng-class="{ 'at-Input--rejected': state._rejected }"
ng-model="state._displayValue"
ng-attr-tabindex="{{ tab || undefined }}"
ng-attr-placeholder="{{::state._placeholder || undefined }}"
ng-change="vm.searchOnInput()"
ng-hide="state._lookupTags"
ng-disabled="state._disabled || form.disabled">
</input>
<span class="form-control Form-textInput Form-textInput--variableHeight input-medium lookup LabelList-lookupTags"
ng-if="state._lookupTags">
<div class="LabelList-tagContainer" ng-repeat="tag in state._value">
<div class="LabelList-deleteContainer" ng-click="vm.removeTag(tag)">
<i class="fa fa-times LabelList-tagDelete"></i>
</div>
<div class="LabelList-tag LabelList-tag--deletable">
<span ng-if="tag.hostname" class="LabelList-name">{{ tag.hostname }}</span>
<span ng-if="!tag.hostname" class="LabelList-name">{{ tag }}</span>
</div>
</div>
</span>
</div>
<at-input-message></at-input-message>
<span class="form-control Form-textInput Form-textInput--variableHeight LabelList-lookupTags"
ng-if="state._lookupTags">
<div class="LabelList-tagContainer" ng-repeat="tag in state._value track by $index">
<div class="LabelList-deleteContainer" ng-click="vm.removeTag(tag)">
<i class="fa fa-times LabelList-tagDelete"></i>
</div>
<div class="LabelList-tag LabelList-tag--deletable">
<span ng-if="tag.hostname" class="LabelList-name">{{ tag.hostname }}</span>
<span ng-if="!tag.hostname" class="LabelList-name">{{ tag }}</span>
</div>
</span>
</div>
<div ui-view="{{ state._resource }}"></div>
<at-input-message></at-input-message>
</div>
<div ui-view="{{ state._resource }}"></div>
</div>

View File

@ -99,6 +99,15 @@
}
}
.at-RowStatus {
align-self: flex-start;
margin: 0 10px 0 0;
}
.at-Row-firstColumn {
margin-right: @at-space-4x;
}
.at-Row-actions {
display: flex;
}
@ -120,6 +129,14 @@
line-height: @at-line-height-list-row-item-header;
}
.at-RowItem--isHeaderLink {
color: @at-blue;
cursor: pointer;
}
.at-RowItem--isHeaderLink:hover {
color: @at-blue-hover;
}
.at-RowItem--labels {
line-height: @at-line-height-list-row-item-labels;
}

View File

@ -26,3 +26,7 @@
cursor: not-allowed;
}
}
.at-TabGroup + .at-Panel-body {
margin-top: 20px;
}

View File

@ -1,21 +0,0 @@
let Base;
function JobModel (method, resource, config) {
Base.call(this, 'jobs');
this.Constructor = JobModel;
return this.create(method, resource, config);
}
function JobModelLoader (BaseModel) {
Base = BaseModel;
return JobModel;
}
JobModelLoader.$inject = [
'BaseModel'
];
export default JobModelLoader;

View File

@ -60,6 +60,8 @@ function BaseStringService (namespace) {
this.CANCEL = t.s('CANCEL');
this.SAVE = t.s('SAVE');
this.OK = t.s('OK');
this.ON = t.s('ON');
this.OFF = t.s('OFF');
this.deleteResource = {
HEADER: t.s('Delete'),
USED_BY: resourceType => t.s('The {{ resourceType }} is currently being used by other resources.', { resourceType }),

View File

@ -23,6 +23,7 @@
font-size: 20px;
}
border-color: transparent;
margin-left: @at-space-2x;
}
.at-Button--info {

View File

@ -72,6 +72,7 @@
@import '../../src/home/dashboard/lists/dashboard-list.block.less';
@import '../../src/home/dashboard/dashboard.block.less';
@import '../../src/instance-groups/capacity-bar/capacity-bar.block.less';
@import '../../src/instance-groups/capacity-adjuster/capacity-adjuster.block.less';
@import '../../src/instance-groups/instance-group.block.less';
@import '../../src/instance-groups/instances/instance-modal.block.less';
@import '../../src/inventories-hosts/inventories/insights/insights.block.less';

View File

@ -316,21 +316,6 @@ angular
activateTab();
});
$transitions.onCreate({}, function(trans) {
console.log('$onCreate ' +trans.to().name);
});
$transitions.onBefore({}, function(trans) {
console.log('$onBefore ' +trans.to().name);
});
$transitions.onError({}, function(trans) {
console.log('$onError ' +trans.to().name);
});
$transitions.onExit({}, function(trans) {
console.log('$onExit ' +trans.to().name);
});
$transitions.onSuccess({}, function(trans) {
if(trans.to() === trans.from()) {

View File

@ -5,23 +5,19 @@
<at-tab-group>
<at-tab state="vm.tab.details">{{:: vm.strings.get('tab.DETAILS') }}</at-tab>
<at-tab state="vm.tab.instances" ng-hide="$state.includes('instanceGroups.add')">{{:: vm.strings.get('tab.INSTANCES') }}</at-tab>
<at-tab state="vm.tab.jobs" ng-hide="$state.includes('instanceGroups.add')">{{:: vm.strings.get('tab.JOBS') }}</at-tab>
<at-tab state="vm.tab.instances">{{:: vm.strings.get('tab.INSTANCES') }}</at-tab>
<at-tab state="vm.tab.jobs">{{:: vm.strings.get('tab.JOBS') }}</at-tab>
</at-tab-group>
<at-panel-body>
<at-form state="vm.form" autocomplete="off">
<!-- Name -->
<at-input-text col="4" tab="1" state="vm.form.name"></at-input-text>
<!-- Minimum Instances -->
<at-input-text col="4" tab="3" state="vm.form.policy_instance_minimum"></at-input-text>
<!-- Range Slider -->
<at-input-slider col="4" tab="3" state="vm.form.policy_instance_percentage"></at-input-slider>
<!-- Instances List May need to turn into lookup tags... -->
<at-input-lookup col="4" tab="4" state="vm.form.policy_instance_list"></at-input-lookup>
<div ui-view="modal"></div>

View File

@ -1,11 +1,10 @@
function AddController ($scope, $state, models, strings) {
const vm = this || {};
const { instanceGroup, instance } = models;
vm.mode = 'add';
vm.strings = strings;
vm.panelTitle = "New Instance Group";
vm.panelTitle = strings.get('state.ADD_BREADCRUMB_LABEL');
vm.tab = {
details: { _active: true },
@ -15,6 +14,7 @@ function AddController ($scope, $state, models, strings) {
vm.form = instanceGroup.createFormSchema('post');
// Default policy instance percentage value is 0
vm.form.policy_instance_percentage._value = 0;
vm.form.policy_instance_list._lookupTags = true;

View File

@ -1,6 +1,5 @@
function EditController ($rootScope, $state, models, strings) {
const vm = this || {};
const { instanceGroup, instance } = models;
$rootScope.breadcrumb.instance_group_name = instanceGroup.get('name');
@ -36,7 +35,7 @@ function EditController ($rootScope, $state, models, strings) {
vm.form.save = data => {
instanceGroup.unset('policy_instance_list');
data.policy_instance_list = data.policy_instance_list.map(instance => instance.hostname);
data.policy_instance_list = data.policy_instance_list.map(instance => instance.hostname || instance);
return instanceGroup.request('put', { data });
};

View File

@ -1,5 +1,5 @@
function InstanceModalController ($scope, $state, $http, $q, models, strings) {
const { instance } = models;
const { instance, instanceGroup } = models;
const vm = this || {};
vm.setInstances = () => {
@ -7,18 +7,34 @@ function InstanceModalController ($scope, $state, $http, $q, models, strings) {
instance.isSelected = false;
return instance;
});
}
};
vm.setRelatedInstances = () => {
vm.instanceGroupName = instanceGroup.get('name');
vm.relatedInstances = instanceGroup.get('policy_instance_list');
vm.instances = instance.get('results').map(instance => {
instance.isSelected = vm.relatedInstances.includes(instance.hostname);
return instance;
});
};
init();
function init() {
vm.strings = strings;
vm.panelTitle = strings.get('instance.PANEL_TITLE');
vm.setInstances();
};
vm.instanceGroupId = instanceGroup.get('id');
vm.defaultParams = { page_size: '10', order_by: 'hostname' };
if (vm.instanceGroupId === undefined) {
vm.setInstances();
} else {
vm.setRelatedInstances();
}
}
$scope.$watch('vm.instances', function() {
vm.selectedRows = _.filter(vm.instances, 'isSelected')
vm.selectedRows = _.filter(vm.instances, 'isSelected');
vm.deselectedRows = _.filter(vm.instances, 'isSelected', false);
}, true);

View File

@ -1,17 +1,17 @@
<div id="instance-modal" class="modal-dialog">
<at-panel on-dismiss="^.^">
<at-panel-heading>
{{ vm.panelTitle }} | {{ vm.instanceGroupName}}
{{:: vm.strings.get('instance.PANEL_TITLE') }}
</at-panel-heading>
<multi-select-preview selected-rows='vm.selectedRows' available-rows='vm.instances'></multi-select-preview>
<at-panel-body
style="margin: 20px 0">
<at-panel-body>
<div class="at-List-toolbar">
<smart-search
class="at-List-search"
django-model="instances"
base-path="instances"
iterator="instance"
default-params="vm.defaultParams"
list="list"
dataset="vm.instances"
collection="collection"
@ -23,8 +23,7 @@
ng-class="{'at-Row--active': (instance.id === vm.activeId)}">
<input type="checkbox"
style="margin-right: 20px"
ng-class="{ 'at-Input--rejected': state.rejected }"
class="at-Row-checkbox"
ng-model="instance.isSelected"
ng-checked="instance.isSelected"
ng-attr-tabindex="{{ tab || undefined }}"
@ -36,17 +35,18 @@
</at-row-item>
</div>
</at-row>
</at-list>
<div class="pull-right" style="margin-top:20px">
<button class="btn at-ButtonHollow--default"
ng-click="$state.go('^.^')">
{{:: vm.strings.get('CANCEL') }}
</button>
<button class="btn at-Button--success"
ng-click="vm.submit()">
{{:: vm.strings.get('SAVE') }}
</button>
<div class="at-ActionGroup">
<div class="pull-right">
<button class="btn at-ButtonHollow--default"
ng-click="$state.go('^.^')">
{{:: vm.strings.get('CANCEL') }}
</button>
<button class="btn at-Button--success"
ng-click="vm.submit()">
{{:: vm.strings.get('SAVE') }}
</button>
</div>
</div>
</at-panel-body>
</at-panel>

View File

@ -0,0 +1,11 @@
capacity-adjuster {
.at-InputSlider {
align-items: center;
margin-right: @at-space-4x;
}
.at-InputSlider p {
white-space: nowrap;
margin: 0 10px;
}
}

View File

@ -1,4 +1,4 @@
function CapacityAdjuster (templateUrl, $http) {
function CapacityAdjuster (templateUrl) {
return {
scope: {
state: '='
@ -18,7 +18,7 @@ function CapacityAdjuster (templateUrl, $http) {
scope.max_capacity = _.max(adjustment_values, 'value');
},
controller: function($http, $scope) {
controller: function($http) {
const vm = this || {};
vm.slide = (state) => {
@ -31,15 +31,14 @@ function CapacityAdjuster (templateUrl, $http) {
data
};
$http(req);
}
};
},
controllerAs: 'vm'
};
}
CapacityAdjuster.$inject = [
'templateUrl',
'$http'
'templateUrl'
];
export default CapacityAdjuster;

View File

@ -1,7 +1,5 @@
<div class="at-InputSlider"
style="align-items:center;margin-right:20px">
<p>{{min_capacity.label}}</p>
<p>{{min_capacity.value}}</p>
<div class="at-InputSlider">
<p>{{min_capacity.label}} {{min_capacity.value}}</p>
<input string-to-number
type="range"
ng-model="state.capacity_adjustment"
@ -9,6 +7,5 @@ style="align-items:center;margin-right:20px">
max="1"
step="0.1"
ng-change="vm.slide(state)"/>
<p>{{max_capacity.label}}</p>
<p>{{max_capacity.value}}</p>
<p>{{max_capacity.label}} {{max_capacity.value}}</p>
</div>

View File

@ -1,4 +1,4 @@
export default ['templateUrl', 'ComponentsStrings',
export default ['templateUrl', 'InstanceGroupsStrings',
function (templateUrl, strings) {
return {
scope: {

View File

@ -1,5 +1,5 @@
<span class="Capacity-details--label" ng-class="{'CapacityBar--offline': isOffline}">
{{labelValue}}
{{ labelValue }}
</span>
<div class="CapacityBar"

View File

@ -1,33 +0,0 @@
<div class="Panel">
<div class="row Form-tabRow">
<div class="col-xs-12">
<div class="List-header">
<div class="List-title">
<div class="List-titleText">{{ instanceGroupName }}</div>
</div>
<div class="List-details">
<div class="Capacity-details">
<p class="Capacity-details--label" translate>Used Capacity</p>
<capacity-bar capacity="instanceGroupCapacity" total-capacity="instanceGroupTotalCapacity"></capacity-bar>
</div>
<div class="RunningJobs-details">
<p class="RunningJobs-details--label" translate>Running Jobs</p>
<span class="badge List-titleBadge">
{{ instanceGroupJobsRunning }}
</span>
</div>
</div>
<div class="List-exitHolder">
<button class="List-exit" ng-click="$state.go('instanceGroups')">
<i class="fa fa-times-circle"></i>
</button>
</div>
</div>
<div class="Form-tabHolder">
<div class="Form-tab Form-tab--notitle" ng-click="$state.go('instanceGroups.instances.list', {instance_group_id: $stateParams.instance_group_id})" ng-class="{'is-selected': $state.includes('instanceGroups.instances.list')}" translate>INSTANCES</div>
<div class="Form-tab Form-tab--notitle" ng-click="$state.go('instanceGroups.instances.jobs', {instance_group_id: $stateParams.instance_group_id})" ng-class="{'is-selected': $state.includes('instanceGroups.instances.jobs')}" translate>JOBS</div>
</div>
</div>
</div>
<div ui-view="list"></div>
</div>

View File

@ -17,7 +17,12 @@ function InstanceGroupsStrings (BaseString) {
ns.instance = {
PANEL_TITLE: t.s('SELECT INSTANCE')
}
};
ns.capacityBar = {
IS_OFFLINE: t.s('Unavailable to run jobs.'),
IS_OFFLINE_LABEL: t.s('Unavailable')
};
}
InstanceGroupsStrings.$inject = ['BaseStringService'];

View File

@ -12,7 +12,7 @@ function InstanceJobsController ($scope, GetBasePath, Rest, Dataset, Find, $filt
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.panelTitle = `${jobStrings.get('list.PANEL_TITLE')} | ${instance.get('hostname')}`;
vm.tab = {
details: {_hide: true},

View File

@ -7,7 +7,7 @@ function InstanceModalController ($scope, $state, $http, $q, models, strings) {
instance.isSelected = false;
return instance;
});
}
};
vm.setRelatedInstances = () => {
vm.instanceGroupName = instanceGroup.get('name');
@ -17,7 +17,7 @@ function InstanceModalController ($scope, $state, $http, $q, models, strings) {
instance.isSelected = vm.relatedInstanceIds.includes(instance.id);
return instance;
});
}
};
init();
@ -31,10 +31,10 @@ function InstanceModalController ($scope, $state, $http, $q, models, strings) {
} else {
vm.setRelatedInstances();
}
};
}
$scope.$watch('vm.instances', function() {
vm.selectedRows = _.filter(vm.instances, 'isSelected')
vm.selectedRows = _.filter(vm.instances, 'isSelected');
vm.deselectedRows = _.filter(vm.instances, 'isSelected', false);
}, true);
@ -49,7 +49,7 @@ function InstanceModalController ($scope, $state, $http, $q, models, strings) {
let config = {
url: `${vm.instanceGroupId}/instances/`,
data: data
}
};
return instanceGroup.http.post(config);
});

View File

@ -4,8 +4,7 @@
{{ vm.panelTitle }} | {{ vm.instanceGroupName}}
</at-panel-heading>
<multi-select-preview selected-rows='vm.selectedRows' available-rows='vm.instances'></multi-select-preview>
<at-panel-body
style="margin: 20px 0">
<at-panel-body>
<div class="at-List-toolbar">
<smart-search
class="at-List-search"
@ -23,7 +22,7 @@
ng-class="{'at-Row--active': (instance.id === vm.activeId)}">
<input type="checkbox"
style="margin-right: 20px"
class="at-Row-checkbox"
ng-class="{ 'at-Input--rejected': state.rejected }"
ng-model="instance.isSelected"
ng-checked="instance.isSelected"
@ -39,16 +38,17 @@
</at-row>
</at-list>
<div class="pull-right" style="margin-top:20px">
<button class="btn at-ButtonHollow--default"
style="margin-right:10px"
ng-click="$state.go('instanceGroups.instances')">
{{:: vm.strings.get('CANCEL') }}
</button>
<button class="btn at-Button--success"
ng-click="vm.submit()">
{{:: vm.strings.get('SAVE') }}
</button>
<div class="at-ActionGroup">
<div class="pull-right">
<button class="btn at-ButtonHollow--default"
ng-click="$state.go('instanceGroups.instances')">
{{:: vm.strings.get('CANCEL') }}
</button>
<button class="btn at-Button--success"
ng-click="vm.submit()">
{{:: vm.strings.get('SAVE') }}
</button>
</div>
</div>
</at-panel-body>
</at-panel>

View File

@ -9,8 +9,7 @@
<at-tab state="vm.tab.jobs" ng-hide="$state.current.name === 'instanceGroups.add'">{{:: vm.strings.get('tab.JOBS') }}</at-tab>
</at-tab-group>
<at-panel-body
style="margin-top: 20px">
<at-panel-body>
<div class="at-List-toolbar">
<smart-search
class="at-List-search"
@ -22,13 +21,12 @@
collection="collection"
search-tags="searchTags">
</smart-search>
<!-- TODO: only show when permission -->
<div class="at-List-toolbarAction">
<button
type="button"
ng-click="$state.go('instanceGroups.instances.modal.add')"
class="at-Button--add"
aria-haspopup="true"
aria-expanded="false">
</button>
<div ui-view="modal"></div>
@ -37,12 +35,24 @@
<at-list results='vm.instances'>
<at-row ng-repeat="instance in vm.instances"
ng-class="{'at-Row--active': (instance.id === vm.activeId)}">
<div class="at-Row-firstColumn">
<div class="ScheduleToggle"
ng-class="{'is-on': instance.enabled}">
<button ng-show="instance.enabled"
class="ScheduleToggle-switch is-on ng-hide"
ng-click="vm.toggle(instance)">
{{:: vm.strings.get('ON') }}
</button>
<button ng-show="!instance.enabled"
class="ScheduleToggle-switch"
ng-click="vm.toggle(instance)">
{{:: vm.strings.get('OFF') }}
</button>
</div>
</div>
<div class="at-Row-items">
<at-row-item
header-value="{{ instance.hostname }}"
header-tag="{{ vm.instanceTypes[instance.type] }}"></at-row-item>
</at-row-item>
<at-row-item header-value="{{ instance.hostname }}"></at-row-item>
<div class="at-Row--rowLayout">
<at-row-item
label-value="Running Jobs"

View File

@ -37,6 +37,29 @@ function InstancesController ($scope, $state, $http, models, Instance, strings,
}
};
vm.toggle = (toggled) => {
let instance = _.find(vm.instances, 'id', toggled.id);
instance.enabled = !instance.enabled;
let data = {
"enabled": instance.enabled
};
let req = {
method: 'PUT',
url: instance.url,
data
};
$http(req).then(vm.onSaveSuccess);
};
vm.onSaveSuccess = () => {
$state.transitionTo($state.current, $state.params, {
reload: true, location: true, inherit: false, notify: true
});
};
$scope.isActive = function(id) {
let selected = parseInt($state.params.instance_id);
return id === selected;

View File

@ -8,7 +8,7 @@
<at-tab state="vm.tab.jobs">{{:: vm.strings.get('tab.JOBS') }}</at-tab>
</at-tab-group>
<at-panel-body style="margin-top: 20px">
<at-panel-body>
<div class="at-List-toolbar">
<smart-search
class="at-List-search"
@ -23,25 +23,23 @@
</smart-search>
</div>
<at-list results="vm.jobs">
<!-- TODO: implement resources are missing red indicator as present in mockup -->
<at-row ng-repeat="job in vm.jobs"
ng-class="{'at-Row--active': (job.id === vm.activeId)}"
job-id="{{ job.id }}">
<div style="align-self:flex-start;margin:0 10px 0 0">
<div class="at-RowStatus">
<a href="{{ job.detailsUrl }}" ng-if="isSuccessful(job.status)" aw-tool-tip="Job successful. Click for details." aw-tip-placement="right">
<i class="fa DashboardList-status DashboardList-status--success icon-job-successful"
style="margin:0"></i>
<i class="fa DashboardList-status DashboardList-status--success icon-job-successful"></i>
</a>
<a href="{{ job.detailsUrl }}" ng-if="!isSuccessful(job.status)" aw-tool-tip="Job failed. Click for details." aw-tip-placement="right">
<i class="fa DashboardList-status DashboardList-status--failed icon-job-failed"
style="margin:0"></i>
<i class="fa DashboardList-status DashboardList-status--failed icon-job-failed"></i>
</a>
</div>
<div class="at-Row-items">
<at-row-item
class="at-RowItem--isHeaderLink"
header-value="{{ job.name }}"
header-link="/#/jobs/{{ job.id }}"
header-tag="{{ vm.jobTypes[job.type] }}">
header-tag="{{ job.type }}"
ng-click="vm.viewjobResults(job)">
</at-row-item>
<at-row-item
label-value="{{:: vm.jobStrings.get('list.ROW_ITEM_LABEL_STARTED') }}"
@ -72,24 +70,12 @@
value="{{ job.summary_fields.project.name }}"
value-link="/#/projects/{{ job.summary_fields.project.id }}">
</at-row-item>
<!-- TODO: add see more for creds -->
<at-row-item
label-value="{{:: vm.jobStrings.get('list.ROW_ITEM_LABEL_CREDENTIALS') }}"
tag-values="job.summary_fields.credentials"
tags-are-creds="true">
</at-row-item>
</div>
<div class="at-Row-actions">
<at-row-action icon="icon-launch" ng-click="vm.submitJob(job)"
ng-show="job.summary_fields.user_capabilities.start">
</at-row-action>
<at-row-action icon="fa-copy" ng-click="vm.copyjob(job)"
ng-show="job.summary_fields.user_capabilities.copy">
</at-row-action>
<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

View File

@ -48,7 +48,7 @@ function InstanceGroupJobsController ($scope, GetBasePath, Rest, Dataset, Find,
return (status === "successful");
};
$scope.viewjobResults = function(job) {
vm.viewjobResults = function(job) {
var goTojobResults = function(state) {
$state.go(state, { id: job.id }, { reload: true });
};

View File

@ -1,76 +1,76 @@
// 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,
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: `<a href="{{ job.workflow_result_link }}"
// aw-tool-tip="{{'View workflow results'|translate}}"
// data-placement="top"
// data-original-title="" title="">
// <i class="WorkflowBadge"
// ng-show="job.launch_type === 'workflow' ">
// W
// </i>
// </a>`
// },
// 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'
// },
// }
// };
// }];
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: `<a href="{{ job.workflow_result_link }}"
aw-tool-tip="{{'View workflow results'|translate}}"
data-placement="top"
data-original-title="" title="">
<i class="WorkflowBadge"
ng-show="job.launch_type === 'workflow' ">
W
</i>
</a>`
},
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'
},
}
};
}];

View File

@ -6,7 +6,7 @@ function JobStrings (BaseString) {
ns.state = {
LIST_BREADCRUMB_LABEL: t.s('JOBS')
}
};
ns.list = {
PANEL_TITLE: t.s('JOBS'),
@ -22,7 +22,7 @@ function JobStrings (BaseString) {
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'];

View File

@ -4,10 +4,11 @@ export default ['$scope', 'InstanceGroupList', 'resolvedModels', 'GetBasePath',
const vm = this;
const { instanceGroup } = resolvedModels;
vm.strings = strings;
init();
function init(){
vm.panelTitle = strings.get('layout.INSTANCE_GROUPS');
$scope.list = list;
$scope[`${list.iterator}_dataset`] = Dataset.data;
$scope[list.name] = $scope[`${list.iterator}_dataset`].results;
@ -23,18 +24,18 @@ export default ['$scope', 'InstanceGroupList', 'resolvedModels', 'GetBasePath',
vm.delete = () => {
let deletables = $scope.selection;
deletables = Object.keys(deletables).filter((n) => deletables[n]);
//refactor
deletables.forEach((data) => {
let promise = instanceGroup.http.delete({resource: data})
let promise = instanceGroup.http.delete({resource: data});
Promise.resolve(promise).then(vm.onSaveSuccess);
});
}
};
vm.onSaveSuccess = () => {
$state.transitionTo($state.current, $state.params, {
reload: true, location: true, inherit: false, notify: true
});
}
};
$scope.createInstanceGroup = () => {
$state.go('instanceGroups.add');

View File

@ -1,6 +1,6 @@
<at-panel>
<at-panel-heading hide-dismiss="true">
{{ vm.panelTitle }}
{{ vm.strings.get('layout.INSTANCE_GROUPS') }}
<span class="badge List-titleBadge">
{{ instanceGroupCount }}
</span>
@ -18,11 +18,9 @@
collection="collection"
search-tags="searchTags">
</smart-search>
<!-- TODO: only show when permission -->
<div class="at-List-toolbarAction">
<div ng-click="vm.delete()"
class="at-RowAction at-RowAction--danger"
style="margin-right:10px">
class="at-RowAction at-RowAction--danger">
<i class="fa fa-trash"></i>
</div>
<button

View File

@ -1,38 +1,43 @@
import InstanceGroupsList from './list/instance-groups-list.controller';
import { templateUrl } from '../shared/template-url/template-url.factory';
import CapacityAdjuster from './capacity-adjuster/capacity-adjuster.directive';
import CapacityBar from './capacity-bar/main';
import instanceGroupsMultiselect from '../shared/instance-groups-multiselect/instance-groups.directive';
import instanceGroupsModal from '../shared/instance-groups-multiselect/instance-groups-modal/instance-groups-modal.directive';
import InstanceGroupJobsListController from './jobs/jobs.controller';
import AddEditTemplate from './add-edit/add-edit-instance-groups.view.html';
import AddInstanceGroupController from './add-edit/add-instance-group.controller';
import EditInstanceGroupController from './add-edit/edit-instance-group.controller';
import InstanceListPolicyTemplate from './add-edit/instance-list-policy.partial.html';
import InstanceListPolicyController from './add-edit/instance-list-policy.controller.js';
import InstanceGroupsTemplate from './list/instance-groups-list.partial.html';
import InstanceGroupsListController from './list/instance-groups-list.controller';
import InstancesTemplate from './instances/instances-list.partial.html';
import InstanceListController from './instances/instances.controller';
import InstanceJobsController from './instances/instance-jobs/instance-jobs.controller';
import CapacityBar from './capacity-bar/main';
import CapacityAdjuster from './capacity-adjuster/capacity-adjuster.directive';
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';
import list from './instance-groups.list';
import service from './instance-groups.service';
import { templateUrl } from '../shared/template-url/template-url.factory';
import addEditTemplate from './add-edit/add-edit-instance-groups.view.html';
import addInstanceModalTemplate from './add-edit/add-instance-list-policy.partial.html';
import addInstanceModalController from './add-edit/add-instance-list-policy.controller.js';
import instancesTemplate from './instances/instances-list.partial.html';
import instanceModalTemplate from './instances/instance-modal.partial.html';
import instanceModalController from './instances/instance-modal.controller.js';
import AddInstanceGroupController from './add-edit/add-instance-group.controller';
import EditInstanceGroupController from './add-edit/edit-instance-group.controller';
import InstanceGroupsStrings from './instance-groups.strings';
import JobStrings from './jobs/jobs.strings';
import jobsTemplate from './jobs/list.view.html';
const MODULE_NAME = 'instanceGroups';
function InstanceGroupsResolve ($q, $stateParams, InstanceGroup, Instance, Job) {
function InstanceGroupsResolve ($q, $stateParams, InstanceGroup, Instance) {
const instanceGroupId = $stateParams.instance_group_id;
const instanceId = $stateParams.instance_id;
let promises = {};
if (!instanceGroupId && !instanceId) {
promises.instanceGroup = new InstanceGroup(['get', 'options'])
promises.instanceGroup = new InstanceGroup(['get', 'options']);
promises.instance = new Instance(['get', 'options']);
return $q.all(promises);
@ -40,16 +45,17 @@ function InstanceGroupsResolve ($q, $stateParams, InstanceGroup, Instance, Job)
if (instanceGroupId && instanceId) {
promises.instance = new Instance(['get', 'options'], [instanceId, instanceId])
.then((instance) => instance.extend('get', 'jobs', {params: {page_size: "10", order_by: "-finished"}}))
.then((instance) => instance.extend('get', 'jobs', {params: {page_size: "10", order_by: "-finished"}}));
return $q.all(promises);
}
promises.instanceGroup = new InstanceGroup(['get', 'options'], [instanceGroupId, instanceGroupId])
.then((instanceGroup) => instanceGroup.extend('get', 'jobs', {params: {page_size: "10", order_by: "-finished"}}))
.then((instanceGroup) => instanceGroup.extend('get', 'instances'))
.then((instanceGroup) => instanceGroup.extend('get', 'instances'));
promises.instance = new Instance('get');
return $q.all(promises)
.then(models => models);
}
@ -58,8 +64,7 @@ InstanceGroupsResolve.$inject = [
'$q',
'$stateParams',
'InstanceGroupModel',
'InstanceModel',
'JobModel'
'InstanceModel'
];
function InstanceGroupsRun ($stateExtender, strings, ComponentsStrings) {
@ -87,8 +92,8 @@ function InstanceGroupsRun ($stateExtender, strings, ComponentsStrings) {
templateUrl: templateUrl('./instance-groups/instance-groups'),
},
'list@instanceGroups': {
templateUrl: templateUrl('./instance-groups/list/instance-groups-list'),
controller: 'InstanceGroupsList',
templateUrl: InstanceGroupsTemplate,
controller: 'InstanceGroupsListController',
controllerAs: 'vm'
}
},
@ -111,7 +116,7 @@ function InstanceGroupsRun ($stateExtender, strings, ComponentsStrings) {
},
views: {
'add@instanceGroups': {
templateUrl: addEditTemplate,
templateUrl: AddEditTemplate,
controller: AddInstanceGroupController,
controllerAs: 'vm'
}
@ -142,8 +147,8 @@ function InstanceGroupsRun ($stateExtender, strings, ComponentsStrings) {
},
views: {
"modal": {
templateUrl: addInstanceModalTemplate,
controller: addInstanceModalController,
templateUrl: InstanceListPolicyTemplate,
controller: InstanceListPolicyController,
controllerAs: 'vm'
}
},
@ -158,7 +163,7 @@ function InstanceGroupsRun ($stateExtender, strings, ComponentsStrings) {
},
views: {
'edit@instanceGroups': {
templateUrl: addEditTemplate,
templateUrl: AddEditTemplate,
controller: EditInstanceGroupController,
controllerAs: 'vm'
}
@ -190,8 +195,8 @@ function InstanceGroupsRun ($stateExtender, strings, ComponentsStrings) {
},
views: {
"modal": {
templateUrl: addInstanceModalTemplate,
controller: addInstanceModalController,
templateUrl: InstanceListPolicyTemplate,
controller: InstanceListPolicyController,
controllerAs: 'vm'
}
},
@ -216,7 +221,7 @@ function InstanceGroupsRun ($stateExtender, strings, ComponentsStrings) {
},
views: {
'instances@instanceGroups': {
templateUrl: instancesTemplate,
templateUrl: InstancesTemplate,
controller: 'InstanceListController',
controllerAs: 'vm'
}
@ -247,8 +252,8 @@ function InstanceGroupsRun ($stateExtender, strings, ComponentsStrings) {
},
views: {
"modal": {
templateUrl: instanceModalTemplate,
controller: instanceModalController,
templateUrl: InstanceModalTemplate,
controller: InstanceModalController,
controllerAs: 'vm'
}
},
@ -264,8 +269,8 @@ function InstanceGroupsRun ($stateExtender, strings, ComponentsStrings) {
},
views: {
'instanceJobs@instanceGroups': {
templateUrl: jobsTemplate,
controller: 'InstanceJobsController',
templateUrl: JobsTemplate,
controller: 'InstanceJobsListController',
controllerAs: 'vm'
},
},
@ -299,7 +304,7 @@ function InstanceGroupsRun ($stateExtender, strings, ComponentsStrings) {
},
views: {
'jobs@instanceGroups': {
templateUrl: jobsTemplate,
templateUrl: JobsTemplate,
controller: 'InstanceGroupJobsListController',
controllerAs: 'vm'
},
@ -307,7 +312,7 @@ function InstanceGroupsRun ($stateExtender, strings, ComponentsStrings) {
resolve: {
resolvedModels: InstanceGroupsResolve
}
})
});
}
InstanceGroupsRun.$inject = [
@ -319,10 +324,10 @@ InstanceGroupsRun.$inject = [
angular.module(MODULE_NAME, [CapacityBar.name])
.service('InstanceGroupsService', service)
.factory('InstanceGroupList', list)
.controller('InstanceGroupsList', InstanceGroupsList)
.controller('InstanceGroupsListController', InstanceGroupsListController)
.controller('InstanceGroupJobsListController', InstanceGroupJobsListController)
.controller('InstanceListController', InstanceListController)
.controller('InstanceJobsController', InstanceJobsController)
.controller('InstanceJobsListController', InstanceJobsListController)
.directive('instanceGroupsMultiselect', instanceGroupsMultiselect)
.directive('instanceGroupsModal', instanceGroupsModal)
.directive('capacityAdjuster', CapacityAdjuster)