Clean up debug UI and code a bit. Allow empty StateEntry values.
This commit is contained in:
@@ -98,7 +98,7 @@ class Client(db.Model):
|
|||||||
class StateEntry(db.Model):
|
class StateEntry(db.Model):
|
||||||
last_set = db.DateTimeProperty(required=True, auto_now=True)
|
last_set = db.DateTimeProperty(required=True, auto_now=True)
|
||||||
entry_key = db.StringProperty(required=True)
|
entry_key = db.StringProperty(required=True)
|
||||||
entry_value = db.StringProperty(required=True)
|
entry_value = db.StringProperty()
|
||||||
|
|
||||||
def ToMessage(self):
|
def ToMessage(self):
|
||||||
return {
|
return {
|
||||||
@@ -114,3 +114,4 @@ class Subject(db.Model):
|
|||||||
|
|
||||||
class Subscription(db.Model):
|
class Subscription(db.Model):
|
||||||
client = db.ReferenceProperty(reference_class=Client)
|
client = db.ReferenceProperty(reference_class=Client)
|
||||||
|
subject = db.ReferenceProperty(reference_class=Subject)
|
||||||
|
|||||||
@@ -149,6 +149,12 @@ cosmopolite.Client.prototype.setValue = function(key, value) {
|
|||||||
'key': key,
|
'key': key,
|
||||||
'value': value,
|
'value': value,
|
||||||
})
|
})
|
||||||
|
// Provide immediate feedback without waiting for a round trip.
|
||||||
|
// We'll also get a response from the server, so this should be eventually
|
||||||
|
// consistent.
|
||||||
|
if ('onStateChange' in this.callbacks_) {
|
||||||
|
this.callbacks_['onStateChange'](key, value);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
cosmopolite.Client.prototype.getValue = function(key) {
|
cosmopolite.Client.prototype.getValue = function(key) {
|
||||||
|
|||||||
@@ -12,18 +12,32 @@ a {
|
|||||||
|
|
||||||
<div>
|
<div>
|
||||||
Key:
|
Key:
|
||||||
<select id="keys">
|
<select id="keys"></select>
|
||||||
<option></option>
|
|
||||||
<option>(add new)</option>
|
|
||||||
</select>
|
|
||||||
<input type="button" id="set" value="Set">
|
<input type="button" id="set" value="Set">
|
||||||
|
<input type="button" id="add" value="Add">
|
||||||
<br />
|
<br />
|
||||||
<textarea id="value" rows="10" cols="40"></textarea>
|
<textarea id="value" rows="10" cols="40"></textarea>
|
||||||
</div>
|
</div>
|
||||||
<script>
|
<script>
|
||||||
|
var keys = document.getElementById('keys');
|
||||||
|
var value = document.getElementById('value');
|
||||||
|
|
||||||
|
var selectKey = function(new_key) {
|
||||||
|
keys.value = new_key;
|
||||||
|
keys.dispatchEvent(new CustomEvent('change'));
|
||||||
|
};
|
||||||
|
|
||||||
|
var addKey = function(new_key, new_value, index) {
|
||||||
|
var option = document.createElement('option');
|
||||||
|
option.text = new_key;
|
||||||
|
keys.options.add(option, index);
|
||||||
|
if (keys.options.length == 1) {
|
||||||
|
selectKey(new_key);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
window.addEventListener('load', function() {
|
window.addEventListener('load', function() {
|
||||||
var googleUser = document.getElementById('google_user');
|
var googleUser = document.getElementById('google_user');
|
||||||
var keys = document.getElementById('keys');
|
|
||||||
|
|
||||||
var callbacks = {
|
var callbacks = {
|
||||||
onLogin: function(username, logout_url) {
|
onLogin: function(username, logout_url) {
|
||||||
@@ -35,47 +49,38 @@ window.addEventListener('load', function() {
|
|||||||
googleUser.innerHTML =
|
googleUser.innerHTML =
|
||||||
'<a href="' + login_url + '" target="_blank">(log in)</a>';
|
'<a href="' + login_url + '" target="_blank">(log in)</a>';
|
||||||
},
|
},
|
||||||
onStateChange: function(key, value) {
|
onStateChange: function(new_key, new_value) {
|
||||||
for (var i = 0; i < keys.options.length; ++i) {
|
for (var i = 0; i < keys.options.length; ++i) {
|
||||||
if (keys.options[i].value == key) {
|
if (keys.options[i].value == new_key) {
|
||||||
break;
|
return;
|
||||||
};
|
};
|
||||||
if (keys.options[i].value > key) {
|
if (keys.options[i].value > new_key) {
|
||||||
var option = document.createElement('option');
|
addKey(new_key, new_value, i);
|
||||||
option.text = key;
|
return;
|
||||||
keys.options.add(option, i);
|
|
||||||
break;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
if (i == keys.options.length) {
|
// Sorts at the end
|
||||||
var option = document.createElement('option');
|
addKey(new_key, new_value, keys.options.length);
|
||||||
option.text = key;
|
|
||||||
keys.options.add(option);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
var debug = new cosmopolite.Client(callbacks);
|
var debug = new cosmopolite.Client(callbacks);
|
||||||
|
|
||||||
document.getElementById('set').addEventListener('click', function() {
|
document.getElementById('set').addEventListener('click', function() {
|
||||||
debug.setValue(
|
debug.setValue(keys.value, value.value);
|
||||||
document.getElementById('keys').value,
|
});
|
||||||
document.getElementById('value').value);
|
|
||||||
|
document.getElementById('add').addEventListener('click', function() {
|
||||||
|
var new_key = prompt('New key name:');
|
||||||
|
if (new_key === null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
debug.setValue(new_key, '');
|
||||||
|
selectKey(new_key);
|
||||||
});
|
});
|
||||||
|
|
||||||
document.getElementById('keys').addEventListener('change', function() {
|
document.getElementById('keys').addEventListener('change', function() {
|
||||||
if (this.value == '(add new)') {
|
value.value = debug.getValue(keys.value);
|
||||||
var new_key = prompt('New key name:');
|
|
||||||
if (new_key === null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
callbacks['onStateChange'](new_key, '');
|
|
||||||
this.value = new_key;
|
|
||||||
document.getElementById('value').value = '';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var value = document.getElementById('value');
|
|
||||||
value.value = debug.getValue(this.value);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Reference in New Issue
Block a user