From 2287201a1a32ce2277c31870b26b764fb384bd97 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Wed, 1 Mar 2017 15:40:31 +0000 Subject: [PATCH] Move API explorer javascript into static file --- .../static/rest_framework/docs/js/api.js | 243 +++++++++++++++++ .../templates/rest_framework/docs/index.html | 245 +----------------- 2 files changed, 244 insertions(+), 244 deletions(-) create mode 100644 rest_framework/static/rest_framework/docs/js/api.js diff --git a/rest_framework/static/rest_framework/docs/js/api.js b/rest_framework/static/rest_framework/docs/js/api.js new file mode 100644 index 000000000..49f14a36e --- /dev/null +++ b/rest_framework/static/rest_framework/docs/js/api.js @@ -0,0 +1,243 @@ +function normalizeHTTPHeader(str) { + return (str.charAt(0).toUpperCase() + str.substring(1)) + .replace( /-(.)/g, function($1) { return $1.toUpperCase(); }) + .replace( /(Www)/g, function($1) { return 'WWW'; }) + .replace( /(Xss)/g, function($1) { return 'XSS'; }) + .replace( /(Md5)/g, function($1) { return 'MD5'; }) +} + +function getCookie(name) { + var cookieValue = null; + if (document.cookie && document.cookie !== '') { + var cookies = document.cookie.split(';'); + for (var i = 0; i < cookies.length; i++) { + var cookie = jQuery.trim(cookies[i]); + // Does this cookie string begin with the name we want? + if (cookie.substring(0, name.length + 1) === (name + '=')) { + cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); + break; + } + } + } + return cookieValue; +} + +let responseDisplay = 'data'; +const coreapi = window.coreapi +const schema = window.schema + +// Language Control +$('#language-control li').click(function (event) { + event.preventDefault(); + const languageMenuItem = $(this).find('a'); + var language = languageMenuItem.data("language") + + var languageControls = $(this).closest('ul').find('li'); + languageControls.find('a').not('[data-language="' + language +'"]').parent().removeClass("active") + languageControls.find('a').filter('[data-language="' + language +'"]').parent().addClass("active") + + $('#selected-language').text(language) + + var codeBlocks = $('pre.highlight') + codeBlocks.not('[data-language="' + language +'"]').addClass("hide") + codeBlocks.filter('[data-language="' + language +'"]').removeClass("hide") +}) + +// API Explorer +$('form.api-interaction').submit(function(event) { + event.preventDefault(); + + const form = $(this).closest("form"); + const key = form.data("key"); + var params = {}; + + const formData = new FormData(form.get()[0]); + for (var [paramKey, paramValue] of formData.entries()) { + var elem = form.find("[name=" + paramKey + "]") + var dataType = elem.data('type') || 'string' + var dataLocation = elem.data('location') + + if (dataType === 'integer' && paramValue) { + paramValue = parseInt(paramValue) + } else if (dataType === 'number' && paramValue) { + paramValue = parseFloat(paramValue) + } else if (dataType === 'boolean' && paramValue) { + paramValue = { + 'true': true, + 'false': false + }[paramValue.toLowerCase()] + } else if (dataType === 'array' && paramValue) { + paramValue = JSON.parse(paramValue) + } + + if (dataLocation === 'query' && !paramValue) { + continue + } + params[paramKey] = paramValue + } + + form.find(":checkbox").each(function( index ) { + var name = $(this).attr("name"); + if (!params.hasOwnProperty(name)) { + params[name] = false + } + }) + + function requestCallback(request) { + // Fill in the "GET /foo/" display. + let parser = document.createElement('a'); + parser.href = request.url; + const method = request.options.method + const path = parser.pathname + parser.hash + parser.search + + form.find(".request-method").text(method) + form.find(".request-url").text(path) + } + + function responseCallback(response, responseText) { + // Display the 'Data'/'Raw' control. + form.closest(".modal-content").find(".toggle-view").removeClass("hide") + + // Fill in the "200 OK" display. + form.find(".response-status-code").removeClass("label-success").removeClass("label-danger") + if (response.ok) { + form.find(".response-status-code").addClass("label-success") + } else { + form.find(".response-status-code").addClass("label-danger") + } + form.find(".response-status-code").text(response.status) + form.find(".meta").removeClass("hide") + + // Fill in the Raw HTTP response display. + var panelText = 'HTTP/1.1 ' + response.status + ' ' + response.statusText + '\n'; + response.headers.forEach((header, key) => { + panelText += normalizeHTTPHeader(key) + ': ' + header + '\n' + }) + if (responseText) { + panelText += '\n' + responseText + } + form.find(".response-raw-response").text(panelText) + } + + // Instantiate a client to make the outgoing request. + let options = { + requestCallback: requestCallback, + responseCallback: responseCallback, + } + + // Setup authentication options. + if (window.auth && window.auth.type === 'token') { + // Header authentication + options.headers = { + 'Authorization': window.auth.value + } + } else if (window.auth && window.auth.type === 'basic') { + // Basic authentication + const token = window.auth.username + ':' + window.auth.password + const hash = window.btoa(token) + options.headers = { + 'Authorization': 'Basic ' + hash + } + } else if (window.auth && window.auth.type === 'session') { + // Session authentication + options.csrf = { + 'X-CSRFToken': getCookie('csrftoken') + } + } + + const client = new coreapi.Client(options) + + client.action(schema, key, params).then(function (data) { + var response = JSON.stringify(data, null, 2); + form.find(".request-awaiting").addClass("hide") + form.find(".response-raw").addClass("hide") + form.find(".response-data").addClass("hide") + form.find(".response-data").text('') + form.find(".response-data").jsonView(response) + + if (responseDisplay === 'data') { + form.find(".response-data").removeClass("hide") + } else { + form.find(".response-raw").removeClass("hide") + } + }).catch(function (error) { + var response = JSON.stringify(error.content, null, 2); + form.find(".request-awaiting").addClass("hide") + form.find(".response-raw").addClass("hide") + form.find(".response-data").addClass("hide") + form.find(".response-data").text('') + form.find(".response-data").jsonView(response) + + if (responseDisplay === 'data') { + form.find(".response-data").removeClass("hide") + } else { + form.find(".response-raw").removeClass("hide") + } + }) +}); + +// 'Data'/'Raw' control +$('.toggle-view button').click(function() { + responseDisplay = $(this).data("display-toggle"); + $(this).removeClass("btn-default").addClass('btn-info').siblings().removeClass('btn-info'); + if (responseDisplay === 'raw') { + $(this).closest(".modal-content").find(".response-raw").removeClass("hide"); + $(this).closest(".modal-content").find(".response-data").addClass("hide"); + } else { + $(this).closest(".modal-content").find(".response-data").removeClass("hide"); + $(this).closest(".modal-content").find(".response-raw").addClass("hide"); + } +}); + +// Authentication: none +$('#auth-control').find("[data-auth='none']").click(function (event) { + event.preventDefault(); + window.auth = null; + $('#selected-authentication').text('none'); + $('#auth-control').children().removeClass('active'); + $('#auth-control').find("[data-auth='none']").addClass('active'); +}) + +// Authentication: token +$('form.authentication-token-form').submit(function(event) { + event.preventDefault(); + const form = $(this).closest("form"); + const value = form.find('input').val(); + window.auth = { + 'type': 'token', + 'value': value, + }; + $('#selected-authentication').text('header'); + $('#auth-control').children().removeClass('active'); + $('#auth-control').find("[data-auth='token']").addClass('active'); + $('#auth_token_modal').modal('hide'); +}); + +// Authentication: basic +$('form.authentication-basic-form').submit(function(event) { + event.preventDefault(); + const form = $(this).closest("form"); + const username = form.find('input#username').val(); + const password = form.find('input#password').val(); + window.auth = { + 'type': 'basic', + 'username': username, + 'password': password, + }; + $('#selected-authentication').text('basic'); + $('#auth-control').children().removeClass('active'); + $('#auth-control').find("[data-auth='basic']").addClass('active'); + $('#auth_basic_modal').modal('hide'); +}); + +// Authentication: session +$('form.authentication-session-form').submit(function(event) { + event.preventDefault(); + window.auth = { + 'type': 'session', + }; + $('#selected-authentication').text('session'); + $('#auth-control').children().removeClass('active'); + $('#auth-control').find("[data-auth='session']").addClass('active'); + $('#auth_session_modal').modal('hide'); +}); diff --git a/rest_framework/templates/rest_framework/docs/index.html b/rest_framework/templates/rest_framework/docs/index.html index c1e1f8447..2eef1d0c7 100644 --- a/rest_framework/templates/rest_framework/docs/index.html +++ b/rest_framework/templates/rest_framework/docs/index.html @@ -41,35 +41,8 @@ +