Restrict existing Action/Workflow to the existing ones

Pull the list of existing Workflows or Actions using the @ref facility
of Barricade.

Closes-bug: #1446228
Change-Id: I0d2dbbe2735104e86cc22507c5f66793294c5b0b
This commit is contained in:
Timur Sufiev 2015-06-16 19:01:07 +03:00
parent 854304924f
commit bcc69f218d
3 changed files with 235 additions and 106 deletions

View File

@ -148,7 +148,7 @@
'@meta': {
'index': 1,
'row': 0,
autocompletionUrl: '/project/mistral/actions/types'
'autocompletionUrl': '/project/mistral/actions/types'
}
})
},
@ -380,20 +380,94 @@
models.ActionTaskMixin = Barricade.Blueprint.create(function() {
return this.extend({}, {
'action': {
'@class': fields.string.extend({}, {
'@class': fields.string.extend({
create: function(json, parameters) {
var self = fields.string.create.call(this, json, parameters),
actionsCls = Barricade.create({
'@type': String,
'@ref': {
to: function() {
return models.Actions;
},
needs: function() {
return models.Workbook;
},
getter: function(data) {
return data.needed.get('actions');
}
}
});
self._actions = actionsCls.create().on(
'replace', function(newValue) {
self._actions = newValue;
self._actions.on('change', function() {
self._choices = self._actions.getIDs();
self.resetValues();
});
self._actions.emit('change');
});
return self;
},
_choices: null
}, {
'@enum': function() {
if (!this._choices) {
this._choices = [];
this.emit('_resolveUp', this._actions);
}
return this._choices;
},
'@meta': {
'row': 0,
'index': 1
}
})
}
});
})
});
models.WorkflowTaskMixin = Barricade.Blueprint.create(function() {
return this.extend({}, {
'workflow': {
'@class': fields.string.extend({}, {
'@class': fields.string.extend({
create: function(json, parameters) {
var self = fields.string.create.call(this, json, parameters),
workflowsCls = Barricade.create({
'@type': String,
'@ref': {
to: function() {
return models.Workflows;
},
needs: function() {
return models.Workbook;
},
getter: function(data) {
return data.needed.get('workflows');
}
}
});
self._workflows = workflowsCls.create().on(
'replace', function(newValue) {
self._workflows = newValue;
self._workflows.on('change', function() {
self._choices = self._workflows.getIDs();
self.resetValues();
});
self._workflows.emit('change');
});
return self;
},
_choices: null
}, {
'@enum': function() {
if ( !this._choices ) {
this._choices = [];
this.emit('_resolveUp', this._workflows);
}
return this._choices;
},
'@meta': {
'row': 0,
'index': 1
@ -542,6 +616,44 @@
return workflowTypes[type].create(json, parameters);
}
models.Actions = fields.dictionary.extend({}, {
'@required': false,
'@meta': {
'index': 3,
'panelIndex': 1
},
'?': {
'@class': models.Action
}
});
models.Workflows = fields.dictionary.extend({
create: function(json, parameters) {
var self = fields.dictionary.create.call(this, json, parameters);
self.on('childChange', function(child, op) {
if ( op === 'workflowType' ) {
var workflowId = child.getID(),
workflowPos = self.getPosByID(workflowId),
params = child._parameters,
workflowData = child.toJSON();
params.wfType = child.type;
params.id = workflowId;
self.set(workflowPos, workflowFactory(workflowData, params));
}
});
return self;
}
}, {
'@meta': {
'index': 4,
'panelIndex': 2
},
'?': {
'@class': models.Workflow,
'@factory': workflowFactory
}
});
models.Workbook = fields.frozendict.extend({
toYAML: function() {
return jsyaml.dump(this.toJSON({pretty: true}));
@ -583,44 +695,10 @@
})
},
'actions': {
'@class': fields.dictionary.extend({}, {
'@required': false,
'@meta': {
'index': 3,
'panelIndex': 1
},
'?': {
'@class': models.Action
}
})
'@class': models.Actions
},
'workflows': {
'@class': fields.dictionary.extend({
create: function(json, parameters) {
var self = fields.dictionary.create.call(this, json, parameters);
self.on('childChange', function(child, op) {
if ( op === 'workflowType' ) {
var workflowId = child.getID(),
workflowPos = self.getPosByID(workflowId),
params = child._parameters,
workflowData = child.toJSON();
params.wfType = child.type;
params.id = workflowId;
self.set(workflowPos, workflowFactory(workflowData, params));
}
});
return self;
}
}, {
'@meta': {
'index': 4,
'panelIndex': 2
},
'?': {
'@class': models.Workflow,
'@factory': workflowFactory
}
})
'@class': models.Workflows
}
});

View File

@ -261,43 +261,78 @@ var Barricade = (function () {
* @mixin
* @memberof Barricade
*/
Deferrable = Blueprint.create(function (schema) {
var self = this,
deferred;
Deferrable = Blueprint.create(function () {
var existingCreate = this.create;
function resolver(neededValue) {
var ref = schema['@ref'].resolver(self, neededValue);
if (ref === undefined) {
logError('Could not resolve ', JSON.stringify(self.toJSON()));
}
return ref;
}
this.create = function() {
var self = existingCreate.apply(this, arguments),
schema = self._schema,
needed,
deferred = schema.hasOwnProperty('@ref')
? Deferred.create(schema['@ref'].needs, getter, resolver)
: null;
if (schema.hasOwnProperty('@ref')) {
deferred = Deferred.create(schema['@ref'].needs, resolver);
}
this.resolveWith = function (obj) {
var allResolved = true;
if (deferred && !deferred.isResolved()) {
if (deferred.needs(obj)) {
this.emit('replace', deferred.resolve(obj));
} else {
allResolved = false;
}
if (schema.hasOwnProperty('@ref') && !schema['@ref'].processor) {
schema['@ref'].processor = function (o) { return o.val; };
}
if (this.instanceof(Container)) {
this.each(function (index, value) {
if (!value.resolveWith(obj)) {
function getter(neededVal) {
return schema['@ref'].getter(
{standIn: self, needed: neededVal});
}
function resolver(retrievedValue) {
self.emit('replace', schema['@ref'].processor({
val: retrievedValue,
standIn: self,
needed: needed
}));
}
self.resolveWith = function (obj) {
var allResolved = true;
if (deferred && !deferred.isResolved()) {
if (deferred.needs(obj)) {
needed = obj;
deferred.resolve(obj);
} else {
allResolved = false;
}
});
}
}
return allResolved;
if (this.instanceof(Container)) {
this.each(function (index, value) {
if (!value.resolveWith(obj)) {
allResolved = false;
}
});
}
return allResolved;
};
self.isPlaceholder = function () {
return !!deferred;
};
return self;
};
this.isValidRef = function(instance) {
var clsRef = this._schema['@ref'];
if (!clsRef) {
return false;
}
if (typeof clsRef.to === 'function') {
return this._safeInstanceof(instance, clsRef.to());
} else if (typeof clsRef.to === 'object') {
return this._safeInstanceof(instance, clsRef.to);
}
throw new Error('Ref.to was ' + clsRef.to);
};
return this;
});
/**
@ -407,7 +442,7 @@ var Barricade = (function () {
this.emit = function (eventName) {
var args = arguments; // Must come from correct scope
if (events.hasOwnProperty(eventName)) {
events[eventName].forEach(function (callback) {
events[eventName].slice().forEach(function (callback) {
// Call with emitter as context and pass all but eventName
callback.apply(this, Array.prototype.slice.call(args, 1));
}, this);
@ -469,10 +504,11 @@ var Barricade = (function () {
Callback to execute when resolve happens.
* @returns {Barricade.Deferred}
*/
create: function (classGetter, onResolve) {
create: function (classGetter, getter, onResolve) {
var self = Object.create(this);
self._isResolved = false;
self._classGetter = classGetter;
self._getter = getter;
self._onResolve = onResolve;
return self;
},
@ -502,17 +538,25 @@ var Barricade = (function () {
* @param obj
*/
resolve: function (obj) {
var ref;
var self = this,
neededValue;
function doResolve(realNeededValue) {
neededValue.off('replace', doResolve);
self._onResolve(realNeededValue);
self._isResolved = true;
}
if (this._isResolved) {
throw new Error('Deferred already resolved');
}
ref = this._onResolve(obj);
neededValue = this._getter(obj);
if (ref !== undefined) {
this._isResolved = true;
return ref;
if (neededValue.isPlaceholder()) {
neededValue.on('replace', doResolve);
} else {
doResolve(neededValue);
}
}
};
@ -537,7 +581,7 @@ var Barricade = (function () {
* @mixes Barricade.Identifiable
* @extends Barricade.Identifiable
*/
Base = Extendable.call(InstanceofMixin.call({
Base = Deferrable.call(Extendable.call(InstanceofMixin.call({
/**
* Creates a `Base` instance
* @memberof Barricade.Base
@ -564,7 +608,6 @@ var Barricade = (function () {
Observable.call(self);
Omittable.call(self, isUsed);
Deferrable.call(self, schema);
Validatable.call(self, schema);
if (schema.hasOwnProperty('@enum')) {
@ -625,7 +668,7 @@ var Barricade = (function () {
* @private
*/
_safeInstanceof: function (instance, class_) {
return typeof instance === 'object' &&
return getType(instance) === Object &&
('instanceof' in instance) &&
instance.instanceof(class_);
},
@ -695,7 +738,7 @@ var Barricade = (function () {
? this._getPrettyJSON(options)
: this._getJSON(options);
}
}));
})));
/**
* @class
@ -714,9 +757,15 @@ var Barricade = (function () {
var self = Base.create.call(this, json, parameters);
return self.on('_addedElement', function (key) {
// every time a new element is added we need to set the
// listeners for it and try to resolve any references,
// passing the resolution upward if needed
self._attachListeners(key);
self._tryResolveOn(self.get(key));
}).each(function (index, value) {
// also we bind the handlers and do reference resolution
// for all the children that are already here (no upward
// resolution here)
self._attachListeners(index);
value.resolveWith(self);
});
@ -776,21 +825,8 @@ var Barricade = (function () {
* @private
*/
_isCorrectType: function (instance, class_) {
var self = this;
function isRefTo() {
if (typeof class_._schema['@ref'].to === 'function') {
return self._safeInstanceof(instance,
class_._schema['@ref'].to());
} else if (typeof class_._schema['@ref'].to === 'object') {
return self._safeInstanceof(instance,
class_._schema['@ref'].to);
}
throw new Error('Ref.to was ' + class_._schema['@ref'].to);
}
return this._safeInstanceof(instance, class_) ||
(class_._schema.hasOwnProperty('@ref') && isRefTo());
class_.isValidRef(instance);
},
/**

View File

@ -11,22 +11,37 @@
});
var restrictedChoicesMixin = Barricade.Blueprint.create(function() {
var values = this.getEnumValues(),
labels = this.getEnumLabels(),
var self = this,
values, labels, items;
function fillItems() {
values = self.getEnumValues();
labels = self.getEnumLabels();
items = {};
values.forEach(function(value, index) {
items[value] = labels[index];
});
values && values.forEach(function (value, index) {
items[value] = labels[index];
});
}
this.getLabel = function(value) {
if ( values === undefined ) {
fillItems();
}
return items[value];
};
this.getValues = function() {
if ( values === undefined ) {
fillItems();
}
return values;
};
this.resetValues = function() {
values = undefined;
};
this.setType('choices');
return this;
});
@ -100,16 +115,15 @@
}, {'@type': String});
var autoCompletionMixin = Barricade.Blueprint.create(function(url) {
var suggestions = [];
var self = this;
this.getSuggestions = function() { return []; };
$http.get(url).success(function(data) {
suggestions = data;
self.getSuggestions = function() {
return data;
};
});
this.getSuggestions = function() {
return suggestions;
};
return this;
});
@ -251,8 +265,9 @@
dictionary: dictionaryModel,
frozendict: frozendictModel,
directeddictionary: directedDictionaryModel,
autocompletionmixin: autoCompletionMixin,
wildcard: wildcardMixin // use for most general type-checks
};
}])
})();
})();