Finalized.

This commit is contained in:
Marat Fayzullin 2024-10-28 13:02:23 -04:00
parent 4cabf86fcc
commit 5084e9f715
5 changed files with 91 additions and 62 deletions

View File

@ -378,7 +378,7 @@
</div>
<div class="form-field">
<label for="frequency">Frequency:</label>
<input type="number" id="frequency" name="frequency">
<input type="number" id="frequency" name="frequency" min="1">
</div>
<div class="form-field">
<label for="modulation">Modulation:</label>

View File

@ -114,26 +114,39 @@ BookmarkBar.prototype.showEditDialog = function(bookmark) {
name: '',
frequency: center_freq + this.getDemodulator().get_offset_frequency(),
modulation: mode1,
underlying: this.verifyUnderlying(mode2, mode1),
underlying: mode2,
description: '',
scannable : this.modesToScan.indexOf(mode1) >= 0
}
this.sanitizeBookmark(bookmark);
}
this.$dialog.bookmarkDialog().setValues(bookmark);
this.$dialog.show();
this.$dialog.find('#name').focus();
};
BookmarkBar.prototype.verifyUnderlying = function(underlying, modulation) {
if (!underlying) return '';
BookmarkBar.prototype.sanitizeBookmark = function(b) {
// must have name, frequency, and modulation
if (!b.name || !b.frequency || !b.modulation)
return "Must have name, frequency, and modulation.";
// check that underlying demod is valid and NOT the default one
var mode = Modes.findByModulation(modulation);
if (!mode || !mode.underlying || mode.underlying.indexOf(underlying) <= 0) {
return '';
}
// must have non-empty name
b.name = b.name.trim();
if (b.name.length <= 0) return "Must have a non-empty name.";
return underlying;
// must have positive frequency
b.frequency = Number(b.frequency);
if (b.frequency <= 0) return "Frequency must be positive.";
// must have valid modulation
var mode = Modes.findByModulation(b.modulation);
if (!mode) return "Must have valid modulation."
// check that underlying demodulator is valid
if (!b.underlying || !mode.underlying || mode.underlying.indexOf(b.underlying) < 0)
b.underlying = '';
return null;
};
BookmarkBar.prototype.storeBookmark = function() {
@ -141,14 +154,8 @@ BookmarkBar.prototype.storeBookmark = function() {
var bookmark = this.$dialog.bookmarkDialog().getValues();
if (!bookmark) return;
// parse bookmark frequency to a number
bookmark.frequency = Number(bookmark.frequency);
// make sure underlying demod, if present, is valid
bookmark.underlying = this.verifyUnderlying(
bookmark.underlying,
bookmark.modulation
);
var error = this.sanitizeBookmark(bookmark);
if (error) { alert(error); return; }
var bookmarks = me.localBookmarks.getBookmarks();

View File

@ -47,4 +47,4 @@ $.fn.bookmarkDialog = function() {
return bookmark;
}
}
}
};

View File

@ -368,6 +368,9 @@ $.fn.bookmarktable = function() {
data: JSON.stringify([data]),
contentType: 'application/json',
method: 'POST'
}).fail(function(data) {
// adding failed, reenable inputs
$.map(inputs, function(input, name) { input.disable(false); });
}).done(function(data) {
if (data.length && data.length === 1 && 'bookmark_id' in data[0]) {
row.attr('data-id', data[0]['bookmark_id']);
@ -378,16 +381,16 @@ $.fn.bookmarktable = function() {
td.data('value', input.getValue());
td.html(input.getHtml());
});
}
var $cell = row.find('td').last();
var $group = $cell.find('.btn-group');
if ($group.length) {
$group.remove;
$cell.html('<div class="btn btn-sm btn-danger bookmark-delete">delete</div>');
}
// remove inputs
var $cell = row.find('td').last();
var $group = $cell.find('.btn-group');
if ($group.length) {
$group.remove;
$cell.html('<div class="btn btn-sm btn-danger bookmark-delete">delete</div>');
}
});
});
$table.append(row);
@ -435,7 +438,10 @@ $.fn.bookmarktable = function() {
data: JSON.stringify(selected),
contentType: 'application/json',
method: 'POST'
}).done(function(data){
}).fail(function(data) {
// import failed
$table.find('.emptytext').remove();
}).done(function(data) {
$table.find('.emptytext').remove();
var modes = $table.data('modes');
if (data.length && data.length == selected.length) {

View File

@ -110,26 +110,44 @@ class BookmarksController(AuthorizationMixin, BreadcrumbMixin, WebpageController
except StopIteration:
return None
def _verifyUnderlyingMode(self, data):
# Get both modes
mode1 = Modes.findByModulation(data["modulation"]) if "modulation" in data else None
mode2 = Modes.findByModulation(data["underlying"]) if "underlying" in data else None
# Unknown main mode
if mode1 is None:
return False
# No underlying mode
if mode2 is None:
data["underlying"] = ""
return True
# Main mode has no underlying mode or underlying mode incorrect
if not hasattr(mode1, "underlying") or mode2.modulation not in mode1.underlying:
return False
# Underlying mode is at the default value
if mode2.modulation == mode1.underlying[0]:
data["underlying"] = ""
return True
# Underlying mode ok
return True
def _sanitizeBookmark(self, data):
try:
# Must have name, frequency, modulation
if "name" not in data or "frequency" not in data or "modulation" not in data:
return "Bookmark missing required fields"
# Name must not be empty
data["name"] = data["name"].strip()
if len(data["name"]) == 0:
return "Empty bookmark name"
# Frequency must be integer
if not isinstance(data["frequency"], int):
data["frequency"] = int(data["frequency"])
# Frequency must be >0
if data["frequency"] <= 0:
return "Frequency must be positive"
# Get both modes
mode1 = Modes.findByModulation(data["modulation"]) if "modulation" in data else None
mode2 = Modes.findByModulation(data["underlying"]) if "underlying" in data else None
# Unknown main mode
if mode1 is None:
return "Invalid modulation"
# No underlying mode
if mode2 is None:
data["underlying"] = ""
else:
# Main mode has no underlying mode or underlying mode incorrect
if not hasattr(mode1, "underlying") or mode2.modulation not in mode1.underlying:
return "Incorrect underlying modulation"
# Underlying mode is at the default value
#if mode2.modulation == mode1.underlying[0]:
# data["underlying"] = ""
except Exception as e:
# Something else went horribly wrong
return str(e)
# Everything ok
return None
def update(self):
bookmark_id = int(self.request.matches.group(1))
@ -142,15 +160,13 @@ class BookmarksController(AuthorizationMixin, BreadcrumbMixin, WebpageController
data = json.loads(self.get_body().decode("utf-8"))
for key in ["name", "frequency", "modulation", "underlying", "description", "scannable"]:
if key in data:
value = data[key]
if key == "frequency":
value = int(value)
newd[key] = value
newd[key] = data[key]
elif hasattr(bookmark, key):
newd[key] = getattr(bookmark, key)
# Make sure underlying mode is correct
if not self._verifyUnderlyingMode(newd):
raise ValueError("Bad underlying modulation")
# Make sure everything is correct
error = self._sanitizeBookmark(newd)
if error is not None:
raise ValueError(error)
# Update and store bookmark
for key in newd:
setattr(bookmark, key, newd[key])
@ -158,7 +174,8 @@ class BookmarksController(AuthorizationMixin, BreadcrumbMixin, WebpageController
# TODO this should not be called explicitly... bookmarks don't have any event capability right now, though
Bookmarks.getSharedInstance().notifySubscriptions(bookmark)
self.send_response("{}", content_type="application/json", code=200)
except (json.JSONDecodeError, ValueError):
except (json.JSONDecodeError, ValueError) as e:
logger.warning("Failed updating bookmark: " + str(e))
self.send_response("{}", content_type="application/json", code=400)
def new(self):
@ -169,12 +186,10 @@ class BookmarksController(AuthorizationMixin, BreadcrumbMixin, WebpageController
data = {}
for key in ["name", "frequency", "modulation", "underlying", "description", "scannable"]:
if key in bookmark_data:
if key == "frequency":
data[key] = int(bookmark_data[key])
else:
data[key] = bookmark_data[key]
if not self._verifyUnderlyingMode(data):
raise ValueError("Bad underlying modulation")
data[key] = bookmark_data[key]
error = self._sanitizeBookmark(data)
if error is not None:
raise ValueError(error)
bookmark = Bookmark(data)
bookmarks.addBookmark(bookmark)
return {"bookmark_id": id(bookmark)}
@ -184,7 +199,8 @@ class BookmarksController(AuthorizationMixin, BreadcrumbMixin, WebpageController
result = [create(b) for b in data]
bookmarks.store()
self.send_response(json.dumps(result), content_type="application/json", code=200)
except (json.JSONDecodeError, ValueError):
except (json.JSONDecodeError, ValueError) as e:
logger.warning("Failed creating bookmark: " + str(e))
self.send_response("{}", content_type="application/json", code=400)
def delete(self):