Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions rest_framework_docs/api_endpoint.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import json
import inspect
from django.contrib.admindocs.views import simplify_regex

Expand All @@ -15,6 +16,8 @@ def __init__(self, pattern, parent_pattern=None):
# self.view_name = pattern.callback.__name__
self.errors = None
self.fields = self.__get_serializer_fields__()
self.fields_json = self.__get_serializer_fields_json__()
self.permissions = self.__get_permissions_class__()

def __get_path__(self, parent_pattern):
if parent_pattern:
Expand All @@ -27,6 +30,10 @@ def __get_allowed_methods__(self):
def __get_docstring__(self):
return inspect.getdoc(self.callback)

def __get_permissions_class__(self):
for perm_class in self.pattern.callback.cls.permission_classes:
return perm_class.__name__

def __get_serializer_fields__(self):
fields = []

Expand All @@ -47,3 +54,8 @@ def __get_serializer_fields__(self):
# Show more attibutes of `field`?

return fields

def __get_serializer_fields_json__(self):
# FIXME:
# Return JSON or not?
return json.dumps(self.fields)
1 change: 1 addition & 0 deletions rest_framework_docs/static/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"build-bootstrap-fonts": "cp -r node_modules/bootstrap/fonts rest_framework_docs/",
"build-less": "lessc --clean-css rest_framework_docs/less/style.less rest_framework_docs/css/style.css",
"watch-less": "watch 'npm run build-less' rest_framework_docs/less/",
"watch": "npm run watch-less",
"build": "npm run build-font-awesome && npm run build-bootstrap-fonts && npm run build-less",
"start": "npm run build && npm run watch-less",
"test": "echo \"Error: no test specified\" && exit 1"
Expand Down

Large diffs are not rendered by default.

203 changes: 203 additions & 0 deletions rest_framework_docs/static/rest_framework_docs/js/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
var jsonPP = {
// Thanks to http://jsfiddle.net/unlsj/
replacer: function (match, pIndent, pKey, pVal, pEnd) {
var key = '<span class=json-key>';
var val = '<span class=json-value>';
var str = '<span class=json-string>';
var r = pIndent || '';
if (pKey)
r = r + key + pKey.replace(/[": ]/g, '') + '</span>: ';
if (pVal)
r = r + (pVal[0] == '"' ? str : val) + pVal + '</span>';
return r + (pEnd || '');
},
prettyPrint: function (obj) {
var jsonLine = /^( *)("[\w]+": )?("[^"]*"|[\w.+-]*)?([,[{])?$/mg;
return JSON.stringify(obj, null, 3)
.replace(/&/g, '&amp;').replace(/\\"/g, '&quot;')
.replace(/</g, '&lt;').replace(/>/g, '&gt;')
.replace(jsonLine, this.replacer);
}
};

$( document ).ready(function() {

var token = null;

var resetForm = function () {
$('#methods').empty();
$('#fields').empty();
};

var cleanResponse = function () {
$('#responseStatusCode').removeClass(function (index, css) {
return (css.match (/(^|\s)status-code-\S+/g) || []).join(' ');
});
$('#responseStatusText').hide();
$('#responseStatusText').find('span').text('');
$('#responseData').html('');
$('#saveTokenButton').hide();
$('#responseData').parent().hide();
};

var setResponse = function (response) {
var statusCodeFirstChar = String(response.status).charAt(0);

$('#responseStatusCode').text(response.status);
$('#responseStatusCode').addClass('status-code-' + statusCodeFirstChar);

$('#responseStatusText').show();
$('#responseStatusText').find('span').text(response.statusText.toLowerCase());

$('#responseData').parent().show();
$('#responseData').html(jsonPP.prettyPrint(response.responseJSON));

// Setup token store
if (response.responseJSON.hasOwnProperty('token')) {
// If the JSON has a token, show the button to save it
$('#saveTokenButton').show();

$('#saveTokenButton').on('click', function () {
// Save the token to the window
token = response.responseJSON['token'];
});
}
};

var getFormData = function () {
var data = {};

$( '#fields .form-group' ).each(function(){
var input = $(this).find( 'input' );
var name = input.attr( 'id' );
var value = input.val();
data[name] = value;
})

return data;
};

var makeRequest = function () {
// Clean the response
cleanResponse();

var url = $('#requestForm #urlInput').val();
var method = $("#methods").find( ".active" ).text();
var data = getFormData();

var token = $('#headers #authorization').val();
var headers = token ? {
'Authorization' : token
} : null;

$.ajax({
url: url,
method: method,
headers: headers,
context: document.body,
data: data
}).always(function(data, textStatus, jqXHR) {

if (textStatus != 'success') {
jqXHR = data;
}
setResponse(jqXHR);
});
};

var _setupMethods = function (methods) {
// List Methods (Radio Buttons)
// FIXME: Use regex - convert to JSON
var methods = methods.replace("[", "").replace("]", "").replace(/'/g, "").replace(/\s/g, "").split(',');
$.each( methods, function( i, method ) {
var methodClass = "btn btn-sm method " + method.toLowerCase();
$('#methods').append("<button type='button' class='" + methodClass + "'>" + method + "</button>");
});

// Make the first method active
$('#methods').children(".btn").first().addClass( 'active' );

$("#methods .method").on('click', function (evt) {
// Remove 'active' from all methods
$("#methods .method").removeClass( 'active' );
// Add 'active' to the clicked button
$(this).addClass( 'active' );
_toggleFields();
});
};

var _setupAuthorization = function (permissions) {
if (permissions === 'None' || permissions === 'AllowAny') {
$('#headers').hide();
} else {
$('#headers').show();
// Check if token exists
if (token) {
$('#headers #authorization').val('Token ' + token);
}
}
};

var _toggleFields = function () {
// Show/Hide Data depending on method type
var method = $("#methods").find( ".active" ).text();
if (method === 'GET' || method === 'OPTIONS') {
$('#headerData').hide();
$('#headers #authorization').val();
$('#fields').hide();
} else {
$('#headerData').show();
$('#fields').show();
}
};

var _setupFields = function (fields) {
_toggleFields();

$.each( fields, function( i, field ) {
var label = field.name.replace('_', ' ');
$('#fields').append("" +
'<div class="form-group">' +
'<label for="field' + field.name + '" class="col-sm-4 control-label">' + label + '</label>' +
'<div class="col-sm-8">' +
'<input type="text" class="form-control input-sm" id="' + field.name + '" placeholder="' + field.type + '">' +
'</div>' +
'</div>' +
"");
});
};

var setupForm = function (data) {
// Reset Form - Remove Methods & Fields
resetForm();
cleanResponse();

$('#urlInput').val(data.path);

_setupMethods(data.methods);
_setupAuthorization(data.permissions);
_setupFields(data.fields);

$('#requestForm').submit(function (e) {
// Prevent Submit
e.preventDefault();

// Make Request
makeRequest(data);
});
};

$('.plug').bind('click', function(evt) {
// Prevent the accordion from collapsing
evt.stopPropagation();
evt.preventDefault();

// Open Modal
$('#liveAPIModal').modal('toggle');

// Setup the form
var data = $(this).data();
setupForm(data);
});

});
122 changes: 122 additions & 0 deletions rest_framework_docs/static/rest_framework_docs/less/style.less
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,22 @@
/* @end Colours */


/* @group Mixins */

// Border Radius (Same Corners)
.BorderRadius(@radius: 5px) {
-webkit-border-radius: @radius;
-moz-border-radius: @radius;
border-radius: @radius;

-moz-background-clip: padding;
-webkit-background-clip: padding-box;
background-clip: padding-box;
}

/* @end Mixins */


/* @group Misc */

body {
Expand All @@ -40,6 +56,11 @@ body {
margin-left: 5px;
}

.btn:focus,
.btn:active {
outline: none !important;
}

/* @end Misc */


Expand Down Expand Up @@ -85,6 +106,16 @@ body {
&.put { background-color: @PatchColor; }
&.delete { background-color: @DeleteColor; }
&.options { background-color: @OptionsColor; }

&.plug {
color: @brand-primary;
border: 1px solid @brand-primary;
.BorderRadius(50%);
font-size: 14px;
width: 30px;
height: 29px;
margin-left: 10px;
}
}
}
}
Expand Down Expand Up @@ -136,6 +167,97 @@ body {
/* @end Footer */


/* @group Modal API */

.modal {

h3 {
margin-top: 0;
}

.control-label {
padding-top: 7px;
}

.request {

.section-title {
background-color: @gray-lighter;
text-align: center;
padding: 5px;
.BorderRadius(3px);
}

.methods {

.method {
color: #FFF;
background-color: @gray-light;
border-left: 1px solid @gray;

&:first-child {
border-left: 0;
}

&.get.active { background-color: @GetColor; }
&.post.active { background-color: @PostColor; }
&.patch.active { background-color: @PutColor; }
&.put.active { background-color: @PatchColor; }
&.delete.active { background-color: @DeleteColor; }
&.options.active { background-color: @OptionsColor; }
}
}

.fields {
label {
text-transform: capitalize;
}
}
}

.response {
.status-code {
font-weight: 300;

&.status-code-1 { background-color: @brand-info; }
&.status-code-2 { background-color: @brand-success; }
&.status-code-3 { background-color: @brand-warning; }
&.status-code-4 { background-color: @brand-danger; }
&.status-code-5 { background-color: @brand-primary; }
}

.status-text {
text-transform: capitalize;
}

pre {
font-size: 12px;
margin-top: 20px;
}
}
}


/* @end Modal API */


/* @group jQuery / JSON View */

.json-key {
color: brown;
}

.json-value {
color: navy;
}

.json-string {
color: olive;
}

/* @end jQuery / JSON View */


/* @group Github Ribbon - SVG */

.github-corner:hover .octo-arm {
Expand Down
Loading