add the "add bookmarks" function
This commit is contained in:
		| @@ -1,6 +1,10 @@ | ||||
| @import url("openwebrx-header.css"); | ||||
| @import url("openwebrx-globals.css"); | ||||
|  | ||||
| html, body { | ||||
|     height: unset; | ||||
| } | ||||
|  | ||||
| .buttons { | ||||
|     text-align: right; | ||||
| } | ||||
| @@ -59,8 +63,16 @@ table.bookmarks .frequency { | ||||
|     text-align: right; | ||||
| } | ||||
|  | ||||
| table.bookmarks input, table.bookmarks select { | ||||
| .bookmarks table input, .bookmarks table select { | ||||
|     width: initial; | ||||
|     text-align: inherit; | ||||
|     display: initial; | ||||
| } | ||||
|  | ||||
| .actions { | ||||
|     margin: 1rem 0; | ||||
| } | ||||
|  | ||||
| .actions .btn { | ||||
|     width: 100%; | ||||
| } | ||||
| @@ -1,6 +1,6 @@ | ||||
| $.fn.bookmarktable = function() { | ||||
|     $.each(this, function(){ | ||||
|         var $table = $(this); | ||||
|         var $table = $(this).find('table'); | ||||
|  | ||||
|         var inputs = $table.find('tr.inputs td').map(function(){ | ||||
|             var candidates = $(this).find('input, select') | ||||
| @@ -8,6 +8,16 @@ $.fn.bookmarktable = function() { | ||||
|         }).toArray(); | ||||
|         $table.find('tr.inputs').remove(); | ||||
|  | ||||
|         var transformToHtml = function($cell) { | ||||
|             var $input = $cell.find('input, select'); | ||||
|             var $option = $input.find('option:selected') | ||||
|             if ($option.length) { | ||||
|                 $cell.html($option.html()); | ||||
|             } else { | ||||
|                 $cell.html($input.val()); | ||||
|             } | ||||
|         }; | ||||
|  | ||||
|         $table.on('dblclick', 'td', function(e) { | ||||
|             var $cell = $(e.target); | ||||
|             var html = $cell.html(); | ||||
| @@ -18,6 +28,7 @@ $.fn.bookmarktable = function() { | ||||
|             var $input = inputs[index]; | ||||
|             if (!$input) return; | ||||
|  | ||||
|             $table.find('tr[data-id="new"]').remove(); | ||||
|             $input.val($cell.data('value') || html); | ||||
|             $input.prop('disabled', false); | ||||
|             $cell.html($input); | ||||
| @@ -30,12 +41,7 @@ $.fn.bookmarktable = function() { | ||||
|                     contentType: 'application/json', | ||||
|                     method: 'POST' | ||||
|                 }).then(function(){ | ||||
|                     var $option = $input.find('option:selected') | ||||
|                     if ($option.length) { | ||||
|                         $cell.html($option.html()); | ||||
|                     } else { | ||||
|                         $cell.html($input.val()); | ||||
|                     } | ||||
|                     transformToHtml($cell); | ||||
|                 }); | ||||
|             }; | ||||
|  | ||||
| @@ -46,5 +52,64 @@ $.fn.bookmarktable = function() { | ||||
|                 } | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         $(this).find('.bookmark-add').on('click', function() { | ||||
|             if ($table.find('tr[data-id="new"]').length) return; | ||||
|  | ||||
|             var row = $('<tr data-id="new">'); | ||||
|             row.append(inputs.map(function(i){ | ||||
|                 var cell = $('<td>'); | ||||
|                 if (i) { | ||||
|                     i.prop('disabled', false); | ||||
|                     i.val(''); | ||||
|                     cell.html(i); | ||||
|                 } else { | ||||
|                     cell.html( | ||||
|                         '<div class="btn-group btn-group-sm">' + | ||||
|                             '<button class="btn btn-primary bookmark-save">Save</button>' + | ||||
|                             '<button class="btn btn-secondary bookmark-cancel">Cancel</button>' + | ||||
|                         '</div>' | ||||
|                     ); | ||||
|                 } | ||||
|                 return cell; | ||||
|             })); | ||||
|  | ||||
|             row.on('click', '.bookmark-cancel', function() { | ||||
|                 row.remove(); | ||||
|             }); | ||||
|  | ||||
|             row.on('click', '.bookmark-save', function() { | ||||
|                 var data = Object.fromEntries( | ||||
|                     row.find('input, select').toArray().map(function(input){ | ||||
|                         var $input = $(input); | ||||
|                         $input.prop('disabled', true); | ||||
|                         return [$input.prop('name'), $input.val()] | ||||
|                     }) | ||||
|                 ); | ||||
|  | ||||
|                 $.ajax(document.location.href, { | ||||
|                     data: JSON.stringify(data), | ||||
|                     contentType: 'application/json', | ||||
|                     method: 'POST' | ||||
|                 }).then(function(data){ | ||||
|                     if ('bookmark_id' in data) { | ||||
|                         row.attr('data-id', data['bookmark_id']); | ||||
|                         row.find('td').each(function(){ | ||||
|                             var $cell = $(this); | ||||
|                             var $group = $cell.find('.btn-group') | ||||
|                             if ($group.length) { | ||||
|                                 $group.remove; | ||||
|                                 $cell.html('<div class="btn btn-sm btn-danger bookmark-delete">delete</div>'); | ||||
|                             } | ||||
|                             transformToHtml($cell); | ||||
|                         }); | ||||
|                     } | ||||
|                 }); | ||||
|  | ||||
|             }); | ||||
|  | ||||
|             $table.append(row); | ||||
|             row[0].scrollIntoView(); | ||||
|         }); | ||||
|     }); | ||||
| }; | ||||
|   | ||||
| @@ -23,5 +23,5 @@ $(function(){ | ||||
|  | ||||
|     $(".sdrdevice").sdrdevice(); | ||||
|     $(".imageupload").imageUpload(); | ||||
|     $("table.bookmarks").bookmarktable(); | ||||
|     $(".bookmarks").bookmarktable(); | ||||
| }); | ||||
| @@ -13,7 +13,18 @@ ${header} | ||||
| <div class="container"> | ||||
|     <div class="row"> | ||||
|         <h1 class="col-12">Bookmarks</h1> | ||||
|         <div class="col-12"> | ||||
|             Double-click the values in the table to edit them. | ||||
|         </div> | ||||
|     </div> | ||||
|     <div class="bookmarks"> | ||||
|         <div class="actions"> | ||||
|             <button class="btn btn-primary bookmark-add">Add a new bookmark</button> | ||||
|         </div> | ||||
|         ${bookmarks} | ||||
|         <div class="actions"> | ||||
|             <button class="btn btn-primary bookmark-add">Add a new bookmark</button> | ||||
|         </div> | ||||
|     </div> | ||||
|     ${bookmarks} | ||||
| </div> | ||||
| </body> | ||||
| @@ -96,3 +96,6 @@ class Bookmarks(object): | ||||
|         with open(Bookmarks._getBookmarksFile(), "w") as file: | ||||
|             json.dump([b.__dict__() for b in self.bookmarks], file, indent=4) | ||||
|         self.file_modified = self._getFileModifiedTimestamp() | ||||
|  | ||||
|     def addBookmark(self, bookmark: Bookmark): | ||||
|         self.bookmarks.append(bookmark) | ||||
|   | ||||
| @@ -32,7 +32,7 @@ class BookmarksController(AuthorizationMixin, WebpageController): | ||||
|             ) | ||||
|  | ||||
|         return """ | ||||
|             <table class="table bookmarks"> | ||||
|             <table class="table"> | ||||
|                 <tr> | ||||
|                     <th>Name</th> | ||||
|                     <th class="frequency">Frequency</th> | ||||
| @@ -97,5 +97,19 @@ class BookmarksController(AuthorizationMixin, WebpageController): | ||||
|         except json.JSONDecodeError: | ||||
|             self.send_response("{}", content_type="application/json", code=400) | ||||
|  | ||||
|     def new(self): | ||||
|         bookmarks = Bookmarks.getSharedInstance() | ||||
|         try: | ||||
|             data = json.loads(self.get_body()) | ||||
|             # sanitize | ||||
|             data = {k: data[k] for k in ["name", "frequency", "modulation"]} | ||||
|             bookmark = Bookmark(data) | ||||
|  | ||||
|             bookmarks.addBookmark(bookmark) | ||||
|             bookmarks.store() | ||||
|             self.send_response(json.dumps({"bookmark_id": id(bookmark)}), content_type="application/json", code=200) | ||||
|         except json.JSONDecodeError: | ||||
|             self.send_response("{}", content_type="application/json", code=400) | ||||
|  | ||||
|     def indexAction(self): | ||||
|         self.serve_template("settings/bookmarks.html", **self.template_variables()) | ||||
|   | ||||
| @@ -110,6 +110,7 @@ class Router(object): | ||||
|             ), | ||||
|             StaticRoute("/settings/sdr", SdrSettingsController), | ||||
|             StaticRoute("/settings/bookmarks", BookmarksController), | ||||
|             StaticRoute("/settings/bookmarks", BookmarksController, method="POST", options={"action": "new"}), | ||||
|             RegexRoute("/settings/bookmarks/(.+)", BookmarksController, method="POST", options={"action": "update"}), | ||||
|             StaticRoute("/login", SessionController, options={"action": "loginAction"}), | ||||
|             StaticRoute("/login", SessionController, method="POST", options={"action": "processLoginAction"}), | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Jakob Ketterl
					Jakob Ketterl