Last active
October 21, 2015 20:48
-
-
Save hallvors/9cdf228aeb72598b78eb to your computer and use it in GitHub Desktop.
A label list implementation for webcompat.com
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* A LabelList is a list of labels. It takes care of all namespace | |
* prefixing and unprefixing, so that the rest of the app doesn't | |
* ever need to worry about those details. Just pass in a list | |
* of labels from the server or a URL. | |
*/ | |
issues.LabelList = Backbone.Model.extend({ | |
initialize: function() { | |
this.set('namespaceRegex', /(browser|closed|os|status)-(.+)/i); | |
this.set('allLabelsURL', '/api/issues/labels'); // see "need a complete list" below | |
// if we're initialized with {labels:array-of-objects} | |
var inputLabelData = this.get('labels'); | |
this.set('labels', []); | |
if(inputLabelData) { | |
// If we have an array, process labels | |
this.parse(inputLabelData); | |
} else { | |
// We default to making a list of all labels if lacking other data | |
if(! this.get('url')) { | |
this.set('url', this.get('allLabelsURL')); | |
} | |
// If we have an URL, start a fetch | |
var headersBag = {headers: {'Accept': 'application/json'}}; | |
this.fetch(headersBag); // This will trigger parse() | |
} | |
// We allow updating 'labels', but want to make sure | |
// other internal details are kept sync'ed.. | |
this.on('change:labels', function(){ | |
this.set('labelsArray', _.pluck(this.get('labels'), 'name')); | |
}); | |
// We need a complete list of labels for certain operations, | |
// especially namespace mapping. If the list we're handling | |
// doesn't happen to contain all the labels initially, it | |
// can't get prefixing/unprefixing right when labels in previously | |
// unseen namespaces are added in their local name form. | |
if(this.get('url') === this.get('allLabelsURL')) { | |
this.set('allLabels', this); | |
} else { | |
this.set('allLabels', new issues.LabelList({url:this.get('allLabelsURL')})); | |
} | |
}, | |
parse: function(labelsArray){ | |
var list = []; | |
var namespaceMap = {"ns2local":{}, "local2ns":{}}; | |
for(var i = 0, matches; i < labelsArray.length; i++){ | |
matches = labelsArray[i].name.match(this.get('namespaceRegex')); | |
if(matches) { | |
namespaceMap.local2ns[matches[2]] = matches[1]; | |
namespaceMap.ns2local[matches[0]] = matches[2]; | |
list[i] = { | |
'name': matches[2], | |
'url': labelsArray[i].url, | |
'color': labelsArray[i].color, | |
}; | |
}else { | |
list[i] = labelsArray[i]; | |
} | |
}; | |
this.set('labels', list); | |
this.set('namespaceMap', namespaceMap); | |
}, | |
// toLocal takes a repository label name and maps it | |
// to the unprefixed local form. Also handles an array | |
// of label names (Note: not arrays of objects) | |
toLocal: function(input) { | |
var all = this.get('allLabels'); | |
if (typeof input === 'string') { | |
return all.get('namespaceMap').ns2local[input] || input; | |
} else { | |
return input.map(function(label){return this.toLocal(label);}.bind(all)); | |
} | |
}, | |
// toNamespaced takes a local label name and maps it | |
// to the prefixed repository form. Also handles an array | |
// of label names (Note: not arrays of objects) | |
toNamespaced: function (input) { | |
var all = this.get('allLabels'); | |
if (typeof input === 'string') { | |
return all.get('namespaceMap').local2ns[input] + '-' + input || input; | |
} else { | |
return input.map(function(label){return this.toNamespaced(label);}.bind(all)); | |
} | |
}, | |
url: function() { | |
return this.get('url'); | |
}, | |
// To save the model to the server, we need to make | |
// sure we apply the prefixes the server expects | |
save: function() { | |
var all = this.get('allLabels'); | |
var labelsArray = this.get('labelsArray'); | |
var saveLabels = all.toNamespaced(labelsArray); | |
var url = this.url(); | |
// We create a new model with only the labels we | |
// want to send to the server to save | |
var saver = new (Backbone.Model.extend({ | |
url:function(){return url;} | |
}))({labels:saveLabels}); | |
saver.save(); | |
} | |
}); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
toNamespaced might be better named "toPrefixed" and toLocal -> toUnprefixed ?
("Local name" and "namespace" terminology is XMLish)
toNamespaced() (by any name) should never apply a namespace to a label that has namespace prefix already - simply because there would be no match in the local2ns object. But this should be tested.