Merge pull request #407 from jonmchan/ParameterTypeSupport

This commit is contained in:
William DURAND 2014-06-25 10:25:59 +02:00
commit 8ddade0e30
4 changed files with 143 additions and 20 deletions

View File

@ -18,27 +18,27 @@ namespace Nelmio\ApiDocBundle;
*/ */
class DataTypes class DataTypes
{ {
const INTEGER = 'integer'; const INTEGER = 'integer';
const FLOAT = 'float'; const FLOAT = 'float';
const STRING = 'string'; const STRING = 'string';
const BOOLEAN = 'boolean'; const BOOLEAN = 'boolean';
const FILE = 'file'; const FILE = 'file';
const ENUM = 'choice'; const ENUM = 'choice';
const COLLECTION = 'collection'; const COLLECTION = 'collection';
const MODEL = 'model'; const MODEL = 'model';
const DATE = 'date'; const DATE = 'date';
const DATETIME = 'datetime'; const DATETIME = 'datetime';
const TIME = 'time'; const TIME = 'time';
/** /**
* Returns true if the supplied `actualType` value is considered a primitive type. Returns false, otherwise. * Returns true if the supplied `actualType` value is considered a primitive type. Returns false, otherwise.

View File

@ -46,6 +46,7 @@ class FormTypeParser implements ParserInterface
'textarea' => DataTypes::STRING, 'textarea' => DataTypes::STRING,
'country' => DataTypes::STRING, 'country' => DataTypes::STRING,
'choice' => DataTypes::ENUM, 'choice' => DataTypes::ENUM,
'file' => DataTypes::FILE,
); );
public function __construct(FormFactoryInterface $formFactory) public function __construct(FormFactoryInterface $formFactory)

View File

@ -101,6 +101,39 @@
}); });
{% if enableSandbox %} {% if enableSandbox %}
var setParameterType = function ($context,setType) {
// no 2nd argument, use default from parameters
if (typeof setType == "undefined") {
setType = $context.parent().attr("data-dataType");
$context.val(setType);
}
$context.parent().find('.value').remove();
var placeholder = "";
if ($context.parent().attr("data-dataType") != "" && typeof $context.parent().attr("data-dataType") != "undefined") {
placeholder += "[" + $context.parent().attr("data-dataType") + "] ";
}
if ($context.parent().attr("data-format") != "" && typeof $context.parent().attr("data-format") != "undefined") {
placeholder += $context.parent().attr("data-dataType");
}
if ($context.parent().attr("data-description") != "" && typeof $context.parent().attr("data-description") != "undefined") {
placeholder += $context.parent().attr("data-description");
} else {
placeholder += "Value";
}
switch(setType) {
case "boolean":
$('<select class="value"><option value=""></option><option value="1">True</option><option value="0">False</option></select>').insertAfter($context);
break;
case "file":
$('<input type="file" class="value" placeholder="'+ placeholder +'">').insertAfter($context);
break;
default:
$('<input type="text" class="value" placeholder="'+ placeholder +'">').insertAfter($context);
}
};
var toggleButtonText = function ($btn) { var toggleButtonText = function ($btn) {
if ($btn.text() === 'Default') { if ($btn.text() === 'Default') {
$btn.text('Raw'); $btn.text('Raw');
@ -221,6 +254,7 @@
method = $(this).attr('method'), method = $(this).attr('method'),
self = this, self = this,
params = {}, params = {},
formData = new FormData(),
headers = {}, headers = {},
content = $(this).find('textarea.content').val(), content = $(this).find('textarea.content').val(),
result_container = $('.result', $(this).parent()); result_container = $('.result', $(this).parent());
@ -235,6 +269,7 @@
var requestFormatMethod = '{{ requestFormatMethod }}'; var requestFormatMethod = '{{ requestFormatMethod }}';
if (requestFormatMethod == 'format_param') { if (requestFormatMethod == 'format_param') {
params['_format'] = $('#request_format option:selected').text(); params['_format'] = $('#request_format option:selected').text();
formData.append('_format',$('#request_format option:selected').text());
} else if (requestFormatMethod == 'accept_header') { } else if (requestFormatMethod == 'accept_header') {
headers['Accept'] = $('#request_format').val(); headers['Accept'] = $('#request_format').val();
} }
@ -246,6 +281,37 @@
headers['Content-type'] = 'application/'+bodyFormat; headers['Content-type'] = 'application/'+bodyFormat;
} }
var hasFileTypes = false;
$('.parameters .tuple_type', $(this)).each(function() {
if ($(this).val() == 'file') {
hasFileTypes = true;
}
});
if (hasFileTypes && method != 'POST') {
alert("Sorry, you can only submit files via POST.");
return false;
}
if (hasFileTypes) {
// retrieve all the parameters to send for file upload
$('.parameters .tuple', $(this)).each(function() {
var key, value;
key = $('.key', $(this)).val();
if ($('.value', $(this)).attr('type') === 'file' ) {
value = $('.value', $(this)).prop('files')[0];
} else {
value = $('.value', $(this)).val();
}
if (value) {
formData.append(key,value);
}
});
}
// retrieve all the parameters to send // retrieve all the parameters to send
$('.parameters .tuple', $(this)).each(function() { $('.parameters .tuple', $(this)).each(function() {
var key, value; var key, value;
@ -258,6 +324,10 @@
} }
}); });
// retrieve the additional headers to send // retrieve the additional headers to send
$('.headers .tuple', $(this)).each(function() { $('.headers .tuple', $(this)).each(function() {
var key, value; var key, value;
@ -279,7 +349,7 @@
} }
}; };
// disable all the fiels and buttons // disable all the fields and buttons
$('input, button', $(this)).attr('disabled', 'disabled'); $('input, button', $(this)).attr('disabled', 'disabled');
// append the query authentication // append the query authentication
@ -307,9 +377,7 @@
body = params; body = params;
} }
var data = content.length ? content : body; var data = content.length ? content : body;
var ajaxOptions = {
// and trigger the API call
$.ajax({
url: endpoint + url, url: endpoint + url,
type: method, type: method,
data: data, data: data,
@ -328,7 +396,18 @@
// and enable them back // and enable them back
$('input:not(.content-type), button', $(self)).removeAttr('disabled'); $('input:not(.content-type), button', $(self)).removeAttr('disabled');
} }
}); };
// overrides body format to send data properly
if (hasFileTypes) {
ajaxOptions.data = formData;
ajaxOptions.processData = false;
ajaxOptions.contentType = false;
delete(ajaxOptions.headers);
}
// and trigger the API call
$.ajax(ajaxOptions);
return false; return false;
}); });
@ -369,8 +448,30 @@
e.preventDefault(); e.preventDefault();
}); });
$('.pane.sandbox').on('click', '.add', function() {
var html = $(this).parents('.pane').find('.tuple_template').html(); // sets the correct parameter type on load
$('.pane.sandbox .tuple_type').each(function() {
setParameterType($(this));
});
// handles parameter type change
$('.pane.sandbox').on('change', '.tuple_type', function() {
setParameterType($(this),$(this).val());
});
$('.pane.sandbox').on('click', '.add_parameter', function() {
var html = $(this).parents('.pane').find('.parameters_tuple_template').html();
$(this).before(html);
return false;
});
$('.pane.sandbox').on('click', '.add_header', function() {
var html = $(this).parents('.pane').find('.headers_tuple_template').html();
$(this).before(html); $(this).before(html);

View File

@ -228,14 +228,20 @@
<h4>Parameters</h4> <h4>Parameters</h4>
{% for name, infos in data.parameters %} {% for name, infos in data.parameters %}
{% if not infos.readonly %} {% if not infos.readonly %}
<p class="tuple"> <p class="tuple" data-dataType="{% if infos.dataType %}{{ infos.dataType }}{% endif %}" data-format="{% if infos.format %}{{ infos.format }}{% endif %}" data-description="{% if infos.description %}{{ infos.description }}{% endif %}">
<input type="text" class="key" value="{{ name }}" placeholder="Key" /> <input type="text" class="key" value="{{ name }}" placeholder="Key" />
<span>=</span> <span>=</span>
<select class="tuple_type">
<option value="">Type</option>
<option value="string">String</option>
<option value="boolean">Boolean</option>
<option value="file">File</option>
</select>
<input type="text" class="value" placeholder="{% if infos.dataType %}[{{ infos.dataType }}] {% endif %}{% if infos.format %}{{ infos.format }}{% endif %}{% if infos.description %}{{ infos.description }}{% else %}Value{% endif %}" {% if infos.default is defined %} value="{{ infos.default }}" {% endif %}/> <span class="remove">-</span> <input type="text" class="value" placeholder="{% if infos.dataType %}[{{ infos.dataType }}] {% endif %}{% if infos.format %}{{ infos.format }}{% endif %}{% if infos.description %}{{ infos.description }}{% else %}Value{% endif %}" {% if infos.default is defined %} value="{{ infos.default }}" {% endif %}/> <span class="remove">-</span>
</p> </p>
{% endif %} {% endif %}
{% endfor %} {% endfor %}
<button type="button" class="add">New parameter</button> <button type="button" class="add_parameter">New parameter</button>
{% endif %} {% endif %}
</fieldset> </fieldset>
@ -257,7 +263,7 @@
<input type="text" class="value" placeholder="Value" /> <span class="remove">-</span> <input type="text" class="value" placeholder="Value" /> <span class="remove">-</span>
</p> </p>
<button type="button" class="add">New header</button> <button type="button" class="add_header">New header</button>
</fieldset> </fieldset>
<fieldset class="request-content"> <fieldset class="request-content">
@ -282,10 +288,25 @@
<p class="tuple"> <p class="tuple">
<input type="text" class="key" placeholder="Key" /> <input type="text" class="key" placeholder="Key" />
<span>=</span> <span>=</span>
<select class="tuple_type">
<option value="">Type</option>
<option value="string">String</option>
<option value="boolean">Boolean</option>
<option value="file">File</option>
</select>
<input type="text" class="value" placeholder="Value" /> <span class="remove">-</span> <input type="text" class="value" placeholder="Value" /> <span class="remove">-</span>
</p> </p>
</script> </script>
<script type="text/x-tmpl" class="headers_tuple_template">
<p class="tuple">
<input type="text" class="key" placeholder="Key" />
<span>=</span>
<input type="text" class="value" placeholder="Value" /> <span class="remove">-</span>
</p>
</script>
<div class="result"> <div class="result">
<h4>Request URL</h4> <h4>Request URL</h4>
<pre class="url"></pre> <pre class="url"></pre>