Merge pull request #601 from mabashian/275-delete-warnings

More verbose delete warnings
This commit is contained in:
Michael Abashian
2017-11-10 16:40:12 -05:00
committed by GitHub
58 changed files with 1002 additions and 258 deletions

View File

@@ -45,6 +45,7 @@ module.exports = {
ignoreTemplateLiterals: true, ignoreTemplateLiterals: true,
}], }],
'no-continue': 'off', 'no-continue': 'off',
'no-debugger': 'off',
'no-mixed-operators': 'off', 'no-mixed-operators': 'off',
'no-param-reassign': 'off', 'no-param-reassign': 'off',
'no-plusplus': 'off', 'no-plusplus': 'off',

View File

@@ -42,7 +42,7 @@ function AddCredentialsController (models, $state, strings) {
vm.form.save = data => { vm.form.save = data => {
data.user = me.get('id'); data.user = me.get('id');
return credential.request('post', data); return credential.request('post', { data });
}; };
vm.form.onSaveSuccess = res => { vm.form.onSaveSuccess = res => {

View File

@@ -27,6 +27,11 @@ function CredentialsStrings (BaseString) {
ns.permissions = { ns.permissions = {
TITLE: t.s('CREDENTIALS PERMISSIONS') TITLE: t.s('CREDENTIALS PERMISSIONS')
}; };
ns.deleteCredential = {
CONFIRM: t.s('Are you sure you want to delete this credential?'),
INVALIDATE: t.s('Doing so will invalidate the following:')
};
} }
CredentialsStrings.$inject = ['BaseStringService']; CredentialsStrings.$inject = ['BaseStringService'];

View File

@@ -88,7 +88,7 @@ function EditCredentialsController (models, $state, $scope, strings) {
data.user = me.get('id'); data.user = me.get('id');
credential.unset('inputs'); credential.unset('inputs');
return credential.request('put', data); return credential.request('put', { data });
}; };
vm.form.onSaveSuccess = () => { vm.form.onSaveSuccess = () => {

View File

@@ -33,7 +33,10 @@
<div class="modal-dialog"> <div class="modal-dialog">
<div class="Modal-content modal-content"> <div class="Modal-content modal-content">
<div class="Modal-header"> <div class="Modal-header">
<div class="Modal-title" ng-bind="promptHeader" id="prompt-header"></div> <div class="Modal-title" id="prompt-header">
<span ng-bind="promptHeader"></span>
<span class="Modal-titleResourceName" ng-bind="promptResourceName"></span>
</div>
<div class="Modal-exitHolder"> <div class="Modal-exitHolder">
<button class="close Modal-exit" data-target="#prompt-modal" data-dismiss="modal" aria-hidden="true"><i class="fa fa-times-circle"></i></button> <button class="close Modal-exit" data-target="#prompt-modal" data-dismiss="modal" aria-hidden="true"><i class="fa fa-times-circle"></i></button>
</div> </div>
@@ -42,7 +45,7 @@
</div> </div>
<div class="Modal-footer"> <div class="Modal-footer">
<a href="#" data-target="#prompt-modal" data-dismiss="modal" id="prompt_cancel_btn" class="btn Modal-defaultButton Modal-footerButton" translate>CANCEL</a> <a href="#" data-target="#prompt-modal" data-dismiss="modal" id="prompt_cancel_btn" class="btn Modal-defaultButton Modal-footerButton" translate>CANCEL</a>
<a href="" ng-class="promptActionBtnClass" ng-click="promptAction()" id="prompt_action_btn" class="btn Modal-footerButton" ng-bind="promptActionText"></a> <a href="" ng-hide="hideActionButton" ng-class="promptActionBtnClass" ng-click="promptAction()" id="prompt_action_btn" class="btn Modal-footerButton" ng-bind="promptActionText"></a>
</div> </div>
</div> </div>
<!-- modal-content --> <!-- modal-content -->

View File

@@ -1,34 +1,46 @@
let $http; let $http;
let $q; let $q;
let cache; let cache;
let strings;
function request (method, resource) { function request (method, resource, config) {
if (Array.isArray(method)) { let req = this.parseRequestConfig(method, resource, config);
const promises = method.map((_method_, i) =>
this.request(_method_, Array.isArray(resource) ? resource[i] : resource)); if (Array.isArray(req.method)) {
const promises = req.method.map((_method, i) => {
const _resource = Array.isArray(req.resource) ? req.resource[i] : req.resource;
req = this.parseRequestConfig(_method, _resource, config);
if (this.isCacheable(req)) {
return this.requestWithCache(req);
}
return this.request(req);
});
return $q.all(promises); return $q.all(promises);
} }
if (this.isCacheable(method, resource)) { if (this.isCacheable(req)) {
return this.requestWithCache(method, resource); return this.requestWithCache(req);
} }
return this.http[method](resource); return this.http[req.method](req);
} }
function requestWithCache (method, resource) { function requestWithCache (config) {
const key = cache.createKey(method, this.path, resource); const key = cache.createKey(config.method, this.path, config.resource);
return cache.get(key) return cache.get(key)
.then(data => { .then(data => {
if (data) { if (data) {
this.model[method.toUpperCase()] = data; this.model[config.method.toUpperCase()] = data;
return data; return data;
} }
return this.http[method](resource) return this.http[config.method](config)
.then(res => { .then(res => {
cache.put(key, res.data); cache.put(key, res.data);
@@ -77,18 +89,22 @@ function search (params, config) {
}); });
} }
function httpGet (resource) { function httpGet (config = {}) {
const req = { const req = {
method: 'GET', method: 'GET',
url: this.path url: this.path
}; };
if (typeof resource === 'object') { if (config.params) {
this.model.GET = resource; req.params = config.params;
}
if (typeof config.resource === 'object') {
this.model.GET = config.resource;
return $q.resolve(); return $q.resolve();
} else if (resource) { } else if (config.resource) {
req.url = `${this.path}${resource}/`; req.url = `${this.path}${config.resource}/`;
} }
return $http(req) return $http(req)
@@ -99,40 +115,51 @@ function httpGet (resource) {
}); });
} }
function httpPost (data) { function httpPost (config = {}) {
const req = { const req = {
method: 'POST', method: 'POST',
url: this.path, url: this.path,
data data: config.data
}; };
return $http(req).then(res => { return $http(req)
this.model.GET = res.data; .then(res => {
this.model.GET = res.data;
return res; return res;
}); });
} }
function httpPut (changes) { function httpPatch (config = {}) {
const model = Object.assign(this.get(), changes); const req = {
method: 'PUT',
url: `${this.path}${this.get('id')}/`,
data: config.changes
};
return $http(req);
}
function httpPut (config = {}) {
const model = _.merge(this.get(), config.data);
const req = { const req = {
method: 'PUT', method: 'PUT',
url: `${this.path}${model.id}/`, url: `${this.path}${this.get('id')}/`,
data: model data: model
}; };
return $http(req).then(res => res); return $http(req);
} }
function httpOptions (resource) { function httpOptions (config = {}) {
const req = { const req = {
method: 'OPTIONS', method: 'OPTIONS',
url: this.path url: this.path
}; };
if (resource) { if (config.resource) {
req.url = `${this.path}${resource}/`; req.url = `${this.path}${config.resource}/`;
} }
return $http(req) return $http(req)
@@ -143,6 +170,19 @@ function httpOptions (resource) {
}); });
} }
function httpDelete (config = {}) {
const req = {
method: 'DELETE',
url: this.path
};
if (config.resource) {
req.url = `${this.path}${config.resource}/`;
}
return $http(req);
}
function options (keys) { function options (keys) {
return this.find('options', keys); return this.find('options', keys);
} }
@@ -349,6 +389,22 @@ function graft (id) {
return new this.Constructor('get', item, true); return new this.Constructor('get', item, true);
} }
function getDependentResourceCounts (id) {
this.setDependentResources(id);
const promises = [];
this.dependentResources.forEach(resource => {
promises.push(resource.model.request('get', { params: resource.params })
.then(res => ({
label: resource.model.label,
count: res.data.count
})));
});
return Promise.all(promises);
}
/** /**
* `create` is called on instantiation of every model. Models can be * `create` is called on instantiation of every model. Models can be
* instantiated empty or with `GET` and/or `OPTIONS` requests that yield data. * instantiated empty or with `GET` and/or `OPTIONS` requests that yield data.
@@ -358,20 +414,22 @@ function graft (id) {
* @arg {string=} method - Populate the model with `GET` or `OPTIONS` data. * @arg {string=} method - Populate the model with `GET` or `OPTIONS` data.
* @arg {(string|Object)=} resource - An `id` reference to a particular * @arg {(string|Object)=} resource - An `id` reference to a particular
* resource or an existing model's data. * resource or an existing model's data.
* @arg {boolean=} isGraft - Create a new instance from existing model data. * @arg {config=} config - Create a new instance from existing model data.
* *
* @returns {(Object|Promise)} - Returns a reference to the model instance * @returns {(Object|Promise)} - Returns a reference to the model instance
* if an empty instance or graft is created. Otherwise, a promise yielding * if an empty instance or graft is created. Otherwise, a promise yielding
* a model instance is returned. * a model instance is returned.
*/ */
function create (method, resource, isGraft, config) { function create (method, resource, config) {
if (!method) { const req = this.parseRequestConfig(method, resource, config);
if (!req || !req.method) {
return this; return this;
} }
this.promise = this.request(method, resource, config); this.promise = this.request(req);
if (isGraft) { if (req.graft) {
return this; return this;
} }
@@ -379,17 +437,55 @@ function create (method, resource, isGraft, config) {
.then(() => this); .then(() => this);
} }
function parseRequestConfig (method, resource, config) {
if (!method) {
return null;
}
let req = {};
if (Array.isArray(method)) {
if (Array.isArray(resource)) {
req.resource = resource;
} else if (resource === null) {
req.resource = undefined;
} else if (typeof resource === 'object') {
req = resource;
}
req.method = method;
} else if (typeof method === 'string') {
if (resource === null) {
req.resource = undefined;
} else if (typeof resource === 'object') {
req = resource;
} else {
req.resource = resource;
}
req.method = method;
} else if (typeof method === 'object') {
req = method;
} else {
req = config;
req.method = method;
req.resource = resource === null ? undefined : resource;
}
return req;
}
/** /**
* Base functionality for API interaction. * Base functionality for API interaction.
* *
* @arg {string} path - The API resource for the model extending BaseModel to * @arg {string} resource - The API resource for the model extending BaseModel to
* use. * use.
* @arg {Object=} settings - Configuration applied to all instances of the * @arg {Object=} settings - Configuration applied to all instances of the
* extending model. * extending model.
* @arg {boolean=} settings.cache - Cache the model data. * @arg {boolean=} settings.cache - Cache the model data.
* *
*/ */
function BaseModel (path, settings) { function BaseModel (resource, settings) {
this.create = create; this.create = create;
this.find = find; this.find = find;
this.get = get; this.get = get;
@@ -401,33 +497,39 @@ function BaseModel (path, settings) {
this.match = match; this.match = match;
this.normalizePath = normalizePath; this.normalizePath = normalizePath;
this.options = options; this.options = options;
this.parseRequestConfig = parseRequestConfig;
this.request = request; this.request = request;
this.requestWithCache = requestWithCache; this.requestWithCache = requestWithCache;
this.search = search; this.search = search;
this.set = set; this.set = set;
this.unset = unset; this.unset = unset;
this.extend = extend; this.extend = extend;
this.getDependentResourceCounts = getDependentResourceCounts;
this.http = { this.http = {
get: httpGet.bind(this), get: httpGet.bind(this),
options: httpOptions.bind(this), options: httpOptions.bind(this),
patch: httpPatch.bind(this),
post: httpPost.bind(this), post: httpPost.bind(this),
put: httpPut.bind(this), put: httpPut.bind(this),
delete: httpDelete.bind(this)
}; };
this.model = {}; this.model = {};
this.path = this.normalizePath(path); this.path = this.normalizePath(resource);
this.label = strings.get(`${resource}.LABEL`);
this.settings = settings || {}; this.settings = settings || {};
} }
function BaseModelLoader (_$http_, _$q_, _cache_) { function BaseModelLoader (_$http_, _$q_, _cache_, ModelsStrings) {
$http = _$http_; $http = _$http_;
$q = _$q_; $q = _$q_;
cache = _cache_; cache = _cache_;
strings = ModelsStrings;
return BaseModel; return BaseModel;
} }
BaseModelLoader.$inject = ['$http', '$q', 'CacheService']; BaseModelLoader.$inject = ['$http', '$q', 'CacheService', 'ModelsStrings'];
export default BaseModelLoader; export default BaseModelLoader;

View File

@@ -1,5 +1,5 @@
let $log; let $log;
let BaseModel; let Base;
function getTruncatedVersion () { function getTruncatedVersion () {
let version; let version;
@@ -17,18 +17,18 @@ function isOpen () {
return this.get('license_info.license_type') === 'open'; return this.get('license_info.license_type') === 'open';
} }
function ConfigModel (method, resource, graft) { function ConfigModel (method, resource, config) {
BaseModel.call(this, 'config', { cache: true }); Base.call(this, 'config', { cache: true });
this.Constructor = ConfigModel; this.Constructor = ConfigModel;
this.getTruncatedVersion = getTruncatedVersion; this.getTruncatedVersion = getTruncatedVersion;
this.isOpen = isOpen; this.isOpen = isOpen;
return this.create(method, resource, graft); return this.create(method, resource, config);
} }
function ConfigModelLoader (_BaseModel_, _$log_) { function ConfigModelLoader (BaseModel, _$log_) {
BaseModel = _BaseModel_; Base = BaseModel;
$log = _$log_; $log = _$log_;
return ConfigModel; return ConfigModel;

View File

@@ -1,6 +1,10 @@
const ENCRYPTED_VALUE = '$encrypted$'; const ENCRYPTED_VALUE = '$encrypted$';
let BaseModel; let Base;
let Project;
let JobTemplate;
let Inventory;
let InventorySource;
function createFormSchema (method, config) { function createFormSchema (method, config) {
if (!config) { if (!config) {
@@ -40,22 +44,69 @@ function assignInputGroupValues (inputs) {
}); });
} }
function CredentialModel (method, resource, graft) { function setDependentResources (id) {
BaseModel.call(this, 'credentials'); this.dependentResources = [
{
model: new Project(),
params: {
credential: id
}
},
{
model: new JobTemplate(),
params: {
credential: id,
ask_credential_on_launch: false
}
},
{
model: new Inventory(),
params: {
insights_credential: id
}
},
{
model: new InventorySource(),
params: {
credential: id
}
}
];
}
function CredentialModel (method, resource, config) {
Base.call(this, 'credentials');
this.Constructor = CredentialModel; this.Constructor = CredentialModel;
this.createFormSchema = createFormSchema.bind(this); this.createFormSchema = createFormSchema.bind(this);
this.assignInputGroupValues = assignInputGroupValues.bind(this); this.assignInputGroupValues = assignInputGroupValues.bind(this);
this.setDependentResources = setDependentResources.bind(this);
return this.create(method, resource, graft); return this.create(method, resource, config);
} }
function CredentialModelLoader (_BaseModel_) { function CredentialModelLoader (
BaseModel = _BaseModel_; BaseModel,
ProjectModel,
JobTemplateModel,
InventoryModel,
InventorySourceModel
) {
Base = BaseModel;
Project = ProjectModel;
JobTemplate = JobTemplateModel;
Inventory = InventoryModel;
InventorySource = InventorySourceModel;
return CredentialModel; return CredentialModel;
} }
CredentialModelLoader.$inject = ['BaseModel']; CredentialModelLoader.$inject = [
'BaseModel',
'ProjectModel',
'JobTemplateModel',
'InventoryModel',
'InventorySourceModel'
];
export default CredentialModelLoader; export default CredentialModelLoader;

View File

@@ -1,4 +1,5 @@
let BaseModel; let Base;
let Credential;
function categorizeByKind () { function categorizeByKind () {
const group = {}; const group = {};
@@ -30,22 +31,38 @@ function mergeInputProperties () {
}); });
} }
function CredentialTypeModel (method, resource, graft) { function setDependentResources (id) {
BaseModel.call(this, 'credential_types'); this.dependentResources = [
{
model: new Credential(),
params: {
credential_type: id
}
}
];
}
function CredentialTypeModel (method, resource, config) {
Base.call(this, 'credential_types');
this.Constructor = CredentialTypeModel; this.Constructor = CredentialTypeModel;
this.categorizeByKind = categorizeByKind.bind(this); this.categorizeByKind = categorizeByKind.bind(this);
this.mergeInputProperties = mergeInputProperties.bind(this); this.mergeInputProperties = mergeInputProperties.bind(this);
this.setDependentResources = setDependentResources.bind(this);
return this.create(method, resource, graft); return this.create(method, resource, config);
} }
function CredentialTypeModelLoader (_BaseModel_) { function CredentialTypeModelLoader (BaseModel, CredentialModel) {
BaseModel = _BaseModel_; Base = BaseModel;
Credential = CredentialModel;
return CredentialTypeModel; return CredentialTypeModel;
} }
CredentialTypeModelLoader.$inject = ['BaseModel']; CredentialTypeModelLoader.$inject = [
'BaseModel',
'CredentialModel'
];
export default CredentialTypeModelLoader; export default CredentialTypeModelLoader;

View File

@@ -0,0 +1,36 @@
let Base;
let JobTemplate;
function setDependentResources (id) {
this.dependentResources = [
{
model: new JobTemplate(),
params: {
inventory: id
}
}
];
}
function InventoryModel (method, resource, config) {
Base.call(this, 'inventories');
this.Constructor = InventoryModel;
this.setDependentResources = setDependentResources.bind(this);
return this.create(method, resource, config);
}
function InventoryModelLoader (BaseModel, JobTemplateModel) {
Base = BaseModel;
JobTemplate = JobTemplateModel;
return InventoryModel;
}
InventoryModelLoader.$inject = [
'BaseModel',
'JobTemplateModel'
];
export default InventoryModelLoader;

View File

@@ -0,0 +1,36 @@
let Base;
let InventorySource;
function setDependentResources (id) {
this.dependentResources = [
{
model: new InventorySource(),
params: {
source_script: id
}
}
];
}
function InventoryScriptModel (method, resource, config) {
Base.call(this, 'inventory_scripts');
this.Constructor = InventoryScriptModel;
this.setDependentResources = setDependentResources.bind(this);
return this.create(method, resource, config);
}
function InventoryScriptModelLoader (BaseModel, InventorySourceModel) {
Base = BaseModel;
InventorySource = InventorySourceModel;
return InventoryScriptModel;
}
InventoryScriptModelLoader.$inject = [
'BaseModel',
'InventorySourceModel'
];
export default InventoryScriptModelLoader;

View File

@@ -0,0 +1,39 @@
let Base;
let WorkflowJobTemplateNode;
function setDependentResources (id) {
this.dependentResources = [
{
model: new WorkflowJobTemplateNode(),
params: {
unified_job_template: id
}
}
];
}
function InventorySourceModel (method, resource, config) {
Base.call(this, 'inventory_sources');
this.Constructor = InventorySourceModel;
this.setDependentResources = setDependentResources.bind(this);
return this.create(method, resource, config);
}
function InventorySourceModelLoader (
BaseModel,
WorkflowJobTemplateNodeModel
) {
Base = BaseModel;
WorkflowJobTemplateNode = WorkflowJobTemplateNodeModel;
return InventorySourceModel;
}
InventorySourceModelLoader.$inject = [
'BaseModel',
'WorkflowJobTemplateNodeModel'
];
export default InventorySourceModelLoader;

View File

@@ -0,0 +1,36 @@
let Base;
let WorkflowJobTemplateNode;
function setDependentResources (id) {
this.dependentResources = [
{
model: new WorkflowJobTemplateNode(),
params: {
unified_job_template: id
}
}
];
}
function JobTemplateModel (method, resource, config) {
Base.call(this, 'job_templates');
this.Constructor = JobTemplateModel;
this.setDependentResources = setDependentResources.bind(this);
return this.create(method, resource, config);
}
function JobTemplateModelLoader (BaseModel, WorkflowJobTemplateNodeModel) {
Base = BaseModel;
WorkflowJobTemplateNode = WorkflowJobTemplateNodeModel;
return JobTemplateModel;
}
JobTemplateModelLoader.$inject = [
'BaseModel',
'WorkflowJobTemplateNodeModel'
];
export default JobTemplateModelLoader;

View File

@@ -1,11 +1,11 @@
let BaseModel; let Base;
function MeModel (method, resource, graft) { function MeModel (method, resource, config) {
BaseModel.call(this, 'me'); Base.call(this, 'me');
this.Constructor = MeModel; this.Constructor = MeModel;
return this.create(method, resource, graft) return this.create(method, resource, config)
.then(() => { .then(() => {
if (this.has('results')) { if (this.has('results')) {
_.merge(this.model.GET, this.get('results[0]')); _.merge(this.model.GET, this.get('results[0]'));
@@ -16,8 +16,8 @@ function MeModel (method, resource, graft) {
}); });
} }
function MeModelLoader (_BaseModel_) { function MeModelLoader (BaseModel) {
BaseModel = _BaseModel_; Base = BaseModel;
return MeModel; return MeModel;
} }

View File

@@ -1,19 +1,21 @@
let BaseModel; let Base;
function OrganizationModel (method, resource, graft) { function OrganizationModel (method, resource, config) {
BaseModel.call(this, 'organizations'); Base.call(this, 'organizations');
this.Constructor = OrganizationModel; this.Constructor = OrganizationModel;
return this.create(method, resource, graft); return this.create(method, resource, config);
} }
function OrganizationModelLoader (_BaseModel_) { function OrganizationModelLoader (BaseModel) {
BaseModel = _BaseModel_; Base = BaseModel;
return OrganizationModel; return OrganizationModel;
} }
OrganizationModelLoader.$inject = ['BaseModel']; OrganizationModelLoader.$inject = [
'BaseModel'
];
export default OrganizationModelLoader; export default OrganizationModelLoader;

View File

@@ -0,0 +1,59 @@
let Base;
let JobTemplate;
let WorkflowJobTemplateNode;
let InventorySource;
function setDependentResources (id) {
this.dependentResources = [
{
model: new JobTemplate(),
params: {
project: id
}
},
{
model: new WorkflowJobTemplateNode(),
params: {
unified_job_template: id
}
},
{
model: new InventorySource(),
params: {
source_project: id
}
}
];
}
function ProjectModel (method, resource, config) {
Base.call(this, 'projects');
this.Constructor = ProjectModel;
this.setDependentResources = setDependentResources.bind(this);
return this.create(method, resource, config);
}
function ProjectModelLoader (
BaseModel,
JobTemplateModel,
WorkflowJobTemplateNodeModel,
InventorySourceModel,
) {
Base = BaseModel;
JobTemplate = JobTemplateModel;
WorkflowJobTemplateNode = WorkflowJobTemplateNodeModel;
InventorySource = InventorySourceModel;
return ProjectModel;
}
ProjectModelLoader.$inject = [
'BaseModel',
'JobTemplateModel',
'WorkflowJobTemplateNodeModel',
'InventorySourceModel'
];
export default ProjectModelLoader;

View File

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

View File

@@ -6,6 +6,14 @@ import Credential from '~models/Credential';
import CredentialType from '~models/CredentialType'; import CredentialType from '~models/CredentialType';
import Me from '~models/Me'; import Me from '~models/Me';
import Organization from '~models/Organization'; import Organization from '~models/Organization';
import Project from '~models/Project';
import JobTemplate from '~models/JobTemplate';
import WorkflowJobTemplateNode from '~models/WorkflowJobTemplateNode';
import InventorySource from '~models/InventorySource';
import Inventory from '~models/Inventory';
import InventoryScript from '~models/InventoryScript';
import ModelsStrings from '~models/models.strings';
const MODULE_NAME = 'at.lib.models'; const MODULE_NAME = 'at.lib.models';
@@ -18,6 +26,13 @@ angular
.service('CredentialModel', Credential) .service('CredentialModel', Credential)
.service('CredentialTypeModel', CredentialType) .service('CredentialTypeModel', CredentialType)
.service('MeModel', Me) .service('MeModel', Me)
.service('OrganizationModel', Organization); .service('OrganizationModel', Organization)
.service('ProjectModel', Project)
.service('JobTemplateModel', JobTemplate)
.service('WorkflowJobTemplateNodeModel', WorkflowJobTemplateNode)
.service('InventorySourceModel', InventorySource)
.service('InventoryModel', Inventory)
.service('InventoryScriptModel', InventoryScript)
.service('ModelsStrings', ModelsStrings);
export default MODULE_NAME; export default MODULE_NAME;

View File

@@ -0,0 +1,52 @@
function ModelsStrings (BaseString) {
BaseString.call(this, 'models');
const { t } = this;
const ns = this.models;
ns.credentials = {
LABEL: t.s('Credentials')
};
ns.credential_types = {
LABEL: t.s('Credential Types')
};
ns.inventories = {
LABEL: t.s('Inventories')
};
ns.inventory_scripts = {
LABEL: t.s('Inventory Scripts')
};
ns.inventory_sources = {
LABEL: t.s('Inventory Sources')
};
ns.job_templates = {
LABEL: t.s('Job Templates')
};
ns.organizations = {
LABEL: t.s('Organizations')
};
ns.projects = {
LABEL: t.s('Projects')
};
ns.workflow_job_template_nodes = {
LABEL: t.s('Workflow Job Template Nodes')
};
}
ModelsStrings.$inject = ['BaseStringService'];
export default ModelsStrings;

View File

@@ -4,7 +4,6 @@ let i18n;
function BaseStringService (namespace) { function BaseStringService (namespace) {
const ERROR_NO_NAMESPACE = 'BaseString cannot be extended without providing a namespace'; const ERROR_NO_NAMESPACE = 'BaseString cannot be extended without providing a namespace';
const ERROR_NO_STRING = 'No string exists with this name';
if (!namespace) { if (!namespace) {
throw new Error(ERROR_NO_NAMESPACE); throw new Error(ERROR_NO_NAMESPACE);
@@ -67,8 +66,6 @@ function BaseStringService (namespace) {
* the more globally relevant strings defined here. Strings with with dots as delimeters are * the more globally relevant strings defined here. Strings with with dots as delimeters are
* supported to give flexibility to extending classes to nest strings as necessary. * supported to give flexibility to extending classes to nest strings as necessary.
* *
* If no match is found, an error is thrown to alert the developer immediately instead of
* failing silently.
* *
* The `t.s` and `t.p` calls should only be used where strings are defined in * The `t.s` and `t.p` calls should only be used where strings are defined in
* <name>.strings.js` files. To use translated strings elsewhere, access them through this * <name>.strings.js` files. To use translated strings elsewhere, access them through this
@@ -88,13 +85,13 @@ function BaseStringService (namespace) {
} else { } else {
value = value[key]; value = value[key];
} }
if (!value) {
throw new Error(`${ERROR_NO_STRING}: ${name}`);
}
}); });
return typeof value === 'string' ? value : value(...args); if (!value || typeof value === 'string') {
return value;
}
return value(...args);
}; };
} }

View File

@@ -0,0 +1,15 @@
function CredentialTypesStrings (BaseString) {
BaseString.call(this, 'credential_types');
let t = this.t;
let ns = this.credential_types;
ns.deleteCredentialType = {
CONFIRM: t.s('Are you sure you want to delete this credential type?'),
CREDENTIAL_TYPE_IN_USE: t.s('This credential type is currently being used by one or more credentials. Credentials that use this credential type must be deleted before the credential type can be deleted.')
};
}
CredentialTypesStrings.$inject = ['BaseStringService'];
export default CredentialTypesStrings;

View File

@@ -5,11 +5,16 @@
*************************************************/ *************************************************/
export default ['$rootScope', '$scope', 'Wait', 'CredentialTypesList', export default ['$rootScope', '$scope', 'Wait', 'CredentialTypesList',
'GetBasePath', 'Rest', 'ProcessErrors', 'Prompt', '$state', '$filter', 'Dataset', 'rbacUiControlService', 'Alert', '$q', 'GetBasePath', 'Rest', 'ProcessErrors', 'Prompt', '$state', '$filter',
'Dataset', 'rbacUiControlService', 'Alert', '$q', 'CredentialTypeModel',
'CredentialTypesStrings', 'i18n',
function( function(
$rootScope, $scope, Wait, CredentialTypesList, $rootScope, $scope, Wait, CredentialTypesList,
GetBasePath, Rest, ProcessErrors, Prompt, $state, $filter, Dataset, rbacUiControlService, Alert, $q GetBasePath, Rest, ProcessErrors, Prompt, $state, $filter,
Dataset, rbacUiControlService, Alert, $q, CredentialType,
CredentialTypesStrings, i18n
) { ) {
let credentialType = new CredentialType();
var defaultUrl = GetBasePath('credential_types'), var defaultUrl = GetBasePath('credential_types'),
list = CredentialTypesList; list = CredentialTypesList;
@@ -58,8 +63,7 @@ export default ['$rootScope', '$scope', 'Wait', 'CredentialTypesList',
$('#prompt-modal').modal('hide'); $('#prompt-modal').modal('hide');
Wait('start'); Wait('start');
var url = defaultUrl + id + '/'; var url = defaultUrl + id + '/';
Rest.setUrl(url); credentialType.request('delete', id)
Rest.destroy()
.then(() => { .then(() => {
let reloadListStateParams = null; let reloadListStateParams = null;
@@ -83,13 +87,29 @@ export default ['$rootScope', '$scope', 'Wait', 'CredentialTypesList',
}); });
}; };
var bodyHtml = '<div class="Prompt-bodyQuery">Are you sure you want to delete the credential type below?</div><div class="Prompt-bodyTarget">' + $filter('sanitize')(name) + '</div>'; credentialType.getDependentResourceCounts(id)
Prompt({ .then((counts) => {
hdr: 'Delete', let credentialTypeInUse = false;
body: bodyHtml, let deleteModalBody = `<div class="Prompt-bodyQuery">${CredentialTypesStrings.get('deleteCredentialType.CONFIRM')}</div>`;
action: action,
actionText: 'DELETE' counts.forEach(countObj => {
}); if(countObj.count && countObj.count > 0) {
credentialTypeInUse = true;
}
});
if (credentialTypeInUse) {
deleteModalBody = `<div class="Prompt-bodyQuery">${CredentialTypesStrings.get('deleteCredentialType.CREDENTIAL_TYPE_IN_USE')}</div>`;
}
Prompt({
hdr: i18n._('Delete') + ' ' + $filter('sanitize')(name),
body: deleteModalBody,
action: action,
hideActionButton: credentialTypeInUse ? true : false,
actionText: 'DELETE'
});
});
}; };
$scope.addCredentialType = function() { $scope.addCredentialType = function() {

View File

@@ -10,6 +10,7 @@ import credentialTypesEdit from './edit/main';
import list from './credential-types.list'; import list from './credential-types.list';
import form from './credential-types.form'; import form from './credential-types.form';
import { N_ } from '../i18n'; import { N_ } from '../i18n';
import CredentialTypesStrings from './credential-types.strings';
export default export default
angular.module('credentialTypes', [ angular.module('credentialTypes', [
@@ -19,6 +20,7 @@ angular.module('credentialTypes', [
]) ])
.factory('CredentialTypesList', list) .factory('CredentialTypesList', list)
.factory('CredentialTypesForm', form) .factory('CredentialTypesForm', form)
.service('CredentialTypesStrings', CredentialTypesStrings)
.config(['$stateProvider', 'stateDefinitionsProvider', .config(['$stateProvider', 'stateDefinitionsProvider',
function($stateProvider, stateDefinitionsProvider) { function($stateProvider, stateDefinitionsProvider) {
let stateDefinitions = stateDefinitionsProvider.$get(); let stateDefinitions = stateDefinitionsProvider.$get();

View File

@@ -6,9 +6,12 @@
export default ['$scope', 'Rest', 'CredentialList', 'Prompt', 'ProcessErrors', 'GetBasePath', export default ['$scope', 'Rest', 'CredentialList', 'Prompt', 'ProcessErrors', 'GetBasePath',
'Wait', '$state', '$filter', 'rbacUiControlService', 'Dataset', 'credentialType', 'i18n', 'Wait', '$state', '$filter', 'rbacUiControlService', 'Dataset', 'credentialType', 'i18n',
'CredentialModel', 'CredentialsStrings',
function($scope, Rest, CredentialList, Prompt, function($scope, Rest, CredentialList, Prompt,
ProcessErrors, GetBasePath, Wait, $state, $filter, rbacUiControlService, Dataset, ProcessErrors, GetBasePath, Wait, $state, $filter, rbacUiControlService, Dataset,
credentialType, i18n) { credentialType, i18n, Credential, CredentialsStrings) {
let credential = new Credential();
var list = CredentialList, var list = CredentialList,
defaultUrl = GetBasePath('credentials'); defaultUrl = GetBasePath('credentials');
@@ -83,8 +86,7 @@ export default ['$scope', 'Rest', 'CredentialList', 'Prompt', 'ProcessErrors', '
$('#prompt-modal').modal('hide'); $('#prompt-modal').modal('hide');
Wait('start'); Wait('start');
var url = defaultUrl + id + '/'; var url = defaultUrl + id + '/';
Rest.setUrl(url); credential.request('delete', id)
Rest.destroy()
.then(() => { .then(() => {
let reloadListStateParams = null; let reloadListStateParams = null;
@@ -109,12 +111,32 @@ export default ['$scope', 'Rest', 'CredentialList', 'Prompt', 'ProcessErrors', '
}); });
}; };
Prompt({ credential.getDependentResourceCounts(id)
hdr: i18n._('Delete'), .then((counts) => {
body: '<div class="Prompt-bodyQuery">' + i18n._('Are you sure you want to delete the credential below?') + '</div><div class="Prompt-bodyTarget">' + $filter('sanitize')(name) + '</div>', const invalidateRelatedLines = [];
action: action, let deleteModalBody = `<div class="Prompt-bodyQuery">${CredentialsStrings.get('deleteCredential.CONFIRM')}</div>`;
actionText: i18n._('DELETE')
}); counts.forEach(countObj => {
if(countObj.count && countObj.count > 0) {
invalidateRelatedLines.push(`<div><span class="Prompt-warningResourceTitle">${countObj.label}</span><span class="badge List-titleBadge">${countObj.count}</span></div>`);
}
});
if (invalidateRelatedLines && invalidateRelatedLines.length > 0) {
deleteModalBody = `<div class="Prompt-bodyQuery">${CredentialsStrings.get('deleteCredential.CONFIRM')} ${CredentialsStrings.get('deleteCredential.INVALIDATE')}</div>`;
invalidateRelatedLines.forEach(invalidateRelatedLine => {
deleteModalBody += invalidateRelatedLine;
});
}
Prompt({
hdr: i18n._('Delete'),
resourceName: $filter('sanitize')(name),
body: deleteModalBody,
action: action,
actionText: 'DELETE'
});
});
}; };
} }
]; ];

View File

@@ -13,7 +13,9 @@
function InventoriesList($scope, function InventoriesList($scope,
$filter, Rest, InventoryList, Prompt, $filter, Rest, InventoryList, Prompt,
ProcessErrors, GetBasePath, Wait, $state, ProcessErrors, GetBasePath, Wait, $state,
Dataset, canAdd, i18n) { Dataset, canAdd, i18n, Inventory, InventoryHostsStrings) {
let inventory = new Inventory();
let list = InventoryList, let list = InventoryList,
defaultUrl = GetBasePath('inventory'); defaultUrl = GetBasePath('inventory');
@@ -85,8 +87,7 @@ function InventoriesList($scope,
var url = defaultUrl + id + '/'; var url = defaultUrl + id + '/';
Wait('start'); Wait('start');
$('#prompt-modal').modal('hide'); $('#prompt-modal').modal('hide');
Rest.setUrl(url); inventory.request('delete', id)
Rest.destroy()
.then(() => { .then(() => {
Wait('stop'); Wait('stop');
}) })
@@ -97,13 +98,34 @@ function InventoriesList($scope,
}); });
}; };
Prompt({ inventory.getDependentResourceCounts(id)
hdr: 'Delete', .then((counts) => {
body: '<div class="Prompt-bodyQuery">' + i18n._('Are you sure you want to delete the inventory below?') + '</div><div class="Prompt-bodyTarget">' + $filter('sanitize')(name) + '</div>' + const invalidateRelatedLines = [];
'<div class="Prompt-bodyNote"><span class="Prompt-bodyNote--emphasis">Note:</span> ' + i18n._('The inventory will be in a pending status until the final delete is processed.') + '</div>', let deleteModalBody = `<div class="Prompt-bodyQuery">${InventoryHostsStrings.get('deleteInventory.CONFIRM')}</div>`;
action: action,
actionText: i18n._('DELETE') counts.forEach(countObj => {
}); if(countObj.count && countObj.count > 0) {
invalidateRelatedLines.push(`<div><span class="Prompt-warningResourceTitle">${countObj.label}</span><span class="badge List-titleBadge">${countObj.count}</span></div>`);
}
});
if (invalidateRelatedLines && invalidateRelatedLines.length > 0) {
deleteModalBody = `<div class="Prompt-bodyQuery">${InventoryHostsStrings.get('deleteInventory.CONFIRM')} ${InventoryHostsStrings.get('deleteInventory.INVALIDATE')}</div>`;
invalidateRelatedLines.forEach(invalidateRelatedLine => {
deleteModalBody += invalidateRelatedLine;
});
}
deleteModalBody += '<div class="Prompt-bodyNote"><span class="Prompt-bodyNote--emphasis">Note:</span> ' + i18n._('The inventory will be in a pending status until the final delete is processed.') + '</div>';
Prompt({
hdr: i18n._('Delete'),
resourceName: $filter('sanitize')(name),
body: deleteModalBody,
action: action,
actionText: 'DELETE'
});
});
}; };
$scope.$on(`ws-inventories`, function(e, data){ $scope.$on(`ws-inventories`, function(e, data){
@@ -131,5 +153,6 @@ function InventoriesList($scope,
export default ['$scope', export default ['$scope',
'$filter', 'Rest', 'InventoryList', 'Prompt', '$filter', 'Rest', 'InventoryList', 'Prompt',
'ProcessErrors', 'GetBasePath', 'Wait', 'ProcessErrors', 'GetBasePath', 'Wait',
'$state', 'Dataset', 'canAdd', 'i18n', InventoriesList '$state', 'Dataset', 'canAdd', 'i18n', 'InventoryModel',
'InventoryHostsStrings', InventoriesList
]; ];

View File

@@ -9,12 +9,15 @@
'ViewUpdateStatus', 'rbacUiControlService', 'GetBasePath', 'ViewUpdateStatus', 'rbacUiControlService', 'GetBasePath',
'GetSyncStatusMsg', 'Dataset', 'Find', 'QuerySet', 'GetSyncStatusMsg', 'Dataset', 'Find', 'QuerySet',
'inventoryData', '$filter', 'Prompt', 'Wait', 'SourcesService', 'inventorySourceOptions', 'inventoryData', '$filter', 'Prompt', 'Wait', 'SourcesService', 'inventorySourceOptions',
'canAdd', 'hasSyncableSources', 'i18n', 'canAdd', 'hasSyncableSources', 'i18n', 'InventoryHostsStrings', 'InventorySourceModel',
function($scope, $rootScope, $state, $stateParams, SourcesListDefinition, function($scope, $rootScope, $state, $stateParams, SourcesListDefinition,
InventoryUpdate, CancelSourceUpdate, InventoryUpdate, CancelSourceUpdate,
ViewUpdateStatus, rbacUiControlService, GetBasePath, GetSyncStatusMsg, ViewUpdateStatus, rbacUiControlService, GetBasePath, GetSyncStatusMsg,
Dataset, Find, qs, inventoryData, $filter, Prompt, Dataset, Find, qs, inventoryData, $filter, Prompt,
Wait, SourcesService, inventorySourceOptions, canAdd, hasSyncableSources, i18n){ Wait, SourcesService, inventorySourceOptions, canAdd, hasSyncableSources, i18n,
InventoryHostsStrings, InventorySource){
let inventorySource = new InventorySource();
let list = SourcesListDefinition; let list = SourcesListDefinition;
var inventory_source; var inventory_source;
@@ -117,7 +120,6 @@
$state.go('inventories.edit.inventory_sources.edit', {inventory_source_id: id}); $state.go('inventories.edit.inventory_sources.edit', {inventory_source_id: id});
}; };
$scope.deleteSource = function(inventory_source){ $scope.deleteSource = function(inventory_source){
var body = '<div class=\"Prompt-bodyQuery\">' + i18n._('Are you sure you want to permanently delete the inventory source below from the inventory?') + '</div><div class=\"Prompt-bodyTarget\">' + $filter('sanitize')(inventory_source.name) + '</div>';
var action = function(){ var action = function(){
delete $rootScope.promptActionBtnClass; delete $rootScope.promptActionBtnClass;
Wait('start'); Wait('start');
@@ -137,14 +139,35 @@
Wait('stop'); Wait('stop');
}); });
}; };
// Prompt depends on having $rootScope.promptActionBtnClass available...
Prompt({ inventorySource.getDependentResourceCounts(inventory_source.id)
hdr: i18n._('Delete Source'), .then((counts) => {
body: body, const invalidateRelatedLines = [];
action: action, let deleteModalBody = `<div class="Prompt-bodyQuery">${InventoryHostsStrings.get('deleteSource.CONFIRM')}</div>`;
actionText: i18n._('DELETE'),
}); counts.forEach(countObj => {
$rootScope.promptActionBtnClass = 'Modal-errorButton'; if(countObj.count && countObj.count > 0) {
invalidateRelatedLines.push(`<div><span class="Prompt-warningResourceTitle">${countObj.label}</span><span class="badge List-titleBadge">${countObj.count}</span></div>`);
}
});
if (invalidateRelatedLines && invalidateRelatedLines.length > 0) {
deleteModalBody = `<div class="Prompt-bodyQuery">${InventoryHostsStrings.get('deleteSource.CONFIRM')} ${InventoryHostsStrings.get('deleteSource.INVALIDATE')}</div>`;
invalidateRelatedLines.forEach(invalidateRelatedLine => {
deleteModalBody += invalidateRelatedLine;
});
}
Prompt({
hdr: i18n._('Delete Source'),
resourceName: $filter('sanitize')(inventory_source.name),
body: deleteModalBody,
action: action,
actionText: 'DELETE'
});
$rootScope.promptActionBtnClass = 'Modal-errorButton';
});
}; };
$scope.updateSource = function(inventory_source) { $scope.updateSource = function(inventory_source) {

View File

@@ -4,6 +4,16 @@ function InventoryHostsStrings (BaseString) {
let t = this.t; let t = this.t;
let ns = this['inventory-hosts']; let ns = this['inventory-hosts'];
ns.deleteInventory = {
CONFIRM: t.s('Are you sure you want to delete this inventory?'),
INVALIDATE: t.s('Doing so will invalidate the following:')
};
ns.deleteSource = {
CONFIRM: t.s('Are you sure you want to delete this inventory source?'),
INVALIDATE: t.s('Doing so will invalidate the following:')
};
ns.deletegroup = { ns.deletegroup = {
GROUP: count => t.p(count, 'group', 'groups'), GROUP: count => t.p(count, 'group', 'groups'),
HOST: count => t.p(count, 'host', 'hosts'), HOST: count => t.p(count, 'host', 'hosts'),

View File

@@ -0,0 +1,15 @@
function InventoryScriptsStrings (BaseString) {
BaseString.call(this, 'inventory_scripts');
let t = this.t;
let ns = this.inventory_scripts;
ns.deleteInventoryScript = {
CONFIRM: t.s('Are you sure you want to delete this inventory script?'),
INVALIDATE: t.s('Doing so will invalidate the following:')
};
}
InventoryScriptsStrings.$inject = ['BaseStringService'];
export default InventoryScriptsStrings;

View File

@@ -5,11 +5,16 @@
*************************************************/ *************************************************/
export default ['$rootScope', '$scope', 'Wait', 'InventoryScriptsList', export default ['$rootScope', '$scope', 'Wait', 'InventoryScriptsList',
'GetBasePath', 'Rest', 'ProcessErrors', 'Prompt', '$state', '$filter', 'Dataset', 'rbacUiControlService', 'GetBasePath', 'Rest', 'ProcessErrors', 'Prompt', '$state', '$filter',
'Dataset', 'rbacUiControlService', 'InventoryScriptModel', 'InventoryScriptsStrings',
'i18n',
function( function(
$rootScope, $scope, Wait, InventoryScriptsList, $rootScope, $scope, Wait, InventoryScriptsList,
GetBasePath, Rest, ProcessErrors, Prompt, $state, $filter, Dataset, rbacUiControlService GetBasePath, Rest, ProcessErrors, Prompt, $state, $filter,
Dataset, rbacUiControlService, InventoryScript, InventoryScriptsStrings,
i18n
) { ) {
let inventoryScript = new InventoryScript();
var defaultUrl = GetBasePath('inventory_scripts'), var defaultUrl = GetBasePath('inventory_scripts'),
list = InventoryScriptsList; list = InventoryScriptsList;
@@ -48,8 +53,7 @@ export default ['$rootScope', '$scope', 'Wait', 'InventoryScriptsList',
$('#prompt-modal').modal('hide'); $('#prompt-modal').modal('hide');
Wait('start'); Wait('start');
var url = defaultUrl + id + '/'; var url = defaultUrl + id + '/';
Rest.setUrl(url); inventoryScript.request('delete', id)
Rest.destroy()
.then(() => { .then(() => {
let reloadListStateParams = null; let reloadListStateParams = null;
@@ -73,13 +77,32 @@ export default ['$rootScope', '$scope', 'Wait', 'InventoryScriptsList',
}); });
}; };
var bodyHtml = '<div class="Prompt-bodyQuery">Are you sure you want to delete the inventory script below?</div><div class="Prompt-bodyTarget">' + $filter('sanitize')(name) + '</div>'; inventoryScript.getDependentResourceCounts(id)
Prompt({ .then((counts) => {
hdr: 'Delete', const invalidateRelatedLines = [];
body: bodyHtml, let deleteModalBody = `<div class="Prompt-bodyQuery">${InventoryScriptsStrings.get('deleteInventoryScript.CONFIRM')}</div>`;
action: action,
actionText: 'DELETE' counts.forEach(countObj => {
}); if(countObj.count && countObj.count > 0) {
invalidateRelatedLines.push(`<div><span class="Prompt-warningResourceTitle">${countObj.label}</span><span class="badge List-titleBadge">${countObj.count}</span></div>`);
}
});
if (invalidateRelatedLines && invalidateRelatedLines.length > 0) {
deleteModalBody = `<div class="Prompt-bodyQuery">${InventoryScriptsStrings.get('deleteInventoryScript.CONFIRM')} ${InventoryScriptsStrings.get('deleteInventoryScript.INVALIDATE')}</div>`;
invalidateRelatedLines.forEach(invalidateRelatedLine => {
deleteModalBody += invalidateRelatedLine;
});
}
Prompt({
hdr: i18n._('Delete'),
resourceName: $filter('sanitize')(name),
body: deleteModalBody,
action: action,
actionText: 'DELETE'
});
});
}; };
$scope.addCustomInv = function() { $scope.addCustomInv = function() {

View File

@@ -10,6 +10,7 @@ import inventoryScriptsEdit from './edit/main';
import list from './inventory-scripts.list'; import list from './inventory-scripts.list';
import form from './inventory-scripts.form'; import form from './inventory-scripts.form';
import { N_ } from '../i18n'; import { N_ } from '../i18n';
import InventoryScriptsStrings from './inventory-scripts.strings';
export default export default
angular.module('inventoryScripts', [ angular.module('inventoryScripts', [
@@ -19,6 +20,7 @@ angular.module('inventoryScripts', [
]) ])
.factory('InventoryScriptsList', list) .factory('InventoryScriptsList', list)
.factory('InventoryScriptsForm', form) .factory('InventoryScriptsForm', form)
.service('InventoryScriptsStrings', InventoryScriptsStrings)
.config(['$stateProvider', 'stateDefinitionsProvider', .config(['$stateProvider', 'stateDefinitionsProvider',
function($stateProvider, stateDefinitionsProvider) { function($stateProvider, stateDefinitionsProvider) {
let stateDefinitions = stateDefinitionsProvider.$get(); let stateDefinitions = stateDefinitionsProvider.$get();

View File

@@ -91,11 +91,9 @@ function ($q, Prompt, $filter, Wait, Rest, $state, ProcessErrors, InitiatePlaybo
deleteJob: function(job) { deleteJob: function(job) {
Prompt({ Prompt({
hdr: i18n._("Delete Job"), hdr: i18n._("Delete Job"),
resourceName: `#${job.id} ` + $filter('sanitize')(job.name),
body: `<div class='Prompt-bodyQuery'> body: `<div class='Prompt-bodyQuery'>
${i18n._("Are you sure you want to delete the job below?")} ${i18n._("Are you sure you want to delete this job?")}
</div>
<div class='Prompt-bodyTarget'>
#${job.id} ${$filter('sanitize')(job.name)}
</div>`, </div>`,
action: function() { action: function() {
Wait('start'); Wait('start');
@@ -140,11 +138,9 @@ function ($q, Prompt, $filter, Wait, Rest, $state, ProcessErrors, InitiatePlaybo
Prompt({ Prompt({
hdr: i18n._('Cancel Job'), hdr: i18n._('Cancel Job'),
resourceName: `#${job.id} ` + $filter('sanitize')(job.name),
body: `<div class='Prompt-bodyQuery' translate> body: `<div class='Prompt-bodyQuery' translate>
${i18n._("Are you sure you want to cancel the job below?")} ${i18n._("Are you sure you want to cancel this job?")}
</div>
<div class='Prompt-bodyTarget'>
#${job.id} ${$filter('sanitize')(job.name)}
</div>`, </div>`,
action: function() { action: function() {
Wait('start'); Wait('start');

View File

@@ -106,10 +106,11 @@
scope.removeCancelJob(); scope.removeCancelJob();
} }
scope.removeCancelJob = scope.$on('CancelJob', function() { scope.removeCancelJob = scope.$on('CancelJob', function() {
var cancelBody = "<div class=\"Prompt-bodyQuery\">" + i18n._("Submit the request to cancel?") + "</div>"; var cancelBody = "<div class=\"Prompt-bodyQuery\">" + i18n._("Are you sure you want to submit the request to cancel this job?") + "</div>";
var deleteBody = "<div class=\"Prompt-bodyQuery\">" + i18n._("Are you sure you want to delete the job below?") + "</div><div class=\"Prompt-bodyTarget\" translate>#" + id + " " + $filter('sanitize')(job.name) + "</div>"; var deleteBody = "<div class=\"Prompt-bodyQuery\">" + i18n._("Are you sure you want to delete this job?") + "</div>";
Prompt({ Prompt({
hdr: hdr, hdr: hdr,
resourceName: `#${job.id} ` + $filter('sanitize')(job.name),
body: (action_label === 'cancel' || job.status === 'new') ? cancelBody : deleteBody, body: (action_label === 'cancel' || job.status === 'new') ? cancelBody : deleteBody,
action: action, action: action,
actionText: (action_label === 'cancel' || job.status === 'new') ? i18n._("OK") : i18n._("DELETE") actionText: (action_label === 'cancel' || job.status === 'new') ? i18n._("OK") : i18n._("DELETE")

View File

@@ -193,10 +193,11 @@
}); });
}); });
}; };
var bodyHtml = '<div class="Prompt-bodyQuery">' + i18n._('Are you sure you want to delete the notification template below?') + '</div><div class="Prompt-bodyTarget">' + $filter('sanitize')(name) + '</div>';
Prompt({ Prompt({
hdr: i18n._('Delete'), hdr: i18n._('Delete'),
body: bodyHtml, resourceName: $filter('sanitize')(name),
body: '<div class="Prompt-bodyQuery">' + i18n._('Are you sure you want to delete this notification template?') + '</div>',
action: action, action: action,
actionText: i18n._('DELETE') actionText: i18n._('DELETE')
}); });

View File

@@ -169,7 +169,8 @@ export default ['$stateParams', '$scope', '$rootScope',
Prompt({ Prompt({
hdr: i18n._('Delete'), hdr: i18n._('Delete'),
body: '<div class="Prompt-bodyQuery">' + i18n._('Are you sure you want to delete the organization below?') + '</div><div class="Prompt-bodyTarget">' + $filter('sanitize')(name) + '</div>', resourceName: $filter('sanitize')(name),
body: '<div class="Prompt-bodyQuery">' + i18n._('Are you sure you want to delete this organization? This makes everything in this organization unavailable.') + '</div>',
action: action, action: action,
actionText: i18n._('DELETE') actionText: i18n._('DELETE')
}); });

View File

@@ -7,14 +7,16 @@
export default ['$scope', '$rootScope', '$log', 'Rest', 'Alert', export default ['$scope', '$rootScope', '$log', 'Rest', 'Alert',
'ProjectList', 'Prompt', 'ProcessErrors', 'GetBasePath', 'ProjectUpdate', 'ProjectList', 'Prompt', 'ProcessErrors', 'GetBasePath', 'ProjectUpdate',
'Wait', 'Empty', 'Find', 'GetProjectIcon', 'GetProjectToolTip', '$filter', 'Wait', 'Empty', 'Find', 'GetProjectIcon', 'GetProjectToolTip', '$filter',
'$state', 'rbacUiControlService', 'Dataset', 'i18n', 'QuerySet', '$state', 'rbacUiControlService', 'Dataset', 'i18n', 'QuerySet', 'ProjectModel',
'ProjectsStrings',
function($scope, $rootScope, $log, Rest, Alert, ProjectList, function($scope, $rootScope, $log, Rest, Alert, ProjectList,
Prompt, ProcessErrors, GetBasePath, ProjectUpdate, Wait, Empty, Find, Prompt, ProcessErrors, GetBasePath, ProjectUpdate, Wait, Empty, Find,
GetProjectIcon, GetProjectToolTip, $filter, $state, rbacUiControlService, GetProjectIcon, GetProjectToolTip, $filter, $state, rbacUiControlService,
Dataset, i18n, qs) { Dataset, i18n, qs, Project, ProjectsStrings) {
var list = ProjectList, let project = new Project();
defaultUrl = GetBasePath('projects');
var list = ProjectList;
init(); init();
@@ -176,9 +178,7 @@ export default ['$scope', '$rootScope', '$log', 'Rest', 'Alert',
var action = function() { var action = function() {
$('#prompt-modal').modal('hide'); $('#prompt-modal').modal('hide');
Wait('start'); Wait('start');
var url = defaultUrl + id + '/'; project.request('delete', id)
Rest.setUrl(url);
Rest.destroy()
.then(() => { .then(() => {
let reloadListStateParams = null; let reloadListStateParams = null;
@@ -196,19 +196,39 @@ export default ['$scope', '$rootScope', '$log', 'Rest', 'Alert',
}) })
.catch(({data, status}) => { .catch(({data, status}) => {
ProcessErrors($scope, data, status, null, { hdr: i18n._('Error!'), ProcessErrors($scope, data, status, null, { hdr: i18n._('Error!'),
msg: i18n.sprintf(i18n._('Call to %s failed. DELETE returned status: '), url) + status }); msg: i18n.sprintf(i18n._('Call to %s failed. DELETE returned status: '), `${project.path}${id}/`) + status });
}) })
.finally(function() { .finally(function() {
Wait('stop'); Wait('stop');
}); });
}; };
Prompt({ project.getDependentResourceCounts(id)
hdr: i18n._('Delete'), .then((counts) => {
body: '<div class="Prompt-bodyQuery">' + i18n._('Are you sure you want to delete the project below?') + '</div>' + '<div class="Prompt-bodyTarget">' + $filter('sanitize')(name) + '</div>', const invalidateRelatedLines = [];
action: action, let deleteModalBody = `<div class="Prompt-bodyQuery">${ProjectsStrings.get('deleteProject.CONFIRM')}</div>`;
actionText: 'DELETE'
}); counts.forEach(countObj => {
if(countObj.count && countObj.count > 0) {
invalidateRelatedLines.push(`<div><span class="Prompt-warningResourceTitle">${countObj.label}</span><span class="badge List-titleBadge">${countObj.count}</span></div>`);
}
});
if (invalidateRelatedLines && invalidateRelatedLines.length > 0) {
deleteModalBody = `<div class="Prompt-bodyQuery">${ProjectsStrings.get('deleteProject.CONFIRM')} ${ProjectsStrings.get('deleteProject.INVALIDATE')}</div>`;
invalidateRelatedLines.forEach(invalidateRelatedLine => {
deleteModalBody += invalidateRelatedLine;
});
}
Prompt({
hdr: i18n._('Delete'),
resourceName: $filter('sanitize')(name),
body: deleteModalBody,
action: action,
actionText: 'DELETE'
});
});
}; };
if ($scope.removeCancelUpdate) { if ($scope.removeCancelUpdate) {

View File

@@ -14,6 +14,7 @@ import GetProjectPath from './factories/get-project-path.factory';
import GetProjectIcon from './factories/get-project-icon.factory'; import GetProjectIcon from './factories/get-project-icon.factory';
import GetProjectToolTip from './factories/get-project-tool-tip.factory'; import GetProjectToolTip from './factories/get-project-tool-tip.factory';
import ProjectsTemplatesRoute from './projects-templates.route'; import ProjectsTemplatesRoute from './projects-templates.route';
import ProjectsStrings from './projects.strings';
export default export default
angular.module('Projects', []) angular.module('Projects', [])
@@ -25,6 +26,7 @@ angular.module('Projects', [])
.factory('GetProjectToolTip', GetProjectToolTip) .factory('GetProjectToolTip', GetProjectToolTip)
.factory('ProjectList', ProjectList) .factory('ProjectList', ProjectList)
.factory('ProjectsForm', ProjectsForm) .factory('ProjectsForm', ProjectsForm)
.service('ProjectsStrings', ProjectsStrings)
.config(['$stateProvider', 'stateDefinitionsProvider', '$stateExtenderProvider', .config(['$stateProvider', 'stateDefinitionsProvider', '$stateExtenderProvider',
function($stateProvider, stateDefinitionsProvider,$stateExtenderProvider) { function($stateProvider, stateDefinitionsProvider,$stateExtenderProvider) {
let stateDefinitions = stateDefinitionsProvider.$get(); let stateDefinitions = stateDefinitionsProvider.$get();

View File

@@ -0,0 +1,15 @@
function ProjectsStrings (BaseString) {
BaseString.call(this, 'projects');
let t = this.t;
let ns = this.projects;
ns.deleteProject = {
CONFIRM: t.s('Are you sure you want to delete this project?'),
INVALIDATE: t.s('Doing so will invalidate the following:')
};
}
ProjectsStrings.$inject = ['BaseStringService'];
export default ProjectsStrings;

View File

@@ -54,7 +54,8 @@ export default
Prompt({ Prompt({
hdr: hdr, hdr: hdr,
body: '<div class="Prompt-bodyQuery">Are you sure you want to delete the schedule below?</div><div class="Prompt-bodyTarget">' + $filter('sanitize')(schedule.name) + '</div>', resourceName: $filter('sanitize')(schedule.name),
body: '<div class="Prompt-bodyQuery">Are you sure you want to delete this schedule?</div>',
action: action, action: action,
actionText: 'DELETE', actionText: 'DELETE',
backdrop: false backdrop: false

View File

@@ -123,3 +123,7 @@
.Modal-footerButton + .Modal-footerButton { .Modal-footerButton + .Modal-footerButton {
margin-left: 20px; margin-left: 20px;
} }
.Modal-titleResourceName {
color: @default-err;
}

View File

@@ -39,9 +39,11 @@ angular.module('PromptDialog', ['Utilities'])
scope = dialog.scope(), cls, local_backdrop; scope = dialog.scope(), cls, local_backdrop;
scope.promptHeader = params.hdr; scope.promptHeader = params.hdr;
scope.promptResourceName = params.resourceName;
scope.promptBody = params.body; scope.promptBody = params.body;
scope.promptAction = params.action; scope.promptAction = params.action;
scope.promptActionText = (params.actionText === null || params.actionText === undefined || params.actionText === '') ? 'YES' : params.actionText; scope.promptActionText = (params.actionText === null || params.actionText === undefined || params.actionText === '') ? 'YES' : params.actionText;
scope.hideActionButton = params.hideActionButton ? true : false;
local_backdrop = (params.backdrop === undefined) ? "static" : params.backdrop; local_backdrop = (params.backdrop === undefined) ? "static" : params.backdrop;

View File

@@ -23,3 +23,7 @@
font-weight: bold; font-weight: bold;
text-transform: uppercase; text-transform: uppercase;
} }
.Prompt-warningResourceTitle {
margin-right: 10px;
}

View File

@@ -6,9 +6,9 @@
export default ['$scope', 'Rest', 'TeamList', 'Prompt', export default ['$scope', 'Rest', 'TeamList', 'Prompt',
'ProcessErrors', 'GetBasePath', 'Wait', '$state', '$filter', 'ProcessErrors', 'GetBasePath', 'Wait', '$state', '$filter',
'rbacUiControlService', 'Dataset', 'rbacUiControlService', 'Dataset', 'i18n',
function($scope, Rest, TeamList, Prompt, ProcessErrors, function($scope, Rest, TeamList, Prompt, ProcessErrors,
GetBasePath, Wait, $state, $filter, rbacUiControlService, Dataset) { GetBasePath, Wait, $state, $filter, rbacUiControlService, Dataset, i18n) {
var list = TeamList, var list = TeamList,
defaultUrl = GetBasePath('teams'); defaultUrl = GetBasePath('teams');
@@ -77,7 +77,8 @@ export default ['$scope', 'Rest', 'TeamList', 'Prompt',
Prompt({ Prompt({
hdr: 'Delete', hdr: 'Delete',
body: '<div class="Prompt-bodyQuery">Are you sure you want to delete the team below?</div><div class="Prompt-bodyTarget">' + $filter('sanitize')(name) + '</div>', resourceName: $filter('sanitize')(name),
body: '<div class="Prompt-bodyQuery">' + i18n._('Are you sure you want to delete this team?') + '</div>',
action: action, action: action,
actionText: 'DELETE' actionText: 'DELETE'
}); });

View File

@@ -8,14 +8,16 @@ export default ['$scope', '$rootScope',
'Alert','TemplateList', 'Prompt', 'ProcessErrors', 'Alert','TemplateList', 'Prompt', 'ProcessErrors',
'GetBasePath', 'InitiatePlaybookRun', 'Wait', '$state', '$filter', 'GetBasePath', 'InitiatePlaybookRun', 'Wait', '$state', '$filter',
'Dataset', 'rbacUiControlService', 'TemplatesService','QuerySet', 'Dataset', 'rbacUiControlService', 'TemplatesService','QuerySet',
'TemplateCopyService', 'i18n', 'TemplateCopyService', 'i18n', 'JobTemplateModel', 'TemplatesStrings',
function( function(
$scope, $rootScope, Alert, $scope, $rootScope, Alert,
TemplateList, Prompt, ProcessErrors, GetBasePath, TemplateList, Prompt, ProcessErrors, GetBasePath,
InitiatePlaybookRun, Wait, $state, $filter, Dataset, rbacUiControlService, TemplatesService, InitiatePlaybookRun, Wait, $state, $filter, Dataset, rbacUiControlService, TemplatesService,
qs, TemplateCopyService, i18n qs, TemplateCopyService, i18n, JobTemplate, TemplatesStrings
) { ) {
let jobTemplate = new JobTemplate();
var list = TemplateList; var list = TemplateList;
init(); init();
@@ -98,65 +100,98 @@ export default ['$scope', '$rootScope',
$scope.deleteJobTemplate = function(template) { $scope.deleteJobTemplate = function(template) {
if(template) { if(template) {
Prompt({ var action = function() {
hdr: i18n._('Delete'), function handleSuccessfulDelete(isWorkflow) {
body: `<div class="Prompt-bodyQuery">${i18n._("Are you sure you want to delete the template below?")}</div><div class="Prompt-bodyTarget">${$filter('sanitize')(template.name)}</div>`, let stateParamId = isWorkflow ? $state.params.workflow_job_template_id : $state.params.job_template_id;
action: function() {
function handleSuccessfulDelete(isWorkflow) { let reloadListStateParams = null;
let stateParamId = isWorkflow ? $state.params.workflow_job_template_id : $state.params.job_template_id;
let reloadListStateParams = null; if($scope.templates.length === 1 && $state.params.template_search && !_.isEmpty($state.params.template_search.page) && $state.params.template_search.page !== '1') {
reloadListStateParams = _.cloneDeep($state.params);
reloadListStateParams.template_search.page = (parseInt(reloadListStateParams.template_search.page)-1).toString();
}
if($scope.templates.length === 1 && $state.params.template_search && !_.isEmpty($state.params.template_search.page) && $state.params.template_search.page !== '1') { if (parseInt(stateParamId) === template.id) {
reloadListStateParams = _.cloneDeep($state.params); // Move the user back to the templates list
reloadListStateParams.template_search.page = (parseInt(reloadListStateParams.template_search.page)-1).toString(); $state.go("templates", reloadListStateParams, {reload: true});
} } else {
$state.go(".", reloadListStateParams, {reload: true});
}
Wait('stop');
}
if (parseInt(stateParamId) === template.id) { $('#prompt-modal').modal('hide');
// Move the user back to the templates list Wait('start');
$state.go("templates", reloadListStateParams, {reload: true}); if(template.type && (template.type === 'Workflow Job Template' || template.type === 'workflow_job_template')) {
} else { TemplatesService.deleteWorkflowJobTemplate(template.id)
$state.go(".", reloadListStateParams, {reload: true}); .then(function () {
} handleSuccessfulDelete(true);
Wait('stop'); })
} .catch(function (response) {
Wait('stop');
ProcessErrors($scope, response.data, response.status, null, { hdr: 'Error!',
msg: 'Call to delete workflow job template failed. DELETE returned status: ' + response.status + '.'});
});
}
else if(template.type && (template.type === 'Job Template' || template.type === 'job_template')) {
TemplatesService.deleteJobTemplate(template.id)
.then(function () {
handleSuccessfulDelete();
})
.catch(function (response) {
Wait('stop');
ProcessErrors($scope, response.data, response.status, null, { hdr: 'Error!',
msg: 'Call to delete job template failed. DELETE returned status: ' + response.status + '.'});
});
}
else {
Wait('stop');
Alert('Error: Unable to determine template type', 'We were unable to determine this template\'s type while deleting.');
}
};
$('#prompt-modal').modal('hide'); if(template.type && (template.type === 'Workflow Job Template' || template.type === 'workflow_job_template')) {
Wait('start'); Prompt({
if(template.type && (template.type === 'Workflow Job Template' || template.type === 'workflow_job_template')) { hdr: i18n._('Delete'),
TemplatesService.deleteWorkflowJobTemplate(template.id) resourceName: $filter('sanitize')(template.name),
.then(function () { body: TemplatesStrings.get('workflowJobTemplates.deleteWorkflowJobTemplate.CONFIRM'),
handleSuccessfulDelete(true); action: action,
}) actionText: 'DELETE'
.catch(function (response) { });
Wait('stop'); }
ProcessErrors($scope, response.data, response.status, null, { hdr: 'Error!', else if(template.type && (template.type === 'Job Template' || template.type === 'job_template')) {
msg: 'Call to delete workflow job template failed. DELETE returned status: ' + response.status + '.'});
}); jobTemplate.getDependentResourceCounts(template.id)
} .then((counts) => {
else if(template.type && (template.type === 'Job Template' || template.type === 'job_template')) { const invalidateRelatedLines = [];
TemplatesService.deleteJobTemplate(template.id) let deleteModalBody = `<div class="Prompt-bodyQuery">${TemplatesStrings.get('jobTemplates.deleteJobTemplate.CONFIRM')}</div>`;
.then(function () {
handleSuccessfulDelete(); counts.forEach(countObj => {
}) if(countObj.count && countObj.count > 0) {
.catch(function (response) { invalidateRelatedLines.push(`<div><span class="Prompt-warningResourceTitle">${countObj.label}</span><span class="badge List-titleBadge">${countObj.count}</span></div>`);
Wait('stop'); }
ProcessErrors($scope, response.data, response.status, null, { hdr: 'Error!', });
msg: 'Call to delete job template failed. DELETE returned status: ' + response.status + '.'});
}); if (invalidateRelatedLines && invalidateRelatedLines.length > 0) {
} deleteModalBody = `<div class="Prompt-bodyQuery">${TemplatesStrings.get('jobTemplates.deleteJobTemplate.CONFIRM')} ${TemplatesStrings.get('jobTemplates.deleteJobTemplate.INVALIDATE')}</div>`;
else { invalidateRelatedLines.forEach(invalidateRelatedLine => {
Wait('stop'); deleteModalBody += invalidateRelatedLine;
Alert('Error: Unable to determine template type', 'We were unable to determine this template\'s type while deleting.'); });
} }
},
actionText: i18n._('DELETE') Prompt({
}); hdr: i18n._('Delete'),
} resourceName: $filter('sanitize')(template.name),
else { body: deleteModalBody,
Alert('Error: Unable to delete template', 'Template parameter is missing'); action: action,
} actionText: 'DELETE'
});
});
}
}
else {
Alert('Error: Unable to delete template', 'Template parameter is missing');
}
}; };
$scope.submitJob = function(template) { $scope.submitJob = function(template) {

View File

@@ -21,6 +21,7 @@ import WorkflowForm from './workflows.form';
import CompletedJobsList from './completed-jobs.list'; import CompletedJobsList from './completed-jobs.list';
import InventorySourcesList from './inventory-sources.list'; import InventorySourcesList from './inventory-sources.list';
import TemplateList from './templates.list'; import TemplateList from './templates.list';
import TemplatesStrings from './templates.strings';
export default export default
angular.module('templates', [surveyMaker.name, templatesList.name, jobTemplates.name, labels.name, workflowAdd.name, workflowEdit.name, angular.module('templates', [surveyMaker.name, templatesList.name, jobTemplates.name, labels.name, workflowAdd.name, workflowEdit.name,
@@ -33,6 +34,7 @@ angular.module('templates', [surveyMaker.name, templatesList.name, jobTemplates.
.factory('CompletedJobsList', CompletedJobsList) .factory('CompletedJobsList', CompletedJobsList)
.factory('TemplateList', TemplateList) .factory('TemplateList', TemplateList)
.value('InventorySourcesList', InventorySourcesList) .value('InventorySourcesList', InventorySourcesList)
.service('TemplatesStrings', TemplatesStrings)
.config(['$stateProvider', 'stateDefinitionsProvider', '$stateExtenderProvider', .config(['$stateProvider', 'stateDefinitionsProvider', '$stateExtenderProvider',
function($stateProvider, stateDefinitionsProvider, $stateExtenderProvider) { function($stateProvider, stateDefinitionsProvider, $stateExtenderProvider) {
let stateTree, addJobTemplate, editJobTemplate, addWorkflow, editWorkflow, let stateTree, addJobTemplate, editJobTemplate, addWorkflow, editWorkflow,

View File

@@ -0,0 +1,23 @@
function TemplatesStrings (BaseString) {
BaseString.call(this, 'templates');
let t = this.t;
let ns = this.templates;
ns.jobTemplates = {
deleteJobTemplate: {
CONFIRM: t.s('Are you sure you want to delete this job template?'),
INVALIDATE: t.s('Doing so will invalidate the following:')
}
};
ns.workflowJobTemplates = {
deleteWorkflowJobTemplate: {
CONFIRM: t.s('Are you sure you want to delete this workflow job template?')
}
};
}
TemplatesStrings.$inject = ['BaseStringService'];
export default TemplatesStrings;

View File

@@ -1,8 +1,12 @@
<div id="workflow-modal-dialog" style="display: none;"> <div id="workflow-modal-dialog" style="display: none;">
<div class="WorkflowMaker-deleteOverlay" ng-show="deleteOverlayVisible"> <div class="WorkflowMaker-deleteOverlay" ng-show="deleteOverlayVisible">
<div class="modal-dialog">
<div class="Modal-content modal-content"> <div class="Modal-content modal-content">
<div class="Modal-header"> <div class="Modal-header">
<div class="Modal-title">REMOVE</div> <div class="Modal-title">
<span>DELETE</span>
<span class="Modal-titleResourceName" ng-bind="nodeToBeDeleted.unifiedJobTemplate.name"></span>
</div>
<div class="Modal-exitHolder"> <div class="Modal-exitHolder">
<button class="close Modal-exit" ng-click="cancelDeleteNode()"> <button class="close Modal-exit" ng-click="cancelDeleteNode()">
<i class="fa fa-times-circle"></i> <i class="fa fa-times-circle"></i>
@@ -10,14 +14,14 @@
</div> </div>
</div> </div>
<div class="Modal-body ng-binding"> <div class="Modal-body ng-binding">
<div class="Prompt-bodyQuery">Are you sure you want to remove the template below?</div> <div class="Prompt-bodyQuery">Are you sure you want to delete this workflow node?</div>
<div class="Prompt-bodyTarget">{{nodeToBeDeleted.unifiedJobTemplate.name}}</div>
</div> </div>
<div class="Modal-footer"> <div class="Modal-footer">
<button ng-click="cancelDeleteNode()" class="btn Modal-defaultButton Modal-footerButton">CANCEL</a> <button ng-click="cancelDeleteNode()" class="btn Modal-defaultButton Modal-footerButton">CANCEL</a>
<button ng-click="confirmDeleteNode()" class="btn Modal-footerButton ng-binding Modal-errorButton">DELETE</a> <button ng-click="confirmDeleteNode()" class="btn Modal-footerButton ng-binding Modal-errorButton">DELETE</a>
</div> </div>
</div> </div>
</div>
</div> </div>
<div class="WorkflowMaker-header"> <div class="WorkflowMaker-header">
<div class="WorkflowMaker-title"> <div class="WorkflowMaker-title">

View File

@@ -87,7 +87,8 @@ export default ['$scope', '$rootScope', 'Rest', 'UserList', 'Prompt',
Prompt({ Prompt({
hdr: i18n._('Delete'), hdr: i18n._('Delete'),
body: '<div class="Prompt-bodyQuery">' + i18n._('Are you sure you want to delete the user below?') + '</div><div class="Prompt-bodyTarget">' + $filter('sanitize')(name) + '</div>', resourceName: $filter('sanitize')(name),
body: '<div class="Prompt-bodyQuery">' + i18n._('Are you sure you want to delete this user?') + '</div>',
action: action, action: action,
actionText: i18n._('DELETE') actionText: i18n._('DELETE')
}); });

View File

@@ -35,11 +35,9 @@ export default ['$q', 'Prompt', '$filter', 'Wait', 'Rest', '$state', 'ProcessErr
deleteJob: function(workflow) { deleteJob: function(workflow) {
Prompt({ Prompt({
hdr: 'Delete Job', hdr: 'Delete Job',
resourceName: `#${workflow.id} ` + $filter('sanitize')(workflow.name),
body: `<div class='Prompt-bodyQuery'> body: `<div class='Prompt-bodyQuery'>
Are you sure you want to delete the workflow below? Are you sure you want to delete this workflow?
</div>
<div class='Prompt-bodyTarget'>
#${workflow.id} ${$filter('sanitize')(workflow.name)}
</div>`, </div>`,
action: function() { action: function() {
Wait('start'); Wait('start');
@@ -84,11 +82,9 @@ export default ['$q', 'Prompt', '$filter', 'Wait', 'Rest', '$state', 'ProcessErr
Prompt({ Prompt({
hdr: 'Cancel Workflow', hdr: 'Cancel Workflow',
resourceName: `#${workflow.id} ${$filter('sanitize')(workflow.name)}`,
body: `<div class='Prompt-bodyQuery'> body: `<div class='Prompt-bodyQuery'>
Are you sure you want to cancel the workflow below? Are you sure you want to cancel this workflow job?
</div>
<div class='Prompt-bodyTarget'>
#${workflow.id} ${$filter('sanitize')(workflow.name)}
</div>`, </div>`,
action: function() { action: function() {
Wait('start'); Wait('start');

View File

@@ -20,7 +20,7 @@ module.exports = {
client.inject( client.inject(
[store, 'OrganizationModel'], [store, 'OrganizationModel'],
(_store_, Model) => new Model().http.post(_store_.organization), (_store_, Model) => new Model().http.post({ data: _store_.organization }),
({ data }) => { store.organization = data; } ({ data }) => { store.organization = data; }
); );

View File

@@ -92,7 +92,7 @@ module.exports = {
client.inject( client.inject(
[store.credentialType, 'CredentialTypeModel'], [store.credentialType, 'CredentialTypeModel'],
(data, Model) => new Model().http.post(data), (data, Model) => new Model().http.post({ data }),
({ data }) => { store.credentialType.response = data; } ({ data }) => { store.credentialType.response = data; }
); );

View File

@@ -23,7 +23,7 @@ module.exports = {
client.inject( client.inject(
[store, 'OrganizationModel'], [store, 'OrganizationModel'],
(_store_, Model) => new Model().http.post(_store_.organization), (_store_, Model) => new Model().http.post({ data: _store_.organization }),
({ data }) => { store.organization = data; } ({ data }) => { store.organization = data; }
); );

View File

@@ -23,7 +23,7 @@ module.exports = {
client.inject( client.inject(
[store, 'OrganizationModel'], [store, 'OrganizationModel'],
(_store_, Model) => new Model().http.post(_store_.organization), (_store_, Model) => new Model().http.post({ data: _store_.organization }),
({ data }) => { store.organization = data; } ({ data }) => { store.organization = data; }
); );

View File

@@ -23,7 +23,7 @@ module.exports = {
client.inject( client.inject(
[store, 'OrganizationModel'], [store, 'OrganizationModel'],
(_store_, Model) => new Model().http.post(_store_.organization), (_store_, Model) => new Model().http.post({ data: _store_.organization }),
({ data }) => { store.organization = data; } ({ data }) => { store.organization = data; }
); );

View File

@@ -23,7 +23,7 @@ module.exports = {
client.inject( client.inject(
[store, 'OrganizationModel'], [store, 'OrganizationModel'],
(_store_, Model) => new Model().http.post(_store_.organization), (_store_, Model) => new Model().http.post({ data: _store_.organization }),
({ data }) => { store.organization = data; } ({ data }) => { store.organization = data; }
); );

View File

@@ -23,7 +23,7 @@ module.exports = {
client.inject( client.inject(
[store, 'OrganizationModel'], [store, 'OrganizationModel'],
(_store_, Model) => new Model().http.post(_store_.organization), (_store_, Model) => new Model().http.post({ data: _store_.organization }),
({ data }) => { store.organization = data; } ({ data }) => { store.organization = data; }
); );

View File

@@ -23,7 +23,7 @@ module.exports = {
client.inject( client.inject(
[store, 'OrganizationModel'], [store, 'OrganizationModel'],
(_store_, Model) => new Model().http.post(_store_.organization), (_store_, Model) => new Model().http.post({ data: _store_.organization }),
({ data }) => { store.organization = data; } ({ data }) => { store.organization = data; }
); );

View File

@@ -14,8 +14,10 @@ describe('Controller: TemplatesList', () => {
canAddDeferred, canAddDeferred,
q, q,
TemplatesService, TemplatesService,
JobTemplateModel,
deleteWorkflowJobTemplateDeferred, deleteWorkflowJobTemplateDeferred,
deleteJobTemplateDeferred, deleteJobTemplateDeferred,
jobTemplateGetDepDeferred,
Dataset; Dataset;
beforeEach(angular.mock.module('awApp')); beforeEach(angular.mock.module('awApp'));
@@ -78,11 +80,17 @@ describe('Controller: TemplatesList', () => {
canAddDeferred = q.defer(); canAddDeferred = q.defer();
deleteWorkflowJobTemplateDeferred = q.defer(); deleteWorkflowJobTemplateDeferred = q.defer();
deleteJobTemplateDeferred = q.defer(); deleteJobTemplateDeferred = q.defer();
jobTemplateGetDepDeferred = q.defer();
rbacUiControlService.canAdd = jasmine.createSpy('canAdd').and.returnValue(canAddDeferred.promise); rbacUiControlService.canAdd = jasmine.createSpy('canAdd').and.returnValue(canAddDeferred.promise);
TemplatesService.deleteWorkflowJobTemplate = jasmine.createSpy('deleteWorkflowJobTemplate').and.returnValue(deleteWorkflowJobTemplateDeferred.promise); TemplatesService.deleteWorkflowJobTemplate = jasmine.createSpy('deleteWorkflowJobTemplate').and.returnValue(deleteWorkflowJobTemplateDeferred.promise);
TemplatesService.deleteJobTemplate = jasmine.createSpy('deleteJobTemplate').and.returnValue(deleteJobTemplateDeferred.promise); TemplatesService.deleteJobTemplate = jasmine.createSpy('deleteJobTemplate').and.returnValue(deleteJobTemplateDeferred.promise);
JobTemplateModel = function () {
this.getDependentResourceCounts = function() {
return jobTemplateGetDepDeferred.promise;
};
};
TemplatesListController = $controller('TemplatesListController', { TemplatesListController = $controller('TemplatesListController', {
$scope: scope, $scope: scope,
@@ -94,8 +102,11 @@ describe('Controller: TemplatesList', () => {
InitiatePlaybookRun: InitiatePlaybookRun, InitiatePlaybookRun: InitiatePlaybookRun,
rbacUiControlService: rbacUiControlService, rbacUiControlService: rbacUiControlService,
TemplatesService: TemplatesService, TemplatesService: TemplatesService,
JobTemplateModel: JobTemplateModel,
Dataset: Dataset Dataset: Dataset
}); });
rootScope.$apply();
})); }));
describe('scope.editJobTemplate()', () => { describe('scope.editJobTemplate()', () => {
@@ -151,10 +162,13 @@ describe('Controller: TemplatesList', () => {
var testTemplate = { var testTemplate = {
id: 1, id: 1,
name: "Test Template" name: "Test Template",
type: "Job Template"
}; };
scope.deleteJobTemplate(testTemplate); scope.deleteJobTemplate(testTemplate);
jobTemplateGetDepDeferred.resolve([]);
rootScope.$apply();
expect(Prompt).toHaveBeenCalled(); expect(Prompt).toHaveBeenCalled();
}); });
@@ -169,6 +183,8 @@ describe('Controller: TemplatesList', () => {
}; };
scope.deleteJobTemplate(testTemplate); scope.deleteJobTemplate(testTemplate);
jobTemplateGetDepDeferred.resolve([]);
rootScope.$apply();
expect(TemplatesService.deleteWorkflowJobTemplate).toHaveBeenCalled(); expect(TemplatesService.deleteWorkflowJobTemplate).toHaveBeenCalled();
}); });
@@ -183,6 +199,8 @@ describe('Controller: TemplatesList', () => {
}; };
scope.deleteJobTemplate(testTemplate); scope.deleteJobTemplate(testTemplate);
jobTemplateGetDepDeferred.resolve([]);
rootScope.$apply();
expect(TemplatesService.deleteJobTemplate).toHaveBeenCalled(); expect(TemplatesService.deleteJobTemplate).toHaveBeenCalled();
}); });

View File

@@ -130,8 +130,8 @@ describe('Components | Layout', () => {
expect(_ComponentsStrings_.get).toHaveBeenCalled(); expect(_ComponentsStrings_.get).toHaveBeenCalled();
})); }));
it('ComponentsStrings get() method should throw an error if string is not a property name of the layout class', () => { it('ComponentsStrings get() method should return undefined if string is not a property name of the layout class', () => {
expect(controller.getString.bind(null, 'SUBMISSION_ERROR_TITLE')).toThrow(); expect(controller.getString('SUBMISSION_ERROR_TITLE')).toBe(undefined);
}); });
it('should return layout string', () => { it('should return layout string', () => {
@@ -145,16 +145,6 @@ describe('Components | Layout', () => {
expect(controller.getString(key)).toBe(value); expect(controller.getString(key)).toBe(value);
}); });
}); });
it('should return default string', () => {
const defaultStrings = {
BRAND_NAME: 'AWX'
};
_.forEach(defaultStrings, (value, key) => {
expect(controller.getString(key)).toBe(value);
});
});
}); });
}); });
}); });