implement dialog to import personal bookmarks
This commit is contained in:
		| @@ -80,7 +80,7 @@ h1 { | ||||
|     padding-right: 15px; | ||||
| } | ||||
|  | ||||
| .bookmarks table .frequency { | ||||
| .bookmarks table .frequency, .bookmark-list table .frequency { | ||||
|     text-align: right; | ||||
| } | ||||
|  | ||||
| @@ -90,6 +90,10 @@ h1 { | ||||
|     display: initial; | ||||
| } | ||||
|  | ||||
| .bookmark-list table .form-check-input { | ||||
|     margin-left: 0; | ||||
| } | ||||
|  | ||||
| .actions { | ||||
|     margin: 1rem 0; | ||||
| } | ||||
|   | ||||
| @@ -145,21 +145,3 @@ BookmarkBar.prototype.getDemodulatorPanel = function() { | ||||
| BookmarkBar.prototype.getDemodulator = function() { | ||||
|     return this.getDemodulatorPanel().getDemodulator(); | ||||
| }; | ||||
|  | ||||
| BookmarkLocalStorage = function(){ | ||||
| }; | ||||
|  | ||||
| BookmarkLocalStorage.prototype.getBookmarks = function(){ | ||||
|     return JSON.parse(window.localStorage.getItem("bookmarks")) || []; | ||||
| }; | ||||
|  | ||||
| BookmarkLocalStorage.prototype.setBookmarks = function(bookmarks){ | ||||
|     window.localStorage.setItem("bookmarks", JSON.stringify(bookmarks)); | ||||
| }; | ||||
|  | ||||
| BookmarkLocalStorage.prototype.deleteBookmark = function(data) { | ||||
|     if (data.id) data = data.id; | ||||
|     var bookmarks = this.getBookmarks(); | ||||
|     bookmarks = bookmarks.filter(function(b) { return b.id !== data; }); | ||||
|     this.setBookmarks(bookmarks); | ||||
| }; | ||||
|   | ||||
							
								
								
									
										17
									
								
								htdocs/lib/BookmarkLocalStorage.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								htdocs/lib/BookmarkLocalStorage.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| BookmarkLocalStorage = function(){ | ||||
| }; | ||||
|  | ||||
| BookmarkLocalStorage.prototype.getBookmarks = function(){ | ||||
|     return JSON.parse(window.localStorage.getItem("bookmarks")) || []; | ||||
| }; | ||||
|  | ||||
| BookmarkLocalStorage.prototype.setBookmarks = function(bookmarks){ | ||||
|     window.localStorage.setItem("bookmarks", JSON.stringify(bookmarks)); | ||||
| }; | ||||
|  | ||||
| BookmarkLocalStorage.prototype.deleteBookmark = function(data) { | ||||
|     if (data.id) data = data.id; | ||||
|     var bookmarks = this.getBookmarks(); | ||||
|     bookmarks = bookmarks.filter(function(b) { return b.id !== data; }); | ||||
|     this.setBookmarks(bookmarks); | ||||
| }; | ||||
| @@ -66,14 +66,16 @@ NameEditor.prototype.getInputHtml = function() { | ||||
|  | ||||
| function FrequencyEditor(table) { | ||||
|     Editor.call(this, table); | ||||
|     this.suffixes = { | ||||
|         'K': 3, | ||||
|         'M': 6, | ||||
|         'G': 9, | ||||
|         'T': 12 | ||||
|     }; | ||||
| } | ||||
|  | ||||
| FrequencyEditor.suffixes = { | ||||
|     '': 0, | ||||
|     'K': 3, | ||||
|     'M': 6, | ||||
|     'G': 9, | ||||
|     'T': 12 | ||||
| }; | ||||
|  | ||||
| FrequencyEditor.prototype = new Editor(); | ||||
|  | ||||
| FrequencyEditor.prototype.getInputHtml = function() { | ||||
| @@ -81,8 +83,7 @@ FrequencyEditor.prototype.getInputHtml = function() { | ||||
|         '<input class="form-control form-control-sm" type="number" step="1">' + | ||||
|         '<div class="input-group-append">' + | ||||
|             '<select class="input-group-text exponent">' + | ||||
|                 '<option value="0">Hz</option>' + | ||||
|                 $.map(this.suffixes, function(v, k) { | ||||
|                 $.map(FrequencyEditor.suffixes, function(v, k) { | ||||
|                     // fix lowercase "kHz" | ||||
|                     if (k === "K") k = "k"; | ||||
|                     return '<option value="' + v + '">' + k + 'Hz</option>'; | ||||
| @@ -117,8 +118,8 @@ FrequencyEditor.prototype.setupEvents = function() { | ||||
|         if (e.keyCode == 13) return me.submit(); | ||||
|         if (e.keyCode == 27) return me.cancel(); | ||||
|         var c = String.fromCharCode(e.which); | ||||
|         if (c in me.suffixes) { | ||||
|             me.expInput.val(me.suffixes[c]); | ||||
|         if (c in FrequencyEditor.suffixes) { | ||||
|             me.expInput.val(FrequencyEditor.suffixes[c]); | ||||
|         } | ||||
|     }); | ||||
| } | ||||
| @@ -132,7 +133,7 @@ FrequencyEditor.prototype.getValue = function() { | ||||
| FrequencyEditor.prototype.setValue = function(value) { | ||||
|     var value = parseFloat(value); | ||||
|     var exp = 0; | ||||
|     if (!Number.isNaN(value)) { | ||||
|     if (!Number.isNaN(value) && value > 0) { | ||||
|         exp = Math.floor(Math.log10(value) / 3) * 3; | ||||
|     } | ||||
|     this.freqInput.val(value / 10 ** exp); | ||||
| @@ -143,15 +144,26 @@ FrequencyEditor.prototype.focus = function() { | ||||
|     this.freqInput.focus(); | ||||
| }; | ||||
|  | ||||
| FrequencyEditor.prototype.getHtml = function() { | ||||
|     var value = this.getValue(); | ||||
| var renderFrequency = function(freq) { | ||||
|     var exp = 0; | ||||
|     if (!Number.isNaN(value)) { | ||||
|         exp = Math.floor(Math.log10(value) / 3) * 3; | ||||
|     if (!Number.isNaN(freq)) { | ||||
|         exp = Math.floor(Math.log10(freq) / 3) * 3; | ||||
|     } | ||||
|     var frequency = value / 10 ** exp; | ||||
|     var expString = this.expInput.find('option[value=' + exp + ']').html(); | ||||
|     var frequency = freq / 10 ** exp; | ||||
|     var suffix = Object.entries(FrequencyEditor.suffixes).find(function(e) { | ||||
|         return e[1] == exp; | ||||
|     }); | ||||
|     if (!suffix) { | ||||
|         return freq + ' Hz'; | ||||
|     } | ||||
|     // fix lowercase 'kHz' | ||||
|     suffix = suffix[0] == 'K' ? 'k' : suffix[0]; | ||||
|     var expString = suffix[0] + 'Hz'; | ||||
|     return frequency + ' ' + expString; | ||||
| } | ||||
|  | ||||
| FrequencyEditor.prototype.getHtml = function() { | ||||
|     return renderFrequency(this.getValue()); | ||||
| }; | ||||
|  | ||||
| function ModulationEditor(table) { | ||||
| @@ -313,5 +325,36 @@ $.fn.bookmarktable = function() { | ||||
|             $table.append(row); | ||||
|             row[0].scrollIntoView(); | ||||
|         }); | ||||
|  | ||||
|         var $importModal = $('#importModal').modal({show: false}); | ||||
|  | ||||
|         $(this).find('.bookmark-import').on('click', function() { | ||||
|             var storage = new BookmarkLocalStorage(); | ||||
|             var bookmarks = storage.getBookmarks(); | ||||
|             if (bookmarks.length) { | ||||
|                 var modes = $table.data('modes'); | ||||
|                 var $list = $('<table class="table table-sm">'); | ||||
|                 $list.append(bookmarks.map(function(b) { | ||||
|                     var modulation = b.modulation; | ||||
|                     if (modulation in modes) { | ||||
|                         modulation = modes[modulation]; | ||||
|                     } | ||||
|                     var row = $( | ||||
|                         '<tr>' + | ||||
|                             '<td><input class="form-check-input" type="checkbox" value="1"></td>' + | ||||
|                             '<td>' + b.name + '</td>' + | ||||
|                             '<td class="frequency">' + renderFrequency(b.frequency) + '</td>' + | ||||
|                             '<td>' + modulation + '</td>' + | ||||
|                         '</tr>' | ||||
|                     ); | ||||
|                     row.data('bookmark', b); | ||||
|                     return row; | ||||
|                 })); | ||||
|                 $importModal.find('.bookmark-list').html($list); | ||||
|             } else { | ||||
|                 $importModal.find('.bookmark-list').html('No personal bookmarks found in this browser'); | ||||
|             } | ||||
|             $importModal.modal('show'); | ||||
|         }); | ||||
|     }); | ||||
| }; | ||||
|   | ||||
| @@ -20,6 +20,7 @@ ${header} | ||||
|     <div class="row mt-3 bookmarks"> | ||||
|         ${bookmarks} | ||||
|         <div class="buttons container"> | ||||
|             <button type="button" class="btn btn-info bookmark-import">Import personal bookmarks...</button> | ||||
|             <button type="button" class="btn btn-primary bookmark-add">Add a new bookmark</button> | ||||
|         </div> | ||||
|     </div> | ||||
| @@ -43,4 +44,24 @@ ${header} | ||||
|         </div> | ||||
|     </div> | ||||
| </div> | ||||
| <div class="modal" id="importModal" tabindex="-1" role="dialog"> | ||||
|     <div class="modal-dialog modal-lg" role="document"> | ||||
|         <div class="modal-content"> | ||||
|             <div class="modal-header"> | ||||
|                 <h5>Please select</h5> | ||||
|                 <button type="button" class="close" data-dismiss="modal" aria-label="Close"> | ||||
|                     <span aria-hidden="true">×</span> | ||||
|                 </button> | ||||
|             </div> | ||||
|             <div class="modal-body"> | ||||
|                 <p>Please select the bookmarks you would like to import:</p> | ||||
|                 <div class="bookmark-list"></div> | ||||
|             </div> | ||||
|             <div class="modal-footer"> | ||||
|                 <button type="button" class="btn btn-secondary cancel" data-dismiss="modal">Cancel</button> | ||||
|                 <button type="button" class="btn btn-primary confirm">Import</button> | ||||
|             </div> | ||||
|         </div> | ||||
|     </div> | ||||
| </div> | ||||
| </body> | ||||
| @@ -125,6 +125,7 @@ class CompiledAssetsController(GzipMixin, ModificationAwareController): | ||||
|             "lib/Header.js", | ||||
|             "lib/Demodulator.js", | ||||
|             "lib/DemodulatorPanel.js", | ||||
|             "lib/BookmarkLocalStorage.js", | ||||
|             "lib/BookmarkBar.js", | ||||
|             "lib/BookmarkDialog.js", | ||||
|             "lib/AudioEngine.js", | ||||
| @@ -148,6 +149,7 @@ class CompiledAssetsController(GzipMixin, ModificationAwareController): | ||||
|             "lib/Header.js", | ||||
|             "lib/settings/MapInput.js", | ||||
|             "lib/settings/ImageUpload.js", | ||||
|             "lib/BookmarkLocalStorage.js", | ||||
|             "lib/settings/BookmarkTable.js", | ||||
|             "lib/settings/WsjtDecodingDepthsInput.js", | ||||
|             "lib/settings/WaterfallDropdown.js", | ||||
|   | ||||
| @@ -43,7 +43,9 @@ class BookmarksController(AuthorizationMixin, WebpageController): | ||||
|                 9: "G", | ||||
|                 12: "T", | ||||
|             } | ||||
|             exp = int(math.log10(freq) / 3) * 3 | ||||
|             exp = 0 | ||||
|             if freq > 0: | ||||
|                 exp = int(math.log10(freq) / 3) * 3 | ||||
|             num = freq | ||||
|             suffix = "" | ||||
|             if exp in suffixes: | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Jakob Ketterl
					Jakob Ketterl