| 
									
										
										
										
											2018-03-25 13:41:29 -04:00
										 |  |  | import noteDetailService from '../services/note_detail.js'; | 
					
						
							| 
									
										
										
										
											2018-03-25 14:49:20 -04:00
										 |  |  | import server from '../services/server.js'; | 
					
						
							| 
									
										
										
										
											2018-03-25 21:29:35 -04:00
										 |  |  | import infoService from "../services/info.js"; | 
					
						
							| 
									
										
										
										
											2018-02-10 08:37:14 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  | const $dialog = $("#labels-dialog"); | 
					
						
							|  |  |  | const $saveLabelsButton = $("#save-labels-button"); | 
					
						
							|  |  |  | const $labelsBody = $('#labels-table tbody'); | 
					
						
							| 
									
										
										
										
											2018-01-11 00:01:16 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  | const labelsModel = new LabelsModel(); | 
					
						
							|  |  |  | let labelNames = []; | 
					
						
							| 
									
										
										
										
											2018-01-11 00:01:16 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  | function LabelsModel() { | 
					
						
							|  |  |  |     const self = this; | 
					
						
							| 
									
										
										
										
											2018-01-11 21:40:09 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |     this.labels = ko.observableArray(); | 
					
						
							| 
									
										
										
										
											2018-01-11 21:40:09 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-01 11:42:12 -04:00
										 |  |  |     this.updateLabelPositions = function() { | 
					
						
							|  |  |  |         let position = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // we need to update positions by searching in the DOM, because order of the
 | 
					
						
							|  |  |  |         // labels in the viewmodel (self.labels()) stays the same
 | 
					
						
							|  |  |  |         $labelsBody.find('input[name="position"]').each(function() { | 
					
						
							|  |  |  |             const label = self.getTargetLabel(this); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             label().position = position++; | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |     this.loadLabels = async function() { | 
					
						
							| 
									
										
										
										
											2018-03-25 13:41:29 -04:00
										 |  |  |         const noteId = noteDetailService.getCurrentNoteId(); | 
					
						
							| 
									
										
										
										
											2018-01-11 21:40:09 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |         const labels = await server.get('notes/' + noteId + '/labels'); | 
					
						
							| 
									
										
										
										
											2018-01-11 00:01:16 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |         self.labels(labels.map(ko.observable)); | 
					
						
							| 
									
										
										
										
											2018-02-04 19:27:27 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |         addLastEmptyRow(); | 
					
						
							| 
									
										
										
										
											2018-02-04 19:27:27 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |         labelNames = await server.get('labels/names'); | 
					
						
							| 
									
										
										
										
											2018-02-10 08:37:14 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |         // label might not be rendered immediatelly so could not focus
 | 
					
						
							|  |  |  |         setTimeout(() => $(".label-name:last").focus(), 100); | 
					
						
							| 
									
										
										
										
											2018-02-10 08:37:14 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |         $labelsBody.sortable({ | 
					
						
							|  |  |  |             handle: '.handle', | 
					
						
							|  |  |  |             containment: $labelsBody, | 
					
						
							| 
									
										
										
										
											2018-04-01 11:42:12 -04:00
										 |  |  |             update: this.updateLabelPositions | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |         }); | 
					
						
							|  |  |  |     }; | 
					
						
							| 
									
										
										
										
											2018-02-06 23:09:19 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |     this.deleteLabel = function(data, event) { | 
					
						
							| 
									
										
										
										
											2018-04-01 09:59:44 -04:00
										 |  |  |         const label = self.getTargetLabel(event.target); | 
					
						
							|  |  |  |         const labelData = label(); | 
					
						
							| 
									
										
										
										
											2018-02-06 23:09:19 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-01 09:59:44 -04:00
										 |  |  |         if (labelData) { | 
					
						
							| 
									
										
										
										
											2018-08-07 11:38:00 +02:00
										 |  |  |             labelData.isDeleted = true; | 
					
						
							| 
									
										
										
										
											2018-02-06 23:09:19 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-01 09:59:44 -04:00
										 |  |  |             label(labelData); | 
					
						
							| 
									
										
										
										
											2018-02-06 23:09:19 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |             addLastEmptyRow(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     }; | 
					
						
							| 
									
										
										
										
											2018-02-04 17:22:21 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |     function isValid() { | 
					
						
							| 
									
										
										
										
											2018-04-01 09:59:44 -04:00
										 |  |  |         for (let labels = self.labels(), i = 0; i < labels.length; i++) { | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |             if (self.isEmptyName(i)) { | 
					
						
							|  |  |  |                 return false; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2018-02-04 17:22:21 -05:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-02-04 23:16:45 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |     this.save = async function() { | 
					
						
							|  |  |  |         // we need to defocus from input (in case of enter-triggered save) because value is updated
 | 
					
						
							|  |  |  |         // on blur event (because of conflict with jQuery UI Autocomplete). Without this, input would
 | 
					
						
							|  |  |  |         // stay in focus, blur wouldn't be triggered and change wouldn't be updated in the viewmodel.
 | 
					
						
							|  |  |  |         $saveLabelsButton.focus(); | 
					
						
							| 
									
										
										
										
											2018-02-04 17:22:21 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |         if (!isValid()) { | 
					
						
							|  |  |  |             alert("Please fix all validation errors and try saving again."); | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-01-11 21:40:09 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-01 11:42:12 -04:00
										 |  |  |         self.updateLabelPositions(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 13:41:29 -04:00
										 |  |  |         const noteId = noteDetailService.getCurrentNoteId(); | 
					
						
							| 
									
										
										
										
											2018-02-04 17:22:21 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |         const labelsToSave = self.labels() | 
					
						
							| 
									
										
										
										
											2018-04-01 09:59:44 -04:00
										 |  |  |             .map(label => label()) | 
					
						
							|  |  |  |             .filter(label => label.labelId !== "" || label.name !== ""); | 
					
						
							| 
									
										
										
										
											2018-02-04 17:22:21 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |         const labels = await server.put('notes/' + noteId + '/labels', labelsToSave); | 
					
						
							| 
									
										
										
										
											2018-01-11 21:40:09 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |         self.labels(labels.map(ko.observable)); | 
					
						
							| 
									
										
										
										
											2018-01-11 21:40:09 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |         addLastEmptyRow(); | 
					
						
							| 
									
										
										
										
											2018-02-04 20:23:30 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 21:29:35 -04:00
										 |  |  |         infoService.showMessage("Labels have been saved."); | 
					
						
							| 
									
										
										
										
											2018-02-04 17:22:21 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 13:41:29 -04:00
										 |  |  |         noteDetailService.loadLabelList(); | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |     }; | 
					
						
							| 
									
										
										
										
											2018-02-04 17:22:21 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |     function addLastEmptyRow() { | 
					
						
							| 
									
										
										
										
											2018-08-07 11:38:00 +02:00
										 |  |  |         const labels = self.labels().filter(attr => !attr().isDeleted); | 
					
						
							| 
									
										
										
										
											2018-04-01 09:59:44 -04:00
										 |  |  |         const last = labels.length === 0 ? null : labels[labels.length - 1](); | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (!last || last.name.trim() !== "" || last.value !== "") { | 
					
						
							|  |  |  |             self.labels.push(ko.observable({ | 
					
						
							|  |  |  |                 labelId: '', | 
					
						
							|  |  |  |                 name: '', | 
					
						
							|  |  |  |                 value: '', | 
					
						
							| 
									
										
										
										
											2018-08-07 11:38:00 +02:00
										 |  |  |                 isDeleted: false, | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |                 position: 0 | 
					
						
							|  |  |  |             })); | 
					
						
							| 
									
										
										
										
											2018-02-04 17:22:21 -05:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-02-04 17:22:21 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |     this.labelChanged = function (data, event) { | 
					
						
							|  |  |  |         addLastEmptyRow(); | 
					
						
							| 
									
										
										
										
											2018-02-04 17:22:21 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-01 09:59:44 -04:00
										 |  |  |         const label = self.getTargetLabel(event.target); | 
					
						
							| 
									
										
										
										
											2018-02-06 23:09:19 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-01 09:59:44 -04:00
										 |  |  |         label.valueHasMutated(); | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |     }; | 
					
						
							| 
									
										
										
										
											2018-02-04 17:22:21 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |     this.isNotUnique = function(index) { | 
					
						
							|  |  |  |         const cur = self.labels()[index](); | 
					
						
							| 
									
										
										
										
											2018-02-04 17:22:21 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |         if (cur.name.trim() === "") { | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-02-04 17:22:21 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-01 09:59:44 -04:00
										 |  |  |         for (let labels = self.labels(), i = 0; i < labels.length; i++) { | 
					
						
							|  |  |  |             const label = labels[i](); | 
					
						
							| 
									
										
										
										
											2018-02-04 17:22:21 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-01 09:59:44 -04:00
										 |  |  |             if (index !== i && cur.name === label.name) { | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |                 return true; | 
					
						
							| 
									
										
										
										
											2018-02-04 17:22:21 -05:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-02-04 17:22:21 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |         return false; | 
					
						
							|  |  |  |     }; | 
					
						
							| 
									
										
										
										
											2018-02-04 17:22:21 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |     this.isEmptyName = function(index) { | 
					
						
							|  |  |  |         const cur = self.labels()[index](); | 
					
						
							| 
									
										
										
										
											2018-02-04 17:22:21 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |         return cur.name.trim() === "" && (cur.labelId !== "" || cur.value !== ""); | 
					
						
							|  |  |  |     }; | 
					
						
							| 
									
										
										
										
											2018-02-06 23:09:19 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |     this.getTargetLabel = function(target) { | 
					
						
							|  |  |  |         const context = ko.contextFor(target); | 
					
						
							|  |  |  |         const index = context.$index(); | 
					
						
							| 
									
										
										
										
											2018-02-06 23:09:19 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |         return self.labels()[index]; | 
					
						
							| 
									
										
										
										
											2018-01-11 00:01:16 -05:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2018-01-11 00:01:16 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  | async function showDialog() { | 
					
						
							|  |  |  |     glob.activeDialog = $dialog; | 
					
						
							| 
									
										
										
										
											2018-01-11 00:01:16 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |     await labelsModel.loadLabels(); | 
					
						
							| 
									
										
										
										
											2018-02-04 19:43:11 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |     $dialog.dialog({ | 
					
						
							|  |  |  |         modal: true, | 
					
						
							|  |  |  |         width: 800, | 
					
						
							|  |  |  |         height: 500 | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2018-01-11 00:01:16 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-28 17:02:48 +02:00
										 |  |  | ko.applyBindings(labelsModel, $dialog[0]); | 
					
						
							| 
									
										
										
										
											2018-02-04 19:43:11 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-28 17:02:48 +02:00
										 |  |  | $dialog.on('focus', '.label-name', function (e) { | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |     if (!$(this).hasClass("ui-autocomplete-input")) { | 
					
						
							|  |  |  |         $(this).autocomplete({ | 
					
						
							|  |  |  |             // shouldn't be required and autocomplete should just accept array of strings, but that fails
 | 
					
						
							| 
									
										
										
										
											2018-03-26 22:29:14 -04:00
										 |  |  |             // because we have overriden filter() function in autocomplete.js
 | 
					
						
							| 
									
										
										
										
											2018-04-01 09:59:44 -04:00
										 |  |  |             source: labelNames.map(label => { | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |                 return { | 
					
						
							| 
									
										
										
										
											2018-04-01 09:59:44 -04:00
										 |  |  |                     label: label, | 
					
						
							|  |  |  |                     value: label | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |                 } | 
					
						
							|  |  |  |             }), | 
					
						
							|  |  |  |             minLength: 0 | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-02-04 19:43:11 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |     $(this).autocomplete("search", $(this).val()); | 
					
						
							|  |  |  | }); | 
					
						
							| 
									
										
										
										
											2018-02-04 19:43:11 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-28 17:02:48 +02:00
										 |  |  | $dialog.on('focus', '.label-value', async function (e) { | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |     if (!$(this).hasClass("ui-autocomplete-input")) { | 
					
						
							|  |  |  |         const labelName = $(this).parent().parent().find('.label-name').val(); | 
					
						
							| 
									
										
										
										
											2018-02-04 19:43:11 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |         if (labelName.trim() === "") { | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-02-04 19:43:11 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |         const labelValues = await server.get('labels/values/' + encodeURIComponent(labelName)); | 
					
						
							| 
									
										
										
										
											2018-02-04 19:43:11 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |         if (labelValues.length === 0) { | 
					
						
							|  |  |  |             return; | 
					
						
							| 
									
										
										
										
											2018-02-04 19:43:11 -05:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-02-04 19:27:27 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |         $(this).autocomplete({ | 
					
						
							|  |  |  |             // shouldn't be required and autocomplete should just accept array of strings, but that fails
 | 
					
						
							| 
									
										
										
										
											2018-03-26 22:29:14 -04:00
										 |  |  |             // because we have overriden filter() function in autocomplete.js
 | 
					
						
							| 
									
										
										
										
											2018-04-01 09:59:44 -04:00
										 |  |  |             source: labelValues.map(label => { | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |                 return { | 
					
						
							| 
									
										
										
										
											2018-04-01 09:59:44 -04:00
										 |  |  |                     label: label, | 
					
						
							|  |  |  |                     value: label | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |                 } | 
					
						
							|  |  |  |             }), | 
					
						
							|  |  |  |             minLength: 0 | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-02-04 19:27:27 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  |     $(this).autocomplete("search", $(this).val()); | 
					
						
							|  |  |  | }); | 
					
						
							| 
									
										
										
										
											2018-03-24 00:54:50 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:09:17 -04:00
										 |  |  | export default { | 
					
						
							|  |  |  |     showDialog | 
					
						
							|  |  |  | }; |