Add interface for creating and viewing bots

We really should not be storing bot API keys in the DOM and should
require some sort of additional authentication before showing them,
but this seems reasonable for a first pass.

(imported from commit c7d75aa52e21894bf53917457e771c18de38bbcc)
This commit is contained in:
Zev Benjamin 2013-05-02 18:29:52 -04:00
parent bd9e97c839
commit 7b3f5ed14c
6 changed files with 142 additions and 1 deletions

View File

@ -304,6 +304,7 @@ PIPELINE_JS = {
'js/timerender.js',
'js/tutorial.js',
'js/templates.js',
'js/settings.js'
],
'output_filename': 'min/app.js'
},

View File

@ -21,6 +21,7 @@
<link href="/static/favicon.ico?v=2" rel="shortcut icon">
{# We need to import jQuery before Bootstrap #}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script src="https://ajax.aspnetcdn.com/ajax/jquery.validate/1.9/jquery.validate.min.js"></script>
<script src="/static/third/bootstrap/js/bootstrap.min.js"></script>
{% compressed_js 'common' %}
{% block customhead %}

View File

@ -6,6 +6,5 @@
{% block customhead %}
{{ block.super }}
<script src="https://ajax.aspnetcdn.com/ajax/jquery.validate/1.9/jquery.validate.min.js"></script>
{% compressed_js 'signup' %}
{% endblock %}

View File

@ -153,6 +153,36 @@
<hr class="settings_separator" />
<h2>Your bots</h2>
<form id="create_bot_form">
<div id="bot_table_error" class="alert alert-error hide"></div>
<table class="table table-condensed table-striped" id="bots_table">
<tbody>
<tr>
<th class="bot_name_header">Name</th><th>Username</th><th class="bot_api_key_header">API key</th>
</tr>
<tr id="create_bot_row">
<td>
<div class="create_bot_control">
<input type="text" name="bot_name" id="create_bot_name" class="required"
maxlength=100 placeholder="Bot name" value="" />
</div>
<div><label for="create_bot_name" generated="true" class="text-error"></label></div>
<td>
<div class="create_bot_control">
<input type="text" name="bot_short_name" id="create_bot_short_name" class="required bot_local_part"
placeholder="Bot username" value="" />-bot@{{ user_profile.realm.domain }}
</div>
<div><label for="create_bot_short_name" generated="true" class="text-error"></label></div>
<td><input type="submit" class="btn btn-primary"
id="create_bot_button" value="Create Bot" />
</tr>
</tbody>
</form>
</table>
<hr class="settings_separator" />
</div>
<div class="span7">

View File

@ -0,0 +1,71 @@
var settings = (function () {
var exports = {};
function add_bot_row(name, email, api_key) {
var row = $('<tr></tr>').append($('<td>').text(name),
$('<td>').text(email),
$('<td class="api_key">').text(api_key));
$('#create_bot_row').after(row);
}
function is_local_part(value, element) {
// Adapted from Django's EmailValidator
return this.optional(element) || /^[\-!#$%&'*+\/=?\^_`{}|~0-9A-Z]+(\.[\-!#$%&'*+\/=?\^_`{}|~0-9A-Z]+)*$/i.test(value);
}
$(function () {
$.ajax({
type: 'POST',
url: '/json/get_bots',
dataType: 'json',
success: function (data) {
$('#bot_table_error').hide();
var bots = data.bots.sort(function (a, b) {
return b.full_name.localeCompare(a.full_name);
});
$.each(bots, function (idx, elem) {
add_bot_row(elem.full_name, elem.username, elem.api_key);
});
},
error: function (xhr, error_type, xhn) {
$('#bot_table_error').text("Could not fetch bots list").show();
}
});
$.validator.addMethod("bot_local_part",
function (value, element) {
return is_local_part.call(this, value + "-bot", element);
},
"Please only use characters that are valid in an email address");
$('#create_bot_form').validate({
errorClass: 'text-error',
success: function () {
$('#bot_table_error').hide();
},
submitHandler: function () {
var name = $('#create_bot_name').val();
var short_name = $('#create_bot_short_name').val();
$.ajax({
type: 'POST',
url: '/json/create_bot',
dataType: 'json',
data: {full_name: name, short_name: short_name},
success: function (data) {
$('#bot_table_error').hide();
$('#create_bot_name').val('');
$('#create_bot_short_name').val('');
add_bot_row(name, short_name + "-bot@" + page_params.domain, data.api_key);
},
error: function (xhr, error_type, exn) {
$('#bot_table_error').text(JSON.parse(xhr.responseText).msg).show();
}
});
}
});
});
}());

View File

@ -1224,3 +1224,42 @@ li.expanded_subject {
#stream_filters .inactive_stream {
opacity: .5;
}
#bots_table {
table-layout: fixed;
width: 100%;
font-size: 90%;
}
#bots_table td {
overflow: hidden;
}
#create_bot_name {
width: 80%;
}
#create_bot_short_name {
width: 40%;
}
.bot_name_header {
width: 12em;
}
.bot_api_key_header {
width: 18em;
}
.api_key {
font-family: monospace;
font-size: 85%;
}
.create_bot_control {
vertical-align: middle;
}
#create_bot_row input {
margin: 0;
}