]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-21186 Redesign the presentation of enum values for Web API v2 Doc
authorViktor Vorona <viktor.vorona@sonarsource.com>
Tue, 2 Jan 2024 14:39:39 +0000 (15:39 +0100)
committersonartech <sonartech@sonarsource.com>
Wed, 3 Jan 2024 20:02:44 +0000 (20:02 +0000)
server/sonar-web/design-system/src/components/CodeSnippet.tsx
server/sonar-web/design-system/src/components/CodeSyntaxHighlighter.tsx
server/sonar-web/design-system/src/components/__tests__/__snapshots__/CodeSnippet-test.tsx.snap
server/sonar-web/src/main/js/apps/web-api-v2/__tests__/WebApiApp-it.tsx
server/sonar-web/src/main/js/apps/web-api-v2/__tests__/utils-test.ts
server/sonar-web/src/main/js/apps/web-api-v2/components/ApiParameters.tsx
server/sonar-web/src/main/js/apps/web-api-v2/components/ApiRequestParameters.tsx
server/sonar-web/src/main/js/apps/web-api-v2/components/ApiResponseSchema.tsx
server/sonar-web/src/main/js/apps/web-api-v2/utils.ts
sonar-core/src/main/resources/org/sonar/l10n/core.properties

index 8281a1242f9e82a016036101f82f941b9ba88884..c5c6e863dcd90729bec0fcc31ef7f878fb885246 100644 (file)
@@ -34,7 +34,7 @@ interface Props {
   noCopy?: boolean;
   render?: string;
   snippet: string | Array<string | undefined>;
-  wrap?: boolean;
+  wrap?: boolean | 'words';
 }
 
 // keep this "useless" concatenation for the readability reason
index bf2ca3d5ced082e1013166fffad74024688ccea9..e500fa239cf97ab052f6105a221d0b2ce351c101 100644 (file)
@@ -43,7 +43,7 @@ interface Props {
   className?: string;
   htmlAsString: string;
   language?: string;
-  wrap?: boolean;
+  wrap?: boolean | 'words';
 }
 
 const CODE_REGEXP = '<(code|pre)\\b([^>]*?)>(.+?)<\\/\\1>';
@@ -93,7 +93,11 @@ export function CodeSyntaxHighlighter(props: Props) {
 
   return (
     <StyledSpan
-      className={classNames(`hljs ${className ?? ''}`, { 'code-wrap': wrap })}
+      className={classNames(
+        `hljs ${className ?? ''}`,
+        { 'code-wrap': wrap },
+        { 'wrap-words': wrap === 'words' },
+      )}
       // Safe: value is escaped by highlight.js
       // eslint-disable-next-line react/no-danger
       dangerouslySetInnerHTML={{ __html: highlightedHtmlAsString }}
@@ -153,6 +157,11 @@ const StyledSpan = styled.span`
   &.code-wrap {
     ${tw`sw-whitespace-pre-wrap`}
     ${tw`sw-break-all`}
+
+    &.wrap-words {
+      word-break: normal;
+      ${tw`sw-break-words`}
+    }
   }
 
   mark {
index 20b9a394505ad74842ccf67ea91577e4f0586691..6d2f58112e90d3f1000118388cce4faae994d400 100644 (file)
@@ -158,6 +158,11 @@ exports[`should highlight code content correctly 1`] = `
   word-break: break-all;
 }
 
+.emotion-6.code-wrap.wrap-words {
+  word-break: normal;
+  overflow-wrap: break-word;
+}
+
 .emotion-6 mark {
   font-weight: 400;
   padding: 0.25rem;
@@ -365,6 +370,11 @@ exports[`should show full size when multiline with no editing 1`] = `
   word-break: break-all;
 }
 
+.emotion-6.code-wrap.wrap-words {
+  word-break: normal;
+  overflow-wrap: break-word;
+}
+
 .emotion-6 mark {
   font-weight: 400;
   padding: 0.25rem;
@@ -576,6 +586,11 @@ exports[`should show reduced size when single line with no editing 1`] = `
   word-break: break-all;
 }
 
+.emotion-6.code-wrap.wrap-words {
+  word-break: normal;
+  overflow-wrap: break-word;
+}
+
 .emotion-6 mark {
   font-weight: 400;
   padding: 0.25rem;
index 5f6fd8ed667c4ce15cc38c79928e2a10087eee1a..5944543fcf7275b4de8fafd633d2c49eb9e10288 100644 (file)
@@ -155,7 +155,9 @@ it('should navigate between apis', async () => {
   expect(ui.requestHeader.query()).not.toBeInTheDocument();
   expect(ui.requestBody.query()).not.toBeInTheDocument();
   expect(ui.queryParameter.getAll()).toHaveLength(1);
-  expect(ui.queryParameter.getAt(0)).toHaveTextContent('status ["available","pending","sold"]');
+  expect(ui.queryParameter.getAt(0)).toHaveTextContent(
+    'status Enum (string): available, pending, sold',
+  );
   expect(ui.queryParameter.getAt(0)).not.toHaveTextContent('default: available');
   await user.click(ui.queryParameter.byRole('button').getAt(0));
   expect(ui.queryParameter.getAt(0)).toHaveTextContent('default: available');
index 5ffd0aa7bfb2fd31b6d8ee449ae1b18f99feb179..2e59ab4490043c98d8624e3415355b284c6d550e 100644 (file)
@@ -235,5 +235,5 @@ it('should map open api response schema', () => {
       type: 'string',
       enum: ['GREEN', 'YELLOW', 'RED'],
     }),
-  ).toStrictEqual(['GREEN', 'YELLOW', 'RED']);
+  ).toStrictEqual('Enum (string): GREEN, YELLOW, RED');
 });
index 6116519884117dc470cff2a4b6c8efed992afe0c..5d29e8fa652a560da060776471a0748ed0c21705 100644 (file)
@@ -22,6 +22,7 @@ import { Accordion, Badge, SubHeading, SubTitle, TextMuted } from 'design-system
 import { groupBy } from 'lodash';
 import { OpenAPIV3 } from 'openapi-types';
 import React from 'react';
+import { FormattedMessage } from 'react-intl';
 import { translate } from '../../../helpers/l10n';
 import { ExcludeReferences } from '../types';
 import { mapOpenAPISchema } from '../utils';
@@ -89,6 +90,20 @@ export default function ApiParameters({ data }: Props) {
                   open={openParameters.includes(parameter.name)}
                 >
                   <div>{parameter.description}</div>
+                  {parameter.schema?.enum && (
+                    <div className="sw-mt-2">
+                      <FormattedMessage
+                        id="api_documentation.v2.enum_description"
+                        values={{
+                          values: (
+                            <div className="sw-body-sm-highlight">
+                              {parameter.schema.enum.join(', ')}
+                            </div>
+                          ),
+                        }}
+                      />
+                    </div>
+                  )}
                   {parameter.schema?.maximum && (
                     <TextMuted
                       className="sw-mt-2 sw-block"
index 1888bd7847c1515aed6393d7fd6c0259e5efdabd..742d083a951b3911674d0bc9221179464184f4c3 100644 (file)
@@ -22,6 +22,7 @@ import { Accordion, Badge, TextMuted } from 'design-system';
 import { isEmpty } from 'lodash';
 import { OpenAPIV3 } from 'openapi-types';
 import React from 'react';
+import { FormattedMessage } from 'react-intl';
 import { translate } from '../../../helpers/l10n';
 import { ExcludeReferences } from '../types';
 
@@ -86,6 +87,16 @@ export default function ApiRequestBodyParameters({ content }: Readonly<Props>) {
             open={openParameters.includes(key)}
           >
             <div>{parameters[key].description}</div>
+            {parameters[key].enum && (
+              <div className="sw-mt-2">
+                <FormattedMessage
+                  id="api_documentation.v2.enum_description"
+                  values={{
+                    values: <i>{parameters[key].enum?.join(', ')}</i>,
+                  }}
+                />
+              </div>
+            )}
             {parameters[key].maxLength && (
               <TextMuted
                 className="sw-mt-2 sw-block"
index ffa716429c5baf93d8786a932c6a336ec5f43cc9..b028123ea9fbf428e958a8e98f7328ea67ef515a 100644 (file)
@@ -29,7 +29,7 @@ interface Props extends Omit<HtmlHTMLAttributes<HTMLDivElement>, 'content'> {
   content?: Exclude<ExcludeReferences<OpenAPIV3.ResponseObject>['content'], undefined>;
 }
 
-export default function ApiResponseSchema(props: Props) {
+export default function ApiResponseSchema(props: Readonly<Props>) {
   const { content, ...other } = props;
   const schema =
     content &&
@@ -43,7 +43,7 @@ export default function ApiResponseSchema(props: Props) {
       language="json"
       className="sw-p-6"
       snippet={JSON.stringify(mapOpenAPISchema(schema), null, 2)}
-      wrap
+      wrap="words"
       {...other}
     />
   );
index 49732b04d7a260bd4ac3a6601a7c4685c7ee365e..2949976f13ce7ce2c6bd3ade1bf7d8a1a0951bb0 100644 (file)
@@ -36,8 +36,8 @@ export const mapOpenAPISchema = (
   if (schema.type === 'array') {
     return [mapOpenAPISchema(schema.items)];
   }
-  if (schema.type === 'string' && schema.enum) {
-    return schema.enum as ConvertedSchema;
+  if (schema.enum) {
+    return `Enum (${schema.type}): ${(schema.enum as ConvertedSchema[]).join(', ')}`;
   }
   if (schema.format) {
     return `${schema.type} (${schema.format})`;
index 3a6bf83af90aaab5948f5a7ab9d3b25e3d24b1bd..f2f4cbb63d00c65489d0a17e90cbe38e95c1efb1 100644 (file)
@@ -4045,6 +4045,7 @@ api_documentation.v2.request_subheader.query=Query Parameters
 api_documentation.v2.request_subheader.path=Path Parameters
 api_documentation.v2.request_subheader.header=Headers
 api_documentation.v2.request_subheader.request_body=Request Body
+api_documentation.v2.enum_description=Valid values: {values}
 
 
 #------------------------------------------------------------------------------