Skip to content

Commit

Permalink
Display content types for responses correctly (#1790)
Browse files Browse the repository at this point in the history
* fix: display content types for responses correctly

* feat: enable other content types for responses

* chore: fix graphql query

* chore: show no content type if description is defined

* chore: add testcase for a different content type for responses

* chore: add changeset

* chore: fix indentation

* refactor: add safety checks

* chore: show content type only if description is not displayed

* refactor: rename prop
  • Loading branch information
timonrey authored Aug 16, 2023
1 parent fc2685e commit f9185c6
Show file tree
Hide file tree
Showing 8 changed files with 116 additions and 58 deletions.
6 changes: 6 additions & 0 deletions .changeset/witty-glasses-share.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@commercetools-docs/gatsby-transformer-raml': minor
'@commercetools-docs/gatsby-theme-api-docs': minor
---

Display the response content type correctly. It also enables support for other content types that are already supported in request bodies.
17 changes: 13 additions & 4 deletions api-specs/test/api.raml
Original file line number Diff line number Diff line change
Expand Up @@ -284,10 +284,11 @@ uses:
203:
description: ArrayTestType using 2 different custom example files
body:
type: arrays.ArrayTestType
examples:
custom1: !include examples/array-test-type-custom-1.json
custom2: !include examples/array-test-type-custom-2.json
application/x-www-form-urlencoded:
type: arrays.ArrayTestType
examples:
custom1: !include examples/array-test-type-custom-1.json
custom2: !include examples/array-test-type-custom-2.json

/description-with-urn-links:
post:
Expand Down Expand Up @@ -338,6 +339,14 @@ uses:
body:
application/x-www-form-urlencoded:
type: scalars.StringTestType
responses:
200:
body:
application/json:
type: scalars.StringTestType
201:
body:
type: date-test-type.DateTestType

/searchApiPattern:
get:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ const Container = styled.div`

const TitleWithAnchor = Markdown.withCopyToClipboard(Title);

function convertContentType(type) {
export function convertContentType(type) {
switch (type) {
case 'applicationjson':
return 'application/json';
Expand Down Expand Up @@ -67,7 +67,9 @@ const Method = ({
allUriParameters = allUriParameters.concat(method.uriParameters);
}

const contentType = [];
const requestContentType = [];
const responseContentType = [];

if (method.body) {
const findOutContentTypes = Object.keys(method.body).reduce(
(list, value) => {
Expand All @@ -76,13 +78,29 @@ const Method = ({
[]
);
findOutContentTypes.forEach((type) => {
contentType.push(convertContentType(type));
requestContentType.push(convertContentType(type));
});
}

if (method.responses) {
const findOutContentTypes = [];
method.responses.forEach((response) => {
response.body &&
Object.keys(response.body).forEach((key) => {
if (convertContentType(key) !== '' && response.body[key]) {
findOutContentTypes.push(key);
}
});
});

findOutContentTypes.forEach((type) => {
responseContentType.push(type);
});
}

const isStructuredDataType =
contentType.includes('application/json') ||
contentType.includes('application/x-www-form-urlencoded');
requestContentType.includes('application/json') ||
requestContentType.includes('application/x-www-form-urlencoded');

const methodColor = computeMethodColor(methodType.toLowerCase());

Expand Down Expand Up @@ -144,15 +162,15 @@ const Method = ({
method.body.applicationxwwwformurlencoded?.type
}
isStructuredDataType={isStructuredDataType}
contentType={contentType}
contentType={requestContentType}
/>
)}

{(!method.body || isStructuredDataType) && method.responses && (
<Responses
apiKey={apiKey}
responses={method.responses}
contentType={contentType}
contentType={responseContentType}
/>
)}
</SpacingsStack>
Expand All @@ -161,6 +179,7 @@ const Method = ({
apiKey={apiKey}
requestCodeExamples={method.codeExamples}
responses={method.responses}
contentType={responseContentType}
/>
)}
</SideBySide>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,8 @@ const RequestResponseExamples = (props) => {
const apiTypes = useApiTypes();
const responsesCodeExamples = [];
if (props.responses) {
props.responses.forEach((response) => {
const typeDisplayName =
response.body && response.body.applicationjson.type;
props.responses.forEach((response, index) => {
const typeDisplayName = response?.body?.[props.contentType[index]]?.type;
const { code } = response;
if (typeDisplayName) {
const apiType = apiTypes.find((type) => {
Expand All @@ -20,7 +19,8 @@ const RequestResponseExamples = (props) => {
);
});

const examplesNode = response.body?.applicationjson?.examples;
const examplesNode =
response.body?.[props.contentType[index]]?.examples;

if (examplesNode && Array.isArray(examplesNode)) {
examplesNode.forEach((example) => {
Expand All @@ -33,7 +33,7 @@ const RequestResponseExamples = (props) => {
value: example.value,
});
});
} else if (apiType.examples && apiType.examples.length > 0) {
} else if (apiType?.examples?.length > 0) {
responsesCodeExamples.push({
code,
typeDisplayName,
Expand Down Expand Up @@ -84,17 +84,10 @@ RequestResponseExamples.propTypes = {
responses: PropTypes.arrayOf(
PropTypes.shape({
code: PropTypes.number.isRequired,
body: PropTypes.oneOfType([
PropTypes.node,
PropTypes.shape({
applicationjson: PropTypes.shape({
builtinType: PropTypes.string.isRequired,
type: PropTypes.string.isRequired,
}),
}),
]),
body: PropTypes.object,
}).isRequired
),
contentType: PropTypes.array.isRequired,
};

export default RequestResponseExamples;
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import SpacingsInline from '@commercetools-uikit/spacings-inline';
import { tokens, dimensions, typography } from '../../../design-system';
import { useTypeLocations } from '../../../hooks/use-type-locations';
import renderTypeAsLink from '../../../utils/render-type-as-link';
import { convertContentType } from './method';
import Title from './title';

const ResponseCode = styled.span`
Expand All @@ -35,7 +36,21 @@ const Responses = ({ apiKey, responses, contentType }) => {
<SpacingsStack scale="xs">
<Title>Response:</Title>
<SpacingsStack scale="s">
{responses.map((response) => {
{responses.map((response, index) => {
const convertedContentType = convertContentType(contentType[index]);
const responseDetails =
response.body &&
renderTypeAsLink(
apiKey,
response.body[contentType[index]].type,
typeLocations,
convertedContentType
);
// If renderTypeAsLink returns the type again and a description is defined, we display the description.
// In this case, the content type should not be displayed at the moment.
const showDescription =
responseDetails === response.body?.[contentType[index]].type &&
response.description;
return (
<SpacingsInline key={response.code}>
<ResponseCode
Expand All @@ -44,20 +59,16 @@ const Responses = ({ apiKey, responses, contentType }) => {
{response.code}
</ResponseCode>
<LinkContainer>
{response.body ? (
{responseDetails ? (
<SpacingsInline alignItems="center">
{renderTypeAsLink(
apiKey,
response.body.applicationjson.type,
typeLocations,
response.description,
contentType
)}
{contentType.length > 0 && (
{showDescription
? markdownFragmentToReact(response.description)
: responseDetails}
{contentType.length > 0 && !showDescription && (
<>
<span>as</span>
<Markdown.InlineCodeWithoutBox>
{contentType}
{convertedContentType}
</Markdown.InlineCodeWithoutBox>
</>
)}
Expand Down
40 changes: 32 additions & 8 deletions packages/gatsby-theme-api-docs/src/hooks/use-api-resources.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,7 @@ export const useApiResources = () => {
code
description
body {
applicationjson {
type
builtinType
examples {
name
value
}
}
...methodBodiesForResponses
}
}
codeExamples {
Expand All @@ -45,6 +38,37 @@ export const useApiResources = () => {
}
}
fragment methodBodiesForResponses on RamlResourceMethodBody {
applicationjson {
type
builtinType
examples {
name
value
}
}
applicationxwwwformurlencoded {
type
builtinType
examples {
name
value
}
}
imagejpeg {
type
builtinType
}
imagepng {
type
builtinType
}
imagegif {
type
builtinType
}
}
fragment methodBodies on RamlResourceMethodBody {
applicationjson {
type
Expand Down
12 changes: 2 additions & 10 deletions packages/gatsby-theme-api-docs/src/utils/render-type-as-link.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,10 @@
import React from 'react';
import { Link } from '@commercetools-docs/gatsby-theme-docs';
import { markdownFragmentToReact, Markdown } from '@commercetools-docs/ui-kit';
import { Markdown } from '@commercetools-docs/ui-kit';
import { locationForType } from '../hooks/use-type-locations';
import { getDescriptionIfPrimitiveType } from '../components/type/type';

function renderTypeAsLink(
apiKey,
type,
typeLocations,
description,
contentType
) {
function renderTypeAsLink(apiKey, type, typeLocations, contentType) {
const typeLocation = locationForType(apiKey, type, typeLocations);

const originalTypeLocation = typeLocation ? typeLocation.url : undefined;
Expand All @@ -28,8 +22,6 @@ function renderTypeAsLink(
return <Link href={originalTypeLocation}>{type}</Link>;
} else if (primitiveJsonType) {
return <Markdown.Em>{primitiveJsonType}</Markdown.Em>;
} else if (description) {
return markdownFragmentToReact(description);
}
return type;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,14 @@ function processMethods({
);
if (returnedMethods[method].responses) {
returnedMethods[method].responses.forEach((response) => {
if (response?.body?.applicationjson.examples) {
response.body.applicationjson.examples = examplesToArray(
response.body.applicationjson.examples
);
if (response?.body) {
Object.keys(response.body).forEach((key) => {
if (response.body[key].examples) {
response.body[key].examples = examplesToArray(
response.body[key].examples
);
}
});
}
});
}
Expand Down

0 comments on commit f9185c6

Please sign in to comment.