diff --git a/src/js/views/figure_view.js b/src/js/views/figure_view.js
index 562fd207d..c8f5fef93 100644
--- a/src/js/views/figure_view.js
+++ b/src/js/views/figure_view.js
@@ -18,6 +18,7 @@
new RoiModalView({model: this.model});
new DpiModalView({model: this.model});
new LegendView({model: this.model});
+ new LabelFromMapsModal({model: this.model});
this.figureFiles = new FileList();
new FileListView({model:this.figureFiles, figureModel: this.model});
diff --git a/src/js/views/labels_from_maps_modal.js b/src/js/views/labels_from_maps_modal.js
new file mode 100644
index 000000000..1ab6f891a
--- /dev/null
+++ b/src/js/views/labels_from_maps_modal.js
@@ -0,0 +1,164 @@
+
+var LabelFromMapsModal = Backbone.View.extend({
+
+ el: $("#labelsFromMapAnns"),
+
+ model: FigureModel,
+
+ // label options: position, size, color
+ options: {},
+
+ /**
+ * Constructor - listen for dialog opening to load data and render
+ */
+ initialize: function() {
+ // when dialog is shown, load map annotations for selected images
+ $("#labelsFromMapAnns").bind("show.bs.modal", function(event){
+ // event options from the label form: {position: 'top', size: '12', color: '0000'}
+ this.options = event.relatedTarget;
+ this.loadMapAnns();
+ }.bind(this));
+ },
+
+ events: {
+ "submit .labelsFromMapAnnsForm": "handleForm",
+ "change select": "renderExampleLabel",
+ "change input": "renderExampleLabel",
+ },
+
+ /**
+ * Load the map annotations, then call render()
+ */
+ loadMapAnns() {
+ let imageIds = this.model.getSelected().map(function(m){return m.get('imageId')});
+ this.isLoading = true;
+ $('select', this.el).html("
");
+
+ var url = WEBINDEX_URL + "api/annotations/?type=map&image=";
+ url += imageIds.join("&image=");
+
+ $.getJSON(url, function(data) {
+ this.isLoading = false;
+ this.annotations = data.annotations;
+ this.render();
+ }.bind(this)
+ );
+ },
+
+ /**
+ * Handle submission of the form to create labels and close dialog
+ *
+ * @param {Object} event
+ */
+ handleForm: function(event) {
+ event.preventDefault();
+ if (this.isLoading) return;
+
+ var key = $('select', this.el).val();
+ var includeKey = $("input[name='includeKey']").is(':checked');
+ var labelSize = this.options.size || "12";
+ var labelPosition = this.options.position || "top";
+ var labelColor = this.options.color || "000000";
+
+ var imageValues = this.annotations.reduce(function(prev, t){
+ var iid = t.link.parent.id;
+ if (!prev[iid]) {
+ prev[iid] = [];
+ }
+ t.values.forEach(function(kv) {
+ if (kv[0] === key) {
+ prev[iid].push(kv[1]);
+ }
+ });
+ return prev;
+ }, {});
+
+ this.model.getSelected().forEach(function(p){
+ var iid = p.get('imageId');
+ if (imageValues[iid]) {
+ var labels = imageValues[iid].map(function(value){
+ return {
+ 'text': includeKey ? (key + ': ' + value) : value,
+ 'size': labelSize,
+ 'position': labelPosition,
+ 'color': labelColor,
+ }
+ });
+ p.add_labels(labels);
+ }
+ });
+ $("#labelsFromMapAnns").modal('hide');
+ return false;
+ },
+
+ /**
+ * Renders the Example label based on currently selected Key and includeKey
+ */
+ renderExampleLabel: function() {
+ var key = $('select', this.el).val();
+ var includeKey = $("input[name='includeKey']").is(':checked');
+ // find first annotation with this value
+ var label;
+ for (var a=0; a
for choosing Key. Also calls renderExampleLabel()
+ */
+ render: function() {
+ // Get keys for images {'key' : {iid: true}}
+ var keys = {};
+ this.annotations.forEach(function(ann) {
+ let iid = ann.link.parent.id;
+ ann.values.forEach(function(kv){
+ var key = kv[0];
+ if (!keys[key]) {
+ keys[key] = {};
+ }
+ keys[key][iid] = true;
+ })
+ });
+
+ // Make a list of keys (and sort) along with counts of images for each key
+ var keyList = [];
+ var keyCounts = {};
+ for (var key in keys) {
+ if (keys.hasOwnProperty(key)) {
+ keyList.push(key);
+ keyCounts[key] = Object.keys(keys[key]).length;
+ }
+ }
+ keyList.sort(function(a, b) {
+ return (a.toUpperCase() < b.toUpperCase()) ? -1 : 1;
+ });
+
+ var html = keyList.map(function(key) {
+ return "";
+ }).join("");
+ if (keyList.length === 0) {
+ html = "";
+ }
+ $('select', this.el).html(html);
+
+ this.renderExampleLabel();
+ }
+});
diff --git a/src/js/views/right_panel_view.js b/src/js/views/right_panel_view.js
index 88a65f2fb..e510742ef 100644
--- a/src/js/views/right_panel_view.js
+++ b/src/js/views/right_panel_view.js
@@ -266,6 +266,7 @@
// For the Label Text, handle this differently...
if ($a.attr('data-label')) {
$('.new-label-form .label-text', this.$el).val( $a.attr('data-label') );
+ return;
}
// All others, we take the from the and place it in the