Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding autocomplete to params using x-data-threescale-name field #1991

Merged
merged 3 commits into from
Jun 26, 2020
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
77 changes: 77 additions & 0 deletions app/javascript/packs/OAS3Autocomplete.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// @flow

import { fetchData } from 'utilities/utils'
import type {
AccountData,
Param,
ResponseBody,
SwaggerResponse
} from 'Types/SwaggerTypes'

const X_DATA_ATTRIBUTE = 'x-data-threescale-name'

const X_DATA_PARAMS_DESCRIPTIONS = {
user_keys: 'First user key from latest 5 applications',
app_ids: 'Latest 5 applications (across all accounts and services)',
app_keys: 'First application key from the latest five applications'
}

const addAutocompleteToParam = (param: Param, accountData: AccountData): Param => {
const xDataKey = param[X_DATA_ATTRIBUTE]
const autocompleteData = accountData[xDataKey]
const paramHasAutocompleteData = autocompleteData && autocompleteData.length > 0 &&
autocompleteData.every(param => param.name !== '')

return paramHasAutocompleteData
? {
...param,
examples: autocompleteData.reduce((examples, item) => (
[...examples, {summary: item.name, value: item.value}]
), [{summary: X_DATA_PARAMS_DESCRIPTIONS[xDataKey], value: '-'}])
}
: param
}

const updateResponseBody = (response: SwaggerResponse, accountData: AccountData): ResponseBody => (
{
...response.body,
paths: Object.keys(response.body.paths).reduce(
(paths, key) => {
const pathParameters = response.body.paths[key].get.parameters
if (pathParameters) {
paths[key] = {
get: {
...response.body.paths[key].get,
parameters: pathParameters.map(param => {
return X_DATA_ATTRIBUTE in param ? addAutocompleteToParam(param, accountData) : param
})
}
}
}
return paths
}, {})
}
)

// response.body.method is not present when fetching the spec,
// is present when doing a request to one of the paths
const isSpecFetched = (response: SwaggerResponse): boolean => !!response.body.method

export const autocompleteOAS3 = async (response: SwaggerResponse, accountDataUrl: string): SwaggerResponse => (
isSpecFetched(response)
? response
: fetchData(accountDataUrl)
.then(data => {
const accountData = data.results
if (!accountData) {
return response
}
const body = updateResponseBody(response, accountData)
return {
...response,
body,
data: JSON.stringify(body),
text: JSON.stringify(body)
}
})
)
11 changes: 9 additions & 2 deletions app/javascript/packs/active_docs.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
// We can define the 3scale plugins here and export the modified bundle
import SwaggerUI from 'swagger-ui'
import { autocompleteOAS3 } from './OAS3Autocomplete'
import 'swagger-ui/dist/swagger-ui.css'

import 'ActiveDocs/swagger-ui-3-patch.scss'

window.SwaggerUI = SwaggerUI
const accountDataUrl = '/api_docs/account_data.json'

window.SwaggerUI = (args) => {
SwaggerUI({
...args,
responseInterceptor: response => autocompleteOAS3(response, accountDataUrl)
})
}
16 changes: 13 additions & 3 deletions app/javascript/packs/service_active_docs.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
import { ActiveDocsSpecWrapper as ActiveDocsSpec } from 'ActiveDocs/components/ActiveDocsSpec'
import SwaggerUI from 'swagger-ui'
import { autocompleteOAS3 } from './OAS3Autocomplete'
import 'swagger-ui/dist/swagger-ui.css'

document.addEventListener('DOMContentLoaded', () => {
const containerId = 'swagger-ui-container'
const { url } = document.getElementById(containerId).dataset
const DATA_URL = 'p/admin/api_docs/account_data.json'
const { url, baseUrl } = document.getElementById(containerId).dataset
const accountDataUrl = `${baseUrl}${DATA_URL}`

ActiveDocsSpec({ url }, containerId)
const responseInterceptor = (response) => autocompleteOAS3(response, accountDataUrl)

SwaggerUI({
url,
dom_id: `#${containerId}`,
responseInterceptor
})
})
18 changes: 0 additions & 18 deletions app/javascript/src/ActiveDocs/components/ActiveDocsSpec.jsx

This file was deleted.

50 changes: 50 additions & 0 deletions app/javascript/src/Types/SwaggerTypes.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
export type Primitive = string | number | boolean

export type AccountData = {
[string]: Array<{ name: string, value: string }>
}

export type ParamArraySchema = {
type: 'array',
items: { type: Primitive }
}
export type ParamEnumSchema = {
enum: Array<Primitive>,
items: { type: Primitive }
}

export type Examples = Array<{
summary: string,
value: string
}>

export type Param = {
in: string,
name: string,
description?: string,
required?: boolean,
schema?: Primitive | ParamArraySchema | ParamEnumSchema,
examples?: Examples
}

export type ResponseBody = {
paths: {
[string]: {
parameters: Array<Param>,
[string]: string | {}
}
},
[string]: string | {}
}

export type SwaggerResponse = {
body: ResponseBody,
data: string,
headers: {},
obj: {},
ok: boolean,
status: number,
statusText: string,
text: string,
url: string
}
8 changes: 7 additions & 1 deletion app/views/admin/api_docs/base/swagger.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,13 @@

<div class="swagger-section">
<div id="message-bar" class="swagger-ui-wrap">&nbsp;</div>
<div id="swagger-ui-container" class="swagger-ui-wrap" data-url="<%= spec_url(@api_docs_service) %>"></div>
<div
id="swagger-ui-container"
class="swagger-ui-wrap"
data-url="<%= spec_url(@api_docs_service) %>"
data-base-url="<%= base_url %>"
>
</div>
</div>

<div class='apidocs-param-tips apidocs-signin-message' style='display:none;'>
Expand Down
22 changes: 0 additions & 22 deletions spec/javascripts/ActiveDocs/ActiveDocsSpec.jsx

This file was deleted.

11 changes: 0 additions & 11 deletions spec/javascripts/ActiveDocs/__snapshots__/Spec.spec.jsx.snap

This file was deleted.