Change code to satisfy new ESLint checks
Change-Id: I36926039fff61328626682f37eb229f58e27c928
This commit is contained in:
parent
6062444015
commit
ac6336b5e2
|
@ -3,24 +3,56 @@
|
|||
*/
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
angular.module('merlin')
|
||||
angular
|
||||
.module('merlin')
|
||||
/*
|
||||
* Allows to edit field name in-place.
|
||||
* For example, you have a field named 'Input 1' and you want to replace this name with "Base input" value.
|
||||
* For example, you have a field named 'Input 1' and you want to replace this name with
|
||||
* "Base input" value.
|
||||
* If you add editable directive to such field, you will get a marker icon near this field,
|
||||
* and with clicking on this icon you can type new name and save or discard changes.
|
||||
* */
|
||||
.directive('editable', function() {
|
||||
.directive('editable', editable)
|
||||
|
||||
/*
|
||||
* this directive auto-sets the focus to an input field once it is shown.
|
||||
* */
|
||||
.directive('showFocus', showFocus)
|
||||
|
||||
/*
|
||||
* tells Merlin to render this element as a panel.
|
||||
* */
|
||||
.directive('panel', panel)
|
||||
|
||||
/*
|
||||
* tells Merlin to render this element as a group with ability to collapse.
|
||||
* */
|
||||
.directive('collapsibleGroup', collapsibleGroup)
|
||||
|
||||
/*
|
||||
* sets up the DOM nodes related to validation of model being edited in this widget
|
||||
* (and specifies the name of this model on scope).
|
||||
* */
|
||||
.directive('validatableWith', validatableWith)
|
||||
|
||||
/*
|
||||
* retrieves a template by its name which is the same as model's type and renders it,
|
||||
* recursive <typed-field></..>-s are possible.
|
||||
* */
|
||||
.directive('typedField', typedField);
|
||||
|
||||
typedField.$inject = ['$compile', 'merlin.templates'];
|
||||
|
||||
function editable() {
|
||||
return {
|
||||
restrict: 'E',
|
||||
templateUrl: '/static/merlin/templates/editable.html',
|
||||
require: 'ngModel',
|
||||
scope: true,
|
||||
link: function(scope, element, attrs, ngModelCtrl) {
|
||||
var hiddenSpan = element.find('span.width-detector'),
|
||||
input = element.find('input'),
|
||||
maxWidth = 400;
|
||||
var hiddenSpan = element.find('span.width-detector');
|
||||
var input = element.find('input');
|
||||
var maxWidth = 400;
|
||||
|
||||
function adjustWidth() {
|
||||
var width;
|
||||
|
@ -40,7 +72,10 @@
|
|||
}
|
||||
|
||||
scope.isEdited = false;
|
||||
scope.$watch('editableValue', function() {
|
||||
|
||||
// Unused variable created here due to rule 'ng_on_watch': 2
|
||||
// (see https://github.com/Gillespie59/eslint-plugin-angular)
|
||||
var editableValueWatcher = scope.$watch('editableValue', function() {
|
||||
adjustWidth();
|
||||
});
|
||||
input.on('keyup', function(e) {
|
||||
|
@ -63,23 +98,23 @@
|
|||
scope.reject = reject;
|
||||
}
|
||||
};
|
||||
})
|
||||
/*
|
||||
* this directive auto-sets the focus to an input field once it is shown.
|
||||
* */
|
||||
.directive('showFocus', function($timeout) {
|
||||
return function(scope, element, attrs) {
|
||||
scope.$watch(attrs.showFocus, function(newValue) {
|
||||
$timeout(function() {
|
||||
newValue && element.focus();
|
||||
});
|
||||
});
|
||||
}
|
||||
})
|
||||
/*
|
||||
* tells Merlin to render this element as a panel.
|
||||
* */
|
||||
.directive('panel', function($parse) {
|
||||
|
||||
function showFocus($timeout) {
|
||||
return function(scope, element, attrs) {
|
||||
// Unused variable created here due to rule 'ng_on_watch': 2
|
||||
// (see https://github.com/Gillespie59/eslint-plugin-angular)
|
||||
var showFocusWatcher = scope.$watch(attrs.showFocus, function(newValue) {
|
||||
$timeout(function() {
|
||||
if (newValue) {
|
||||
element.focus();
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function panel($parse) {
|
||||
return {
|
||||
restrict: 'E',
|
||||
templateUrl: '/static/merlin/templates/collapsible-panel.html',
|
||||
|
@ -91,12 +126,10 @@
|
|||
scope.removable = $parse(attrs.removable)();
|
||||
scope.isCollapsed = false;
|
||||
}
|
||||
};
|
||||
}
|
||||
})
|
||||
/*
|
||||
* tells Merlin to render this element as a group with ability to collapse.
|
||||
* */
|
||||
.directive('collapsibleGroup', function() {
|
||||
|
||||
function collapsibleGroup() {
|
||||
return {
|
||||
restrict: 'E',
|
||||
templateUrl: '/static/merlin/templates/collapsible-group.html',
|
||||
|
@ -115,12 +148,10 @@
|
|||
scope.removable = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
})
|
||||
/*
|
||||
* sets up the DOM nodes related to validation of model being edited in this widget (and specifies the name of this model on scope).
|
||||
* */
|
||||
.directive('validatableWith', function($parse) {
|
||||
|
||||
function validatableWith($parse) {
|
||||
return {
|
||||
restrict: 'A',
|
||||
require: 'ngModel',
|
||||
|
@ -129,32 +160,33 @@
|
|||
if ( attrs.validatableWith ) {
|
||||
model = $parse(attrs.validatableWith)(scope);
|
||||
scope.error = '';
|
||||
model.setValidatable && model.setValidatable(true);
|
||||
model.on && model.on('validation', function(result) {
|
||||
var isValid = (result == 'succeeded'),
|
||||
baseMessage = '';
|
||||
if (model.setValidatable) {
|
||||
model.setValidatable(true);
|
||||
}
|
||||
if (model.on) {
|
||||
model.on('validation', function(result) {
|
||||
var isValid = (result == 'succeeded');
|
||||
var baseMessage = '';
|
||||
// (FIXME): hack until Barricade supports validation of empty required entries
|
||||
if ( !model.get() && model.isRequired() ) {
|
||||
isValid = false;
|
||||
baseMessage = 'This field is required.'
|
||||
baseMessage = 'This field is required.';
|
||||
}
|
||||
ctrl.$setValidity('barricade', isValid);
|
||||
scope.error = model.hasError() ? model.getError() : baseMessage;
|
||||
});
|
||||
}
|
||||
ctrl.$formatters.push(function(modelValue) {
|
||||
return modelValue === undefined ?
|
||||
return angular.isUndefined(modelValue) ?
|
||||
( ctrl.$isEmpty(ctrl.$viewValue) ? undefined : ctrl.$viewValue ) :
|
||||
modelValue;
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
})
|
||||
/*
|
||||
* retrieves a template by its name which is the same as model's type and renders it, recursive <typed-field></..>-s are possible.
|
||||
* */
|
||||
.directive('typedField', ['$compile', 'merlin.templates',
|
||||
function($compile, templates) {
|
||||
|
||||
function typedField($compile, templates) {
|
||||
return {
|
||||
restrict: 'E',
|
||||
scope: {
|
||||
|
@ -164,9 +196,8 @@
|
|||
link: function(scope, element) {
|
||||
templates.templateReady(scope.type).then(function(template) {
|
||||
element.replaceWith($compile(template)(scope));
|
||||
})
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
}])
|
||||
|
||||
})();
|
||||
|
|
|
@ -2,38 +2,43 @@
|
|||
(function() {
|
||||
'use strict';
|
||||
|
||||
angular.module('merlin')
|
||||
.factory('merlin.field.models',
|
||||
['merlin.utils', 'merlin.panel.models', '$http', function(utils, panels, $http) {
|
||||
angular
|
||||
.module('merlin')
|
||||
.factory('merlin.field.models', merlinFieldModels);
|
||||
|
||||
merlinFieldModels.$inject = ['merlin.utils', 'merlin.panel.models', '$http'];
|
||||
|
||||
function merlinFieldModels(utils, panels, $http) {
|
||||
var wildcardMixin = Barricade.Blueprint.create(function() {
|
||||
return this;
|
||||
});
|
||||
|
||||
var viewChoicesMixin = Barricade.Blueprint.create(function() {
|
||||
var self = this,
|
||||
dropDownLimit = this._dropDownLimit || 5,
|
||||
values, labels, items, isDropDown;
|
||||
var self = this;
|
||||
var dropDownLimit = this._dropDownLimit || 5;
|
||||
var values, labels, items, isDropDown;
|
||||
|
||||
function fillItems() {
|
||||
values = self.getEnumValues();
|
||||
labels = self.getEnumLabels();
|
||||
items = {};
|
||||
|
||||
values && values.forEach(function (value, index) {
|
||||
if (values) {
|
||||
values.forEach(function (value, index) {
|
||||
items[value] = labels[index];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
this.getLabel = function(value) {
|
||||
if ( values === undefined ) {
|
||||
if ( angular.isUndefined(values) ) {
|
||||
fillItems();
|
||||
}
|
||||
return items[value];
|
||||
};
|
||||
|
||||
this.getValues = function() {
|
||||
if ( values === undefined ) {
|
||||
if ( angular.isUndefined(values) ) {
|
||||
fillItems();
|
||||
}
|
||||
return values;
|
||||
|
@ -57,8 +62,8 @@
|
|||
});
|
||||
|
||||
var modelMixin = Barricade.Blueprint.create(function(type) {
|
||||
var isValid = true,
|
||||
isValidatable = false;
|
||||
var isValid = true;
|
||||
var isValidatable = false;
|
||||
this.value = function() {
|
||||
if ( !arguments.length ) {
|
||||
if ( isValidatable ) {
|
||||
|
@ -168,7 +173,7 @@
|
|||
self._getContents = function() {
|
||||
return self.getKeys().map(function(key) {
|
||||
return self.get(key);
|
||||
})
|
||||
});
|
||||
};
|
||||
meldGroup.call(self);
|
||||
return self;
|
||||
|
@ -177,11 +182,11 @@
|
|||
|
||||
var dictionaryModel = Barricade.MutableObject.extend({
|
||||
create: function(json, parameters) {
|
||||
var self = Barricade.MutableObject.create.call(this, json, parameters),
|
||||
_items = [],
|
||||
_elClass = self._elementClass,
|
||||
baseKey = utils.getMeta(_elClass, 'baseKey') || 'key',
|
||||
baseName = utils.getMeta(_elClass, 'baseName') || utils.makeTitle(baseKey);
|
||||
var self = Barricade.MutableObject.create.call(this, json, parameters);
|
||||
var _items = [];
|
||||
var _elClass = self._elementClass;
|
||||
var baseKey = utils.getMeta(_elClass, 'baseKey') || 'key';
|
||||
var baseName = utils.getMeta(_elClass, 'baseName') || utils.makeTitle(baseKey);
|
||||
|
||||
modelMixin.call(self, 'dictionary');
|
||||
|
||||
|
@ -198,8 +203,8 @@
|
|||
}
|
||||
|
||||
self.add = function(newID) {
|
||||
var regexp = new RegExp('(' + baseKey + ')([0-9]+)'),
|
||||
newValue;
|
||||
var regexp = new RegExp('(' + baseKey + ')([0-9]+)');
|
||||
var newValue;
|
||||
newID = newID || baseKey + utils.getNextIDSuffix(self, regexp);
|
||||
if ( _elClass.instanceof(Barricade.ImmutableObject) ) {
|
||||
if ( 'name' in _elClass._schema ) {
|
||||
|
@ -251,8 +256,8 @@
|
|||
|
||||
var linkedCollectionModel = stringModel.extend({
|
||||
create: function(json, parameters) {
|
||||
var self = stringModel.create.call(this, json, parameters),
|
||||
collectionCls = Barricade.create({
|
||||
var self = stringModel.create.call(this, json, parameters);
|
||||
var collectionCls = Barricade.create({
|
||||
'@type': String,
|
||||
'@ref': {
|
||||
to: function() {
|
||||
|
@ -300,6 +305,5 @@
|
|||
frozendict: frozendictModel,
|
||||
wildcard: wildcardMixin // use for most general type-checks
|
||||
};
|
||||
}])
|
||||
|
||||
}
|
||||
})();
|
||||
|
|
|
@ -14,9 +14,17 @@
|
|||
under the License.
|
||||
*/
|
||||
(function() {
|
||||
angular.module('merlin')
|
||||
angular
|
||||
.module('merlin')
|
||||
.filter('extractPanels', extractPanels)
|
||||
.filter('extractRows', extractRows)
|
||||
.filter('extractItems', extractItems);
|
||||
|
||||
.filter('extractPanels', ['merlin.utils', function(utils) {
|
||||
extractPanels.$inject = ['merlin.utils'];
|
||||
extractRows.$inject = ['merlin.utils'];
|
||||
extractItems.$inject = ['merlin.utils'];
|
||||
|
||||
function extractPanels(utils) {
|
||||
var panelProto = {
|
||||
create: function(itemsOrContainer, id) {
|
||||
if ( angular.isArray(itemsOrContainer) && !itemsOrContainer.length ) {
|
||||
|
@ -52,8 +60,8 @@
|
|||
}
|
||||
},
|
||||
remove: function() {
|
||||
var container = this._barricadeContainer,
|
||||
pos = container.getPosByID(this._barricadeId);
|
||||
var container = this._barricadeContainer;
|
||||
var pos = container.getPosByID(this._barricadeId);
|
||||
container.remove(pos);
|
||||
}
|
||||
};
|
||||
|
@ -73,8 +81,8 @@
|
|||
}
|
||||
|
||||
return _.memoize(function(container) {
|
||||
var items = container._getContents(),
|
||||
panels = [];
|
||||
var items = container._getContents();
|
||||
var panels = [];
|
||||
utils.groupByMetaKey(items, 'panelIndex').forEach(function(items) {
|
||||
var panelsRoot = extractPanelsRoot(items);
|
||||
if ( panelsRoot ) {
|
||||
|
@ -85,7 +93,7 @@
|
|||
panels.push(Object.create(panelProto).create(items));
|
||||
}
|
||||
});
|
||||
return panels.condense();
|
||||
return utils.condense(panels);
|
||||
}, function(container) {
|
||||
var hash = '';
|
||||
container.getKeys().map(function(key) {
|
||||
|
@ -100,9 +108,9 @@
|
|||
});
|
||||
return hash;
|
||||
});
|
||||
}])
|
||||
}
|
||||
|
||||
.filter('extractRows', ['merlin.utils', function(utils) {
|
||||
function extractRows(utils) {
|
||||
function getItems(panelOrContainer) {
|
||||
if ( panelOrContainer.items ) {
|
||||
return panelOrContainer.items;
|
||||
|
@ -136,10 +144,10 @@
|
|||
hash += item.uid();
|
||||
});
|
||||
return hash;
|
||||
})
|
||||
}])
|
||||
});
|
||||
}
|
||||
|
||||
.filter('extractItems', ['merlin.utils', function(utils) {
|
||||
function extractItems(utils) {
|
||||
return _.memoize(function(row) {
|
||||
return row.items.sort(function(item1, item2) {
|
||||
return utils.getMeta(item1, 'index') - utils.getMeta(item2, 'index');
|
||||
|
@ -150,7 +158,6 @@
|
|||
hash += item.uid();
|
||||
});
|
||||
return hash;
|
||||
})
|
||||
}])
|
||||
|
||||
});
|
||||
}
|
||||
})();
|
||||
|
|
|
@ -4,20 +4,33 @@
|
|||
(function() {
|
||||
'use strict';
|
||||
|
||||
angular.module('merlin', ['ui.bootstrap'])
|
||||
.config(function($interpolateProvider) {
|
||||
angular
|
||||
.module('merlin', ['ui.bootstrap'])
|
||||
.config(interpolateProvider)
|
||||
// move these 2 values out of run section to change them in unit-tests
|
||||
.value('fieldTemplatesUrl', '/static/merlin/templates/fields/')
|
||||
// The false posititive on array constant here we're working around is caused
|
||||
// by https://github.com/Gillespie59/eslint-plugin-angular/issues/99
|
||||
.value('fieldTemplates', fieldTemplates())
|
||||
.run(runTemplates);
|
||||
|
||||
runTemplates.$inject = ['merlin.templates', 'fieldTemplatesUrl', 'fieldTemplates'];
|
||||
|
||||
function fieldTemplates() {
|
||||
return [
|
||||
'dictionary', 'frozendict', 'list',
|
||||
'string', 'text', 'group', 'number', 'choices'
|
||||
];
|
||||
}
|
||||
|
||||
function runTemplates(templates, rootUrl, fieldList) {
|
||||
templates.prefetch(rootUrl, fieldList);
|
||||
}
|
||||
|
||||
function interpolateProvider($interpolateProvider) {
|
||||
// Replacing the default angular symbol
|
||||
// allow us to mix angular with django templates
|
||||
$interpolateProvider.startSymbol('{$');
|
||||
$interpolateProvider.endSymbol('$}');
|
||||
})
|
||||
// move these 2 values out of run section to change them in unit-tests
|
||||
.value('fieldTemplatesUrl', '/static/merlin/templates/fields/')
|
||||
.value('fieldTemplates', ['dictionary', 'frozendict', 'list',
|
||||
'string', 'text', 'group', 'number', 'choices'])
|
||||
.run(['merlin.templates', 'fieldTemplatesUrl', 'fieldTemplates',
|
||||
function(templates, rootUrl, fieldList) {
|
||||
templates.prefetch(rootUrl, fieldList);
|
||||
}])
|
||||
|
||||
}
|
||||
})();
|
|
@ -4,22 +4,26 @@
|
|||
(function() {
|
||||
'use strict';
|
||||
|
||||
angular.module('merlin')
|
||||
.factory('merlin.panel.models', ['merlin.utils', function(utils) {
|
||||
angular
|
||||
.module('merlin')
|
||||
.factory('merlin.panel.models', merlinPanelModels);
|
||||
|
||||
merlinPanelModels.$inject = ['merlin.utils'];
|
||||
|
||||
function merlinPanelModels(utils) {
|
||||
var groupMixin = Barricade.Blueprint.create(function() {
|
||||
var self = this,
|
||||
additive = utils.getMeta(self, 'additive'),
|
||||
removable = utils.getMeta(self, 'removable');
|
||||
var self = this;
|
||||
var additive = utils.getMeta(self, 'additive');
|
||||
var removable = utils.getMeta(self, 'removable');
|
||||
|
||||
if ( additive === undefined ) {
|
||||
if ( angular.isUndefined(additive) ) {
|
||||
additive = true;
|
||||
}
|
||||
self.isAdditive = function() {
|
||||
return additive;
|
||||
};
|
||||
|
||||
if ( removable === undefined ) {
|
||||
if ( angular.isUndefined(removable) ) {
|
||||
removable = false;
|
||||
}
|
||||
self.isRemovable = function() {
|
||||
|
@ -33,7 +37,7 @@
|
|||
} else {
|
||||
return self.getID();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
self.setType('group');
|
||||
|
@ -43,7 +47,6 @@
|
|||
|
||||
return {
|
||||
groupmixin: groupMixin
|
||||
};
|
||||
}
|
||||
}])
|
||||
|
||||
})();
|
|
@ -1,7 +1,11 @@
|
|||
(function() {
|
||||
angular.module('merlin')
|
||||
.factory('merlin.templates', [
|
||||
'$http', '$q', function($http, $q) {
|
||||
angular
|
||||
.module('merlin')
|
||||
.factory('merlin.templates', merlinTemplates);
|
||||
|
||||
merlinTemplates.$inject = ['$http', '$q'];
|
||||
|
||||
function merlinTemplates($http, $q) {
|
||||
var promises = {};
|
||||
|
||||
function makeEmptyPromise() {
|
||||
|
@ -33,5 +37,5 @@
|
|||
prefetch: prefetch,
|
||||
templateReady: templateReady
|
||||
};
|
||||
}])
|
||||
}
|
||||
})();
|
|
@ -1,30 +1,35 @@
|
|||
/**
|
||||
* Created by tsufiev on 2/24/15.
|
||||
*/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
angular.module('merlin')
|
||||
.factory('merlin.utils', function() {
|
||||
Array.prototype.condense = function() {
|
||||
return this.filter(function(el) {
|
||||
return el !== undefined && el != null;
|
||||
});
|
||||
};
|
||||
angular
|
||||
.module('merlin')
|
||||
.factory('merlin.utils', merlinUtils);
|
||||
|
||||
var _id_counter = 0;
|
||||
function merlinUtils() {
|
||||
function condense(array) {
|
||||
return array.filter(function(el) {
|
||||
return angular.isDefined(el) && el !== null;
|
||||
});
|
||||
}
|
||||
|
||||
var idCounter = 0;
|
||||
|
||||
function getNewId() {
|
||||
_id_counter++;
|
||||
return 'id-' + _id_counter;
|
||||
idCounter++;
|
||||
return 'id-' + idCounter;
|
||||
}
|
||||
|
||||
function groupByMetaKey(sequence, metaKey, insertAtBeginning) {
|
||||
var newSequence = [], defaultBucket = [],
|
||||
index;
|
||||
var newSequence = [];
|
||||
var defaultBucket = [];
|
||||
var index;
|
||||
sequence.forEach(function(item) {
|
||||
index = getMeta(item, metaKey);
|
||||
if ( index !== undefined ) {
|
||||
if ( angular.isDefined(index) ) {
|
||||
if ( !newSequence[index] ) {
|
||||
newSequence[index] = [];
|
||||
newSequence[index][metaKey] = index;
|
||||
|
@ -34,7 +39,7 @@
|
|||
defaultBucket.push(item);
|
||||
}
|
||||
});
|
||||
newSequence = newSequence.condense();
|
||||
newSequence = condense(newSequence);
|
||||
// insert default bucket at the beginning/end of sequence
|
||||
if ( defaultBucket.length ) {
|
||||
if ( insertAtBeginning ) {
|
||||
|
@ -86,7 +91,7 @@
|
|||
|
||||
function extend(proto, extension) {
|
||||
var newObj;
|
||||
proto = (proto !== undefined ? proto : null);
|
||||
proto = (angular.isDefined(proto) ? proto : null);
|
||||
newObj = Object.create(proto);
|
||||
Object.keys(extension).forEach(function(key) {
|
||||
newObj[key] = extension[key];
|
||||
|
@ -102,8 +107,9 @@
|
|||
getNextIDSuffix: getNextIDSuffix,
|
||||
enhanceItemWithID: enhanceItemWithID,
|
||||
extend: extend,
|
||||
pop: pop
|
||||
pop: pop,
|
||||
condense: condense
|
||||
};
|
||||
}
|
||||
})
|
||||
|
||||
})();
|
||||
|
|
|
@ -16,15 +16,10 @@ describe('merlin.utils', function() {
|
|||
});
|
||||
});
|
||||
|
||||
describe('condense Array method', function() {
|
||||
it('Array prototype should have condense()', function() {
|
||||
var array = [];
|
||||
expect(array.condense).toBeDefined();
|
||||
});
|
||||
|
||||
describe('condense function', function() {
|
||||
it('condense() should throw away undefined and null values', function() {
|
||||
var array = [1, 0, 15, undefined, 7, null, null, 8];
|
||||
expect(array.condense()).toEqual([1, 0, 15, 7, 8]);
|
||||
expect(utils.condense(array)).toEqual([1, 0, 15, 7, 8]);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in New Issue