]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-9521 Add sparator between ws descriptions (hum and rewrite to ts)
authorGrégoire Aubert <gregoire.aubert@sonarsource.com>
Thu, 24 Aug 2017 13:08:35 +0000 (15:08 +0200)
committerGrégoire Aubert <gregoire.aubert@sonarsource.com>
Fri, 25 Aug 2017 14:01:06 +0000 (16:01 +0200)
47 files changed:
server/sonar-web/src/main/js/api/web-api.ts
server/sonar-web/src/main/js/apps/web-api/components/Action.js [deleted file]
server/sonar-web/src/main/js/apps/web-api/components/Action.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/apps/web-api/components/ActionChangelog.js [deleted file]
server/sonar-web/src/main/js/apps/web-api/components/ActionChangelog.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/apps/web-api/components/DeprecatedBadge.js [deleted file]
server/sonar-web/src/main/js/apps/web-api/components/DeprecatedBadge.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/apps/web-api/components/Domain.js [deleted file]
server/sonar-web/src/main/js/apps/web-api/components/Domain.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/apps/web-api/components/InternalBadge.js [deleted file]
server/sonar-web/src/main/js/apps/web-api/components/InternalBadge.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/apps/web-api/components/Menu.js [deleted file]
server/sonar-web/src/main/js/apps/web-api/components/Menu.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/apps/web-api/components/Params.js [deleted file]
server/sonar-web/src/main/js/apps/web-api/components/Params.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/apps/web-api/components/ResponseExample.js [deleted file]
server/sonar-web/src/main/js/apps/web-api/components/ResponseExample.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/apps/web-api/components/Search.js [deleted file]
server/sonar-web/src/main/js/apps/web-api/components/Search.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/apps/web-api/components/WebApiApp.js [deleted file]
server/sonar-web/src/main/js/apps/web-api/components/WebApiApp.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/apps/web-api/components/__tests__/Action-test.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/apps/web-api/components/__tests__/ActionChangelog-test.js [deleted file]
server/sonar-web/src/main/js/apps/web-api/components/__tests__/ActionChangelog-test.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/apps/web-api/components/__tests__/Domain-test.js [deleted file]
server/sonar-web/src/main/js/apps/web-api/components/__tests__/Domain-test.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/apps/web-api/components/__tests__/Menu-test.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/apps/web-api/components/__tests__/Params-test.js [deleted file]
server/sonar-web/src/main/js/apps/web-api/components/__tests__/Params-test.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/apps/web-api/components/__tests__/ResponseExample-test.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/apps/web-api/components/__tests__/Search-test.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/apps/web-api/components/__tests__/__snapshots__/Action-test.tsx.snap [new file with mode: 0644]
server/sonar-web/src/main/js/apps/web-api/components/__tests__/__snapshots__/ActionChangelog-test.js.snap [deleted file]
server/sonar-web/src/main/js/apps/web-api/components/__tests__/__snapshots__/ActionChangelog-test.tsx.snap [new file with mode: 0644]
server/sonar-web/src/main/js/apps/web-api/components/__tests__/__snapshots__/Domain-test.js.snap [deleted file]
server/sonar-web/src/main/js/apps/web-api/components/__tests__/__snapshots__/Domain-test.tsx.snap [new file with mode: 0644]
server/sonar-web/src/main/js/apps/web-api/components/__tests__/__snapshots__/Menu-test.tsx.snap [new file with mode: 0644]
server/sonar-web/src/main/js/apps/web-api/components/__tests__/__snapshots__/Params-test.js.snap [deleted file]
server/sonar-web/src/main/js/apps/web-api/components/__tests__/__snapshots__/Params-test.tsx.snap [new file with mode: 0644]
server/sonar-web/src/main/js/apps/web-api/components/__tests__/__snapshots__/ResponseExample-test.tsx.snap [new file with mode: 0644]
server/sonar-web/src/main/js/apps/web-api/components/__tests__/__snapshots__/Search-test.tsx.snap [new file with mode: 0644]
server/sonar-web/src/main/js/apps/web-api/styles/web-api.css
server/sonar-web/src/main/js/apps/web-api/utils.js [deleted file]
server/sonar-web/src/main/js/apps/web-api/utils.ts [new file with mode: 0644]
server/sonar-web/src/main/js/components/icons-components/LinkIcon.js [deleted file]
server/sonar-web/src/main/js/components/icons-components/LinkIcon.tsx [new file with mode: 0644]
sonar-core/src/main/resources/org/sonar/l10n/core.properties

index 3bd512e43f9ccff930ab0fb6ca74f1d657b11ead..88c257c4d411a3717e7e019f436ea1b633180c04 100644 (file)
  */
 import { getJSON } from '../helpers/request';
 
+export interface Changelog {
+  description: string;
+  version: string;
+}
+
 export interface Param {
   key: string;
   defaultValue?: string;
@@ -28,20 +33,22 @@ export interface Param {
   deprecatedSince?: string;
   exampleValue?: string;
   internal: boolean;
+  maxValuesAllowed?: number;
   possibleValues?: string[];
   required: boolean;
+  since?: string;
 }
 
 export interface Action {
   key: string;
+  changelog: Changelog[];
   description: string;
   deprecatedSince?: string;
-  since?: string;
-  internal: boolean;
-  post: boolean;
   hasResponseExample: boolean;
-  changelog: Array<{ version: string; description: string }>;
+  internal: boolean;
   params?: Param[];
+  post: boolean;
+  since?: string;
 }
 
 export interface Domain {
@@ -50,6 +57,12 @@ export interface Domain {
   deprecated: boolean;
   internal: boolean;
   path: string;
+  since?: string;
+}
+
+export interface Example {
+  example: string;
+  format: string;
 }
 
 export function fetchWebApi(showInternal: boolean = true): Promise<Array<Domain>> {
@@ -62,6 +75,6 @@ export function fetchWebApi(showInternal: boolean = true): Promise<Array<Domain>
   );
 }
 
-export function fetchResponseExample(domain: string, action: string): Promise<{ example: string }> {
+export function fetchResponseExample(domain: string, action: string): Promise<Example> {
   return getJSON('/api/webservices/response_example', { controller: domain, action });
 }
diff --git a/server/sonar-web/src/main/js/apps/web-api/components/Action.js b/server/sonar-web/src/main/js/apps/web-api/components/Action.js
deleted file mode 100644 (file)
index 6e84e8a..0000000
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2017 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-// @flow
-import React from 'react';
-import { Link } from 'react-router';
-import classNames from 'classnames';
-import { getActionKey } from '../utils';
-import Params from './Params';
-import ResponseExample from './ResponseExample';
-import ActionChangelog from './ActionChangelog';
-import DeprecatedBadge from './DeprecatedBadge';
-import InternalBadge from './InternalBadge';
-import LinkIcon from '../../../components/icons-components/LinkIcon';
-import { TooltipsContainer } from '../../../components/mixins/tooltips-mixin';
-/*:: import type { Action as ActionType, Domain as DomainType } from '../../../api/web-api'; */
-
-/*::
-type Props = {
-  action: ActionType,
-  domain: DomainType,
-  showDeprecated: boolean,
-  showInternal: boolean
-};
-*/
-
-/*::
-type State = {
-  showChangelog: boolean,
-  showParams: boolean,
-  showResponse: boolean
-};
-*/
-
-export default class Action extends React.PureComponent {
-  /*:: props: Props; */
-
-  state /*: State */ = {
-    showChangelog: false,
-    showParams: false,
-    showResponse: false
-  };
-
-  handleShowParamsClick = (e /*: SyntheticInputEvent */) => {
-    e.preventDefault();
-    this.setState({
-      showChangelog: false,
-      showResponse: false,
-      showParams: !this.state.showParams
-    });
-  };
-
-  handleShowResponseClick = (e /*: SyntheticInputEvent */) => {
-    e.preventDefault();
-    this.setState({
-      showChangelog: false,
-      showParams: false,
-      showResponse: !this.state.showResponse
-    });
-  };
-
-  handleChangelogClick = (e /*: SyntheticInputEvent */) => {
-    e.preventDefault();
-    this.setState({
-      showChangelog: !this.state.showChangelog,
-      showParams: false,
-      showResponse: false
-    });
-  };
-
-  render() {
-    const { action, domain } = this.props;
-    const { showChangelog, showParams, showResponse } = this.state;
-    const verb = action.post ? 'POST' : 'GET';
-    const actionKey = getActionKey(domain.path, action.key);
-
-    return (
-      <div id={actionKey} className="web-api-action">
-        <TooltipsContainer>
-          <header className="web-api-action-header">
-            <Link
-              to={{ pathname: '/web_api/' + actionKey }}
-              className="spacer-right link-no-underline">
-              <LinkIcon />
-            </Link>
-
-            <h3 className="web-api-action-title">
-              {verb}&nbsp;{actionKey}
-            </h3>
-
-            {action.internal &&
-              <span className="spacer-left">
-                <InternalBadge />
-              </span>}
-
-            {action.since &&
-              <span className="spacer-left badge">
-                since {action.since}
-              </span>}
-
-            {action.deprecatedSince &&
-              <span className="spacer-left">
-                <DeprecatedBadge since={action.deprecatedSince} />
-              </span>}
-          </header>
-        </TooltipsContainer>
-
-        <div
-          className="web-api-action-description markdown"
-          dangerouslySetInnerHTML={{ __html: action.description }}
-        />
-
-        {(action.params || action.hasResponseExample) &&
-          <ul className="web-api-action-actions tabs">
-            {action.params &&
-              <li>
-                <a
-                  className={classNames({ selected: showParams })}
-                  href="#"
-                  onClick={this.handleShowParamsClick}>
-                  Parameters
-                </a>
-              </li>}
-
-            {action.hasResponseExample &&
-              <li>
-                <a
-                  className={classNames({ selected: showResponse })}
-                  href="#"
-                  onClick={this.handleShowResponseClick}>
-                  Response Example
-                </a>
-              </li>}
-
-            {action.changelog.length > 0 &&
-              <li>
-                <a
-                  className={classNames({ selected: showChangelog })}
-                  href="#"
-                  onClick={this.handleChangelogClick}>
-                  Changelog
-                </a>
-              </li>}
-          </ul>}
-
-        {showParams &&
-          action.params &&
-          <Params
-            params={action.params}
-            showDeprecated={this.props.showDeprecated}
-            showInternal={this.props.showInternal}
-          />}
-
-        {showResponse &&
-          action.hasResponseExample &&
-          <ResponseExample domain={domain} action={action} />}
-
-        {showChangelog && <ActionChangelog changelog={action.changelog} />}
-      </div>
-    );
-  }
-}
diff --git a/server/sonar-web/src/main/js/apps/web-api/components/Action.tsx b/server/sonar-web/src/main/js/apps/web-api/components/Action.tsx
new file mode 100644 (file)
index 0000000..92cea76
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+import * as React from 'react';
+import { Link } from 'react-router';
+import * as classNames from 'classnames';
+import { getActionKey } from '../utils';
+import Params from './Params';
+import ResponseExample from './ResponseExample';
+import ActionChangelog from './ActionChangelog';
+import DeprecatedBadge from './DeprecatedBadge';
+import InternalBadge from './InternalBadge';
+import LinkIcon from '../../../components/icons-components/LinkIcon';
+import { Action as ActionType, Domain as DomainType } from '../../../api/web-api';
+import { translate, translateWithParameters } from '../../../helpers/l10n';
+
+interface Props {
+  action: ActionType;
+  domain: DomainType;
+  showDeprecated: boolean;
+  showInternal: boolean;
+}
+
+interface State {
+  showChangelog: boolean;
+  showParams: boolean;
+  showResponse: boolean;
+}
+
+export default class Action extends React.PureComponent<Props, State> {
+  state: State = {
+    showChangelog: false,
+    showParams: false,
+    showResponse: false
+  };
+
+  handleShowParamsClick = (e: React.SyntheticEvent<HTMLElement>) => {
+    e.preventDefault();
+    this.setState({
+      showChangelog: false,
+      showResponse: false,
+      showParams: !this.state.showParams
+    });
+  };
+
+  handleShowResponseClick = (e: React.SyntheticEvent<HTMLElement>) => {
+    e.preventDefault();
+    this.setState({
+      showChangelog: false,
+      showParams: false,
+      showResponse: !this.state.showResponse
+    });
+  };
+
+  handleChangelogClick = (e: React.SyntheticEvent<HTMLElement>) => {
+    e.preventDefault();
+    this.setState({
+      showChangelog: !this.state.showChangelog,
+      showParams: false,
+      showResponse: false
+    });
+  };
+
+  renderTabs() {
+    const { action } = this.props;
+    const { showChangelog, showParams, showResponse } = this.state;
+
+    if (action.params || action.hasResponseExample || action.changelog.length > 0) {
+      return (
+        <ul className="web-api-action-actions tabs">
+          {action.params &&
+            <li>
+              <a
+                className={classNames({ selected: showParams })}
+                href="#"
+                onClick={this.handleShowParamsClick}>
+                {translate('api_documentation.parameters')}
+              </a>
+            </li>}
+
+          {action.hasResponseExample &&
+            <li>
+              <a
+                className={classNames({ selected: showResponse })}
+                href="#"
+                onClick={this.handleShowResponseClick}>
+                {translate('api_documentation.response_example')}
+              </a>
+            </li>}
+
+          {action.changelog.length > 0 &&
+            <li>
+              <a
+                className={classNames({ selected: showChangelog })}
+                href="#"
+                onClick={this.handleChangelogClick}>
+                {translate('api_documentation.changelog')}
+              </a>
+            </li>}
+        </ul>
+      );
+    }
+
+    return <hr />;
+  }
+
+  render() {
+    const { action, domain } = this.props;
+    const { showChangelog, showParams, showResponse } = this.state;
+    const verb = action.post ? 'POST' : 'GET';
+    const actionKey = getActionKey(domain.path, action.key);
+
+    return (
+      <div id={actionKey} className="web-api-action">
+        <header className="web-api-action-header">
+          <Link
+            to={{ pathname: '/web_api/' + actionKey }}
+            className="spacer-right link-no-underline">
+            <LinkIcon />
+          </Link>
+
+          <h3 className="web-api-action-title">
+            {verb}&nbsp;{actionKey}
+          </h3>
+
+          {action.internal &&
+            <span className="spacer-left">
+              <InternalBadge />
+            </span>}
+
+          {action.since &&
+            <span className="spacer-left badge">
+              {translateWithParameters('since_x', action.since)}
+            </span>}
+
+          {action.deprecatedSince &&
+            <span className="spacer-left">
+              <DeprecatedBadge since={action.deprecatedSince} />
+            </span>}
+        </header>
+
+        <div
+          className="web-api-action-description markdown"
+          dangerouslySetInnerHTML={{ __html: action.description }}
+        />
+
+        {this.renderTabs()}
+
+        {showParams &&
+          action.params &&
+          <Params
+            params={action.params}
+            showDeprecated={this.props.showDeprecated}
+            showInternal={this.props.showInternal}
+          />}
+
+        {showResponse &&
+          action.hasResponseExample &&
+          <ResponseExample domain={domain} action={action} />}
+
+        {showChangelog && <ActionChangelog changelog={action.changelog} />}
+      </div>
+    );
+  }
+}
diff --git a/server/sonar-web/src/main/js/apps/web-api/components/ActionChangelog.js b/server/sonar-web/src/main/js/apps/web-api/components/ActionChangelog.js
deleted file mode 100644 (file)
index ff5b42b..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2017 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-// @flow
-import React from 'react';
-
-/*::
-type Props = {
-  changelog: Array<{
-    description: string,
-    version: string
-  }>
-};
-*/
-
-export default class ActionChangelog extends React.PureComponent {
-  /*:: props: Props; */
-
-  render() {
-    return (
-      <ul className="big-spacer-top">
-        {this.props.changelog.map((item, index) =>
-          <li key={index} className="spacer-top">
-            <span className="spacer-right badge">
-              {item.version}
-            </span>
-            {item.description}
-          </li>
-        )}
-      </ul>
-    );
-  }
-}
diff --git a/server/sonar-web/src/main/js/apps/web-api/components/ActionChangelog.tsx b/server/sonar-web/src/main/js/apps/web-api/components/ActionChangelog.tsx
new file mode 100644 (file)
index 0000000..7e33e97
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+import * as React from 'react';
+import { Changelog } from '../../../api/web-api';
+
+interface Props {
+  changelog: Changelog[];
+}
+
+export default function ActionChangelog({ changelog }: Props) {
+  return (
+    <ul className="big-spacer-top">
+      {changelog.map((item, index) =>
+        <li key={index} className="spacer-top">
+          <span className="spacer-right badge">
+            {item.version}
+          </span>
+          {item.description}
+        </li>
+      )}
+    </ul>
+  );
+}
diff --git a/server/sonar-web/src/main/js/apps/web-api/components/DeprecatedBadge.js b/server/sonar-web/src/main/js/apps/web-api/components/DeprecatedBadge.js
deleted file mode 100644 (file)
index 988daab..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2017 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-import React from 'react';
-import { translate } from '../../../helpers/l10n';
-
-export default function DeprecatedBadge({ since }) {
-  const label = since ? `deprecated since ${since}` : 'deprecated';
-
-  return (
-    <span
-      className="badge badge-warning"
-      title={translate('api_documentation.deprecation_tooltip')}
-      data-toggle="tooltip">
-      {label}
-    </span>
-  );
-}
diff --git a/server/sonar-web/src/main/js/apps/web-api/components/DeprecatedBadge.tsx b/server/sonar-web/src/main/js/apps/web-api/components/DeprecatedBadge.tsx
new file mode 100644 (file)
index 0000000..504d055
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+import * as React from 'react';
+import Tooltip from '../../../components/controls/Tooltip';
+import { translate, translateWithParameters } from '../../../helpers/l10n';
+
+export default function DeprecatedBadge({ since }: { since?: string }) {
+  const label = since
+    ? translateWithParameters('api_documentation.depracated_since_x', since)
+    : translate('api_documentation.depracated');
+  return (
+    <Tooltip overlay={translate('api_documentation.deprecation_tooltip')}>
+      <span className="badge badge-warning">
+        {label}
+      </span>
+    </Tooltip>
+  );
+}
diff --git a/server/sonar-web/src/main/js/apps/web-api/components/Domain.js b/server/sonar-web/src/main/js/apps/web-api/components/Domain.js
deleted file mode 100644 (file)
index e724050..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2017 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-// @flow
-import React from 'react';
-import Action from './Action';
-import DeprecatedBadge from './DeprecatedBadge';
-import InternalBadge from './InternalBadge';
-import { getActionKey, actionsFilter } from '../utils';
-/*:: import type { Domain as DomainType } from '../../../api/web-api'; */
-
-/*::
-type Props = {
-  domain: DomainType,
-  showDeprecated: boolean,
-  showInternal: boolean,
-  searchQuery: string
-};
-*/
-
-export default class Domain extends React.PureComponent {
-  /*:: props: Props; */
-
-  render() {
-    const { domain, showInternal, showDeprecated, searchQuery } = this.props;
-    const filteredActions = domain.actions.filter(action =>
-      actionsFilter(showDeprecated, showInternal, searchQuery, domain, action)
-    );
-
-    return (
-      <div className="web-api-domain">
-        <header className="web-api-domain-header">
-          <h2 className="web-api-domain-title">
-            {domain.path}
-          </h2>
-
-          {domain.deprecated &&
-            <span className="spacer-left">
-              <DeprecatedBadge />
-            </span>}
-
-          {domain.internal &&
-            <span className="spacer-left">
-              <InternalBadge />
-            </span>}
-        </header>
-
-        {domain.description &&
-          <div
-            className="web-api-domain-description markdown"
-            dangerouslySetInnerHTML={{ __html: domain.description }}
-          />}
-
-        <div className="web-api-domain-actions">
-          {filteredActions.map(action =>
-            <Action
-              key={getActionKey(domain.path, action.key)}
-              action={action}
-              domain={domain}
-              showDeprecated={showDeprecated}
-              showInternal={showInternal}
-            />
-          )}
-        </div>
-      </div>
-    );
-  }
-}
diff --git a/server/sonar-web/src/main/js/apps/web-api/components/Domain.tsx b/server/sonar-web/src/main/js/apps/web-api/components/Domain.tsx
new file mode 100644 (file)
index 0000000..8e70e2e
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+import * as React from 'react';
+import Action from './Action';
+import DeprecatedBadge from './DeprecatedBadge';
+import InternalBadge from './InternalBadge';
+import { getActionKey, actionsFilter } from '../utils';
+import { Domain as DomainType } from '../../../api/web-api';
+
+interface Props {
+  domain: DomainType;
+  showDeprecated: boolean;
+  showInternal: boolean;
+  searchQuery: string;
+}
+
+export default function Domain({ domain, showInternal, showDeprecated, searchQuery }: Props) {
+  const filteredActions = domain.actions.filter(action =>
+    actionsFilter(showDeprecated, showInternal, searchQuery, domain, action)
+  );
+
+  return (
+    <div className="web-api-domain">
+      <header className="web-api-domain-header">
+        <h2 className="web-api-domain-title">
+          {domain.path}
+        </h2>
+
+        {domain.deprecated &&
+          <span className="spacer-left">
+            <DeprecatedBadge />
+          </span>}
+
+        {domain.internal &&
+          <span className="spacer-left">
+            <InternalBadge />
+          </span>}
+      </header>
+
+      {domain.description &&
+        <div
+          className="web-api-domain-description markdown"
+          dangerouslySetInnerHTML={{ __html: domain.description }}
+        />}
+
+      <div className="web-api-domain-actions">
+        {filteredActions.map(action =>
+          <Action
+            key={getActionKey(domain.path, action.key)}
+            action={action}
+            domain={domain}
+            showDeprecated={showDeprecated}
+            showInternal={showInternal}
+          />
+        )}
+      </div>
+    </div>
+  );
+}
diff --git a/server/sonar-web/src/main/js/apps/web-api/components/InternalBadge.js b/server/sonar-web/src/main/js/apps/web-api/components/InternalBadge.js
deleted file mode 100644 (file)
index 210d30b..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2017 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-import React from 'react';
-import { translate } from '../../../helpers/l10n';
-
-export default function InternalBadge() {
-  return (
-    <span
-      className="badge badge-danger"
-      title={translate('api_documentation.internal_tooltip')}
-      data-toggle="tooltip">
-      internal
-    </span>
-  );
-}
diff --git a/server/sonar-web/src/main/js/apps/web-api/components/InternalBadge.tsx b/server/sonar-web/src/main/js/apps/web-api/components/InternalBadge.tsx
new file mode 100644 (file)
index 0000000..4b7ed15
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+import * as React from 'react';
+import Tooltip from '../../../components/controls/Tooltip';
+import { translate } from '../../../helpers/l10n';
+
+export default function InternalBadge() {
+  return (
+    <Tooltip overlay={translate('api_documentation.internal_tooltip')}>
+      <span className="badge badge-danger">
+        {translate('internal')}
+      </span>
+    </Tooltip>
+  );
+}
diff --git a/server/sonar-web/src/main/js/apps/web-api/components/Menu.js b/server/sonar-web/src/main/js/apps/web-api/components/Menu.js
deleted file mode 100644 (file)
index 521817b..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2017 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-// @flow
-import React from 'react';
-import { Link } from 'react-router';
-import classNames from 'classnames';
-import DeprecatedBadge from './DeprecatedBadge';
-import InternalBadge from './InternalBadge';
-import { TooltipsContainer } from '../../../components/mixins/tooltips-mixin';
-import { isDomainPathActive, actionsFilter } from '../utils';
-/*:: import type { Domain as DomainType } from '../../../api/web-api'; */
-
-/*::
-type Props = {
-  domains: Array<DomainType>,
-  showDeprecated: boolean,
-  showInternal: boolean,
-  searchQuery: string,
-  splat: string
-};
-*/
-
-export default class Menu extends React.PureComponent {
-  /*:: props: Props; */
-
-  render() {
-    const { domains, showInternal, showDeprecated, searchQuery, splat } = this.props;
-    const filteredDomains = (domains || [])
-      .map(domain => {
-        const filteredActions = domain.actions.filter(action =>
-          actionsFilter(showDeprecated, showInternal, searchQuery, domain, action)
-        );
-        return { ...domain, filteredActions };
-      })
-      .filter(domain => domain.filteredActions.length);
-
-    return (
-      <div className="api-documentation-results panel">
-        <TooltipsContainer>
-          <div className="list-group">
-            {filteredDomains.map(domain =>
-              <Link
-                key={domain.path}
-                className={classNames('list-group-item', {
-                  active: isDomainPathActive(domain.path, splat)
-                })}
-                to={'/web_api/' + domain.path}>
-                <h3 className="list-group-item-heading">
-                  {domain.path}
-                  {domain.deprecated && <DeprecatedBadge />}
-                  {domain.internal && <InternalBadge />}
-                </h3>
-                {domain.description &&
-                  <div
-                    className="list-group-item-text markdown"
-                    dangerouslySetInnerHTML={{ __html: domain.description }}
-                  />}
-              </Link>
-            )}
-          </div>
-        </TooltipsContainer>
-      </div>
-    );
-  }
-}
diff --git a/server/sonar-web/src/main/js/apps/web-api/components/Menu.tsx b/server/sonar-web/src/main/js/apps/web-api/components/Menu.tsx
new file mode 100644 (file)
index 0000000..d33ddad
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+import * as React from 'react';
+import { Link } from 'react-router';
+import * as classNames from 'classnames';
+import DeprecatedBadge from './DeprecatedBadge';
+import InternalBadge from './InternalBadge';
+import { isDomainPathActive, actionsFilter } from '../utils';
+import { Domain } from '../../../api/web-api';
+
+interface Props {
+  domains: Domain[];
+  showDeprecated: boolean;
+  showInternal: boolean;
+  searchQuery: string;
+  splat: string;
+}
+
+export default function Menu(props: Props) {
+  const { domains, showInternal, showDeprecated, searchQuery, splat } = props;
+  const filteredDomains = (domains || [])
+    .map(domain => {
+      const filteredActions = domain.actions.filter(action =>
+        actionsFilter(showDeprecated, showInternal, searchQuery, domain, action)
+      );
+      return { ...domain, filteredActions };
+    })
+    .filter(domain => domain.filteredActions.length);
+
+  return (
+    <div className="api-documentation-results panel">
+      <div className="list-group">
+        {filteredDomains.map(domain =>
+          <Link
+            key={domain.path}
+            className={classNames('list-group-item', {
+              active: isDomainPathActive(domain.path, splat)
+            })}
+            to={'/web_api/' + domain.path}>
+            <h3 className="list-group-item-heading">
+              {domain.path}
+              {domain.deprecated && <DeprecatedBadge />}
+              {domain.internal && <InternalBadge />}
+            </h3>
+            {domain.description &&
+              <div
+                className="list-group-item-text markdown"
+                dangerouslySetInnerHTML={{ __html: domain.description }}
+              />}
+          </Link>
+        )}
+      </div>
+    </div>
+  );
+}
diff --git a/server/sonar-web/src/main/js/apps/web-api/components/Params.js b/server/sonar-web/src/main/js/apps/web-api/components/Params.js
deleted file mode 100644 (file)
index f2e7751..0000000
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2017 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-// @flow
-import React from 'react';
-import InternalBadge from './InternalBadge';
-import DeprecatedBadge from './DeprecatedBadge';
-/*:: import type { Param } from '../../../api/web-api'; */
-
-export default class Params extends React.PureComponent {
-  /*:: props: {
-    showDeprecated: boolean,
-    showInternal: boolean,
-    params: Array<Param>
-  };
-*/
-
-  render() {
-    const { showDeprecated, showInternal, params } = this.props;
-    const displayedParameters = params
-      .filter(p => showDeprecated || !p.deprecatedSince)
-      .filter(p => showInternal || !p.internal);
-    return (
-      <div className="web-api-params">
-        <table>
-          <tbody>
-            {displayedParameters.map(param =>
-              <tr key={param.key}>
-                <td className="markdown" style={{ width: 180 }}>
-                  <code>
-                    {param.key}
-                  </code>
-
-                  {param.internal &&
-                    <div className="little-spacer-top">
-                      <InternalBadge />
-                    </div>}
-
-                  {param.deprecatedSince &&
-                    <div className="little-spacer-top">
-                      <DeprecatedBadge since={param.deprecatedSince} />
-                    </div>}
-
-                  {showDeprecated &&
-                    param.deprecatedKey &&
-                    <div className="little-spacer-top">
-                      <code>
-                        {param.deprecatedKey}
-                      </code>
-                    </div>}
-
-                  {showDeprecated &&
-                    param.deprecatedKey &&
-                    param.deprecatedKeySince &&
-                    <div className="little-spacer-top">
-                      <DeprecatedBadge since={param.deprecatedKeySince} />
-                    </div>}
-
-                  <div className="note little-spacer-top">
-                    {param.required ? 'required' : 'optional'}
-                  </div>
-
-                  {param.since &&
-                    <div className="note little-spacer-top">
-                      since {param.since}
-                    </div>}
-                </td>
-
-                <td>
-                  <div
-                    className="markdown"
-                    dangerouslySetInnerHTML={{ __html: param.description }}
-                  />
-                </td>
-
-                <td style={{ width: 250 }}>
-                  {param.possibleValues &&
-                    <div>
-                      <h4>Possible values</h4>
-                      <ul className="list-styled">
-                        {param.possibleValues.map(value =>
-                          <li key={value} className="little-spacer-top">
-                            <code>
-                              {value}
-                            </code>
-                          </li>
-                        )}
-                      </ul>
-                    </div>}
-
-                  {param.defaultValue &&
-                    <div className="little-spacer-top">
-                      <h4>Default value</h4>
-                      <code>
-                        {param.defaultValue}
-                      </code>
-                    </div>}
-
-                  {param.exampleValue &&
-                    <div className="little-spacer-top">
-                      <h4>Example value</h4>
-                      <code>
-                        {param.exampleValue}
-                      </code>
-                    </div>}
-
-                  {param.maxValuesAllowed != null &&
-                    <div className="little-spacer-top">
-                      <h4>Maximum allowed values</h4>
-                      <code>
-                        {param.maxValuesAllowed}
-                      </code>
-                    </div>}
-                </td>
-              </tr>
-            )}
-          </tbody>
-        </table>
-      </div>
-    );
-  }
-}
diff --git a/server/sonar-web/src/main/js/apps/web-api/components/Params.tsx b/server/sonar-web/src/main/js/apps/web-api/components/Params.tsx
new file mode 100644 (file)
index 0000000..e069180
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+import * as React from 'react';
+import InternalBadge from './InternalBadge';
+import DeprecatedBadge from './DeprecatedBadge';
+import { Param } from '../../../api/web-api';
+import { translate, translateWithParameters } from '../../../helpers/l10n';
+
+interface Props {
+  params: Param[];
+  showDeprecated: boolean;
+  showInternal: boolean;
+}
+
+export default function Params({ params, showDeprecated, showInternal }: Props) {
+  const displayedParameters = params
+    .filter(p => showDeprecated || !p.deprecatedSince)
+    .filter(p => showInternal || !p.internal);
+  return (
+    <div className="web-api-params">
+      <table>
+        <tbody>
+          {displayedParameters.map(param =>
+            <tr key={param.key}>
+              <td className="markdown" style={{ width: 180 }}>
+                <code>
+                  {param.key}
+                </code>
+
+                {param.internal &&
+                  <div className="little-spacer-top">
+                    <InternalBadge />
+                  </div>}
+
+                {param.deprecatedSince &&
+                  <div className="little-spacer-top">
+                    <DeprecatedBadge since={param.deprecatedSince} />
+                  </div>}
+
+                {showDeprecated &&
+                  param.deprecatedKey &&
+                  <div className="little-spacer-top">
+                    <code>
+                      {param.deprecatedKey}
+                    </code>
+                  </div>}
+
+                {showDeprecated &&
+                  param.deprecatedKey &&
+                  param.deprecatedKeySince &&
+                  <div className="little-spacer-top">
+                    <DeprecatedBadge since={param.deprecatedKeySince} />
+                  </div>}
+
+                <div className="note little-spacer-top">
+                  {param.required ? 'required' : 'optional'}
+                </div>
+
+                {param.since &&
+                  <div className="note little-spacer-top">
+                    {translateWithParameters('since_x', param.since)}
+                  </div>}
+              </td>
+
+              <td>
+                <div className="markdown" dangerouslySetInnerHTML={{ __html: param.description }} />
+              </td>
+
+              <td style={{ width: 250 }}>
+                {param.possibleValues &&
+                  <div>
+                    <h4>
+                      {translate('api_documentation.possible_values')}
+                    </h4>
+                    <ul className="list-styled">
+                      {param.possibleValues.map(value =>
+                        <li key={value} className="little-spacer-top">
+                          <code>
+                            {value}
+                          </code>
+                        </li>
+                      )}
+                    </ul>
+                  </div>}
+
+                {param.defaultValue &&
+                  <div className="little-spacer-top">
+                    <h4>
+                      {translate('api_documentation.default_values')}
+                    </h4>
+                    <code>
+                      {param.defaultValue}
+                    </code>
+                  </div>}
+
+                {param.exampleValue &&
+                  <div className="little-spacer-top">
+                    <h4>
+                      {translate('api_documentation.example_values')}
+                    </h4>
+                    <code>
+                      {param.exampleValue}
+                    </code>
+                  </div>}
+
+                {param.maxValuesAllowed != null &&
+                  <div className="little-spacer-top">
+                    <h4>
+                      {translate('api_documentation.max_values')}
+                    </h4>
+                    <code>
+                      {param.maxValuesAllowed}
+                    </code>
+                  </div>}
+              </td>
+            </tr>
+          )}
+        </tbody>
+      </table>
+    </div>
+  );
+}
diff --git a/server/sonar-web/src/main/js/apps/web-api/components/ResponseExample.js b/server/sonar-web/src/main/js/apps/web-api/components/ResponseExample.js
deleted file mode 100644 (file)
index 88bf497..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2017 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-import React from 'react';
-import { fetchResponseExample as fetchResponseExampleApi } from '../../../api/web-api';
-
-export default class ResponseExample extends React.PureComponent {
-  state = {};
-
-  componentDidMount() {
-    this.mounted = true;
-    this.fetchResponseExample();
-  }
-
-  componentDidUpdate(nextProps) {
-    if (nextProps.action !== this.props.action) {
-      this.fetchResponseExample();
-    }
-  }
-
-  componentWillUnmount() {
-    this.mounted = false;
-  }
-
-  fetchResponseExample() {
-    const { domain, action } = this.props;
-    fetchResponseExampleApi(domain.path, action.key).then(responseExample =>
-      this.setState({ responseExample })
-    );
-  }
-
-  render() {
-    const { responseExample } = this.state;
-
-    return (
-      <div className="web-api-response">
-        {responseExample &&
-          <pre style={{ whiteSpace: 'pre-wrap' }}>
-            {responseExample.example}
-          </pre>}
-      </div>
-    );
-  }
-}
diff --git a/server/sonar-web/src/main/js/apps/web-api/components/ResponseExample.tsx b/server/sonar-web/src/main/js/apps/web-api/components/ResponseExample.tsx
new file mode 100644 (file)
index 0000000..746fb39
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+import * as React from 'react';
+import {
+  Action,
+  Domain,
+  Example,
+  fetchResponseExample as fetchResponseExampleApi
+} from '../../../api/web-api';
+
+interface Props {
+  action: Action;
+  domain: Domain;
+}
+
+interface State {
+  responseExample?: Example;
+}
+
+export default class ResponseExample extends React.PureComponent<Props, State> {
+  mounted: boolean;
+  state: State = {};
+
+  componentDidMount() {
+    this.mounted = true;
+    this.fetchResponseExample();
+  }
+
+  componentDidUpdate(nextProps: Props) {
+    if (nextProps.action !== this.props.action) {
+      this.fetchResponseExample();
+    }
+  }
+
+  componentWillUnmount() {
+    this.mounted = false;
+  }
+
+  fetchResponseExample() {
+    const { domain, action } = this.props;
+    fetchResponseExampleApi(domain.path, action.key).then(responseExample =>
+      this.setState({ responseExample })
+    );
+  }
+
+  render() {
+    const { responseExample } = this.state;
+
+    return (
+      <div className="web-api-response">
+        {responseExample &&
+          <pre style={{ whiteSpace: 'pre-wrap' }}>
+            {responseExample.example}
+          </pre>}
+      </div>
+    );
+  }
+}
diff --git a/server/sonar-web/src/main/js/apps/web-api/components/Search.js b/server/sonar-web/src/main/js/apps/web-api/components/Search.js
deleted file mode 100644 (file)
index c08bbb8..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2017 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-// @flow
-import React from 'react';
-import { debounce } from 'lodash';
-import Checkbox from '../../../components/controls/Checkbox';
-import HelpIcon from '../../../components/icons-components/HelpIcon';
-import Tooltip from '../../../components/controls/Tooltip';
-import { translate } from '../../../helpers/l10n';
-
-/*::
-type Props = {
-  showDeprecated: boolean,
-  showInternal: boolean,
-  onSearch: string => void,
-  onToggleInternal: () => void,
-  onToggleDeprecated: () => void
-};
-*/
-
-/*::
-type State = {
-  query: string
-};
-*/
-
-export default class Search extends React.PureComponent {
-  /*:: actuallySearch: () => void; */
-  /*:: props: Props; */
-  /*:: state: State; */
-
-  constructor(props /*: Props */) {
-    super(props);
-    this.state = { query: '' };
-    this.actuallySearch = debounce(this.actuallySearch, 250);
-  }
-
-  handleSearch = (e /*: SyntheticInputEvent */) => {
-    const { value } = e.target;
-    this.setState({ query: value });
-    this.actuallySearch();
-  };
-
-  actuallySearch = () => {
-    const { onSearch } = this.props;
-    onSearch(this.state.query);
-  };
-
-  render() {
-    const { showInternal, showDeprecated, onToggleInternal, onToggleDeprecated } = this.props;
-
-    return (
-      <div className="web-api-search">
-        <div>
-          <i className="icon-search" />
-          <input
-            className="spacer-left input-large"
-            type="search"
-            value={this.state.query}
-            placeholder={translate('search_verb')}
-            onChange={this.handleSearch}
-          />
-        </div>
-
-        <div className="big-spacer-top">
-          <Checkbox checked={showInternal} onCheck={onToggleInternal}>
-            <span className="little-spacer-left">
-              {translate('api_documentation.show_deprecated')}
-            </span>
-          </Checkbox>
-          <Tooltip overlay={translate('api_documentation.internal_tooltip')} placement="right">
-            <span>
-              <HelpIcon className="spacer-left text-info" />
-            </span>
-          </Tooltip>
-        </div>
-
-        <div className="spacer-top">
-          <Checkbox checked={showDeprecated} onCheck={onToggleDeprecated}>
-            <span className="little-spacer-left">
-              {translate('api_documentation.show_internal')}
-            </span>
-          </Checkbox>
-          <Tooltip overlay={translate('api_documentation.deprecation_tooltip')} placement="right">
-            <span>
-              <HelpIcon className="spacer-left text-info" />
-            </span>
-          </Tooltip>
-        </div>
-      </div>
-    );
-  }
-}
diff --git a/server/sonar-web/src/main/js/apps/web-api/components/Search.tsx b/server/sonar-web/src/main/js/apps/web-api/components/Search.tsx
new file mode 100644 (file)
index 0000000..ab64ad6
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+import * as React from 'react';
+import { debounce } from 'lodash';
+import Checkbox from '../../../components/controls/Checkbox';
+import HelpIcon from '../../../components/icons-components/HelpIcon';
+import Tooltip from '../../../components/controls/Tooltip';
+import { translate } from '../../../helpers/l10n';
+
+interface Props {
+  showDeprecated: boolean;
+  showInternal: boolean;
+  onSearch: (search: string) => void;
+  onToggleInternal: () => void;
+  onToggleDeprecated: () => void;
+}
+
+interface State {
+  query: string;
+}
+
+export default class Search extends React.PureComponent<Props, State> {
+  constructor(props: Props) {
+    super(props);
+    this.state = { query: '' };
+    this.actuallySearch = debounce(this.actuallySearch, 250);
+  }
+
+  handleSearch = (e: React.SyntheticEvent<HTMLInputElement>) => {
+    this.setState({ query: e.currentTarget.value });
+    this.actuallySearch();
+  };
+
+  actuallySearch = () => this.props.onSearch(this.state.query);
+
+  render() {
+    const { showInternal, showDeprecated, onToggleInternal, onToggleDeprecated } = this.props;
+
+    return (
+      <div className="web-api-search">
+        <div>
+          <i className="icon-search" />
+          <input
+            className="spacer-left input-large"
+            type="search"
+            value={this.state.query}
+            placeholder={translate('search_verb')}
+            onChange={this.handleSearch}
+          />
+        </div>
+
+        <div className="big-spacer-top">
+          <Checkbox checked={showInternal} onCheck={onToggleInternal}>
+            <span className="little-spacer-left">
+              {translate('api_documentation.show_internal')}
+            </span>
+          </Checkbox>
+          <Tooltip overlay={translate('api_documentation.internal_tooltip')} placement="right">
+            <span>
+              <HelpIcon className="spacer-left text-info" />
+            </span>
+          </Tooltip>
+        </div>
+
+        <div className="spacer-top">
+          <Checkbox checked={showDeprecated} onCheck={onToggleDeprecated}>
+            <span className="little-spacer-left">
+              {translate('api_documentation.show_deprecated')}
+            </span>
+          </Checkbox>
+          <Tooltip overlay={translate('api_documentation.deprecation_tooltip')} placement="right">
+            <span>
+              <HelpIcon className="spacer-left text-info" />
+            </span>
+          </Tooltip>
+        </div>
+      </div>
+    );
+  }
+}
diff --git a/server/sonar-web/src/main/js/apps/web-api/components/WebApiApp.js b/server/sonar-web/src/main/js/apps/web-api/components/WebApiApp.js
deleted file mode 100644 (file)
index a8e8ead..0000000
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2017 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-// @flow
-import React from 'react';
-import PropTypes from 'prop-types';
-import Helmet from 'react-helmet';
-import { Link } from 'react-router';
-import { fetchWebApi } from '../../../api/web-api';
-import Menu from './Menu';
-import Search from './Search';
-import Domain from './Domain';
-import { getActionKey, isDomainPathActive } from '../utils';
-import { translate } from '../../../helpers/l10n';
-/*:: import type { Domain as DomainType } from '../../../api/web-api'; */
-import '../styles/web-api.css';
-
-/*::
-type State = {
-  domains: Array<DomainType>,
-  searchQuery: string,
-  showDeprecated: boolean,
-  showInternal: boolean
-};
-*/
-
-export default class WebApiApp extends React.PureComponent {
-  /*:: mounted: boolean; */
-  /*:: scrollToAction: () => void; */
-  state /*: State */ = {
-    domains: [],
-    searchQuery: '',
-    showDeprecated: false,
-    showInternal: false
-  };
-
-  componentDidMount() {
-    this.mounted = true;
-    this.fetchList();
-    const footer = document.getElementById('footer');
-    if (footer) {
-      footer.classList.add('search-navigator-footer');
-    }
-  }
-
-  componentDidUpdate() {
-    this.toggleInternalInitially();
-    this.scrollToAction();
-  }
-
-  componentWillUnmount() {
-    this.mounted = false;
-    const footer = document.getElementById('footer');
-    if (footer) {
-      footer.classList.remove('search-navigator-footer');
-    }
-  }
-
-  fetchList(cb /*: void | () => void */) {
-    fetchWebApi().then(domains => {
-      if (this.mounted) {
-        this.setState({ domains }, cb);
-      }
-    });
-  }
-
-  scrollToAction = () => {
-    const splat = this.props.params.splat || '';
-    this.scrollToElement(splat);
-  };
-
-  scrollToElement(id /*: string */) {
-    const element = document.getElementById(id);
-
-    if (element) {
-      const rect = element.getBoundingClientRect();
-      const top = rect.top + window.pageYOffset - 20;
-
-      window.scrollTo(0, top);
-    } else {
-      window.scrollTo(0, 0);
-    }
-  }
-
-  toggleInternalInitially() {
-    const splat = this.props.params.splat || '';
-    const { domains, showInternal } = this.state;
-
-    if (!showInternal) {
-      domains.forEach(domain => {
-        if (domain.path === splat && domain.internal) {
-          this.setState({ showInternal: true });
-        }
-        domain.actions.forEach(action => {
-          const actionKey = getActionKey(domain.path, action.key);
-          if (actionKey === splat && action.internal) {
-            this.setState({ showInternal: true });
-          }
-        });
-      });
-    }
-  }
-
-  handleSearch = (searchQuery /*: string */) => {
-    this.setState({ searchQuery });
-  };
-
-  handleToggleInternal = () => {
-    const splat = this.props.params.splat || '';
-    const { router } = this.context;
-    const { domains } = this.state;
-    const domain = domains.find(domain => isDomainPathActive(domain.path, splat));
-    const showInternal = !this.state.showInternal;
-
-    if (domain && domain.internal && !showInternal) {
-      router.push('/web_api');
-    }
-
-    this.setState({ showInternal });
-  };
-
-  handleToggleDeprecated = () => {
-    this.setState(state => ({ showDeprecated: !state.showDeprecated }));
-  };
-
-  render() {
-    const splat = this.props.params.splat || '';
-    const { domains, showInternal, showDeprecated, searchQuery } = this.state;
-
-    const domain = domains.find(domain => isDomainPathActive(domain.path, splat));
-
-    return (
-      <div className="layout-page">
-        <Helmet title={translate('api_documentation.page')} />
-        <div className="layout-page-side-outer">
-          <div className="layout-page-side" style={{ top: 30 }}>
-            <div className="layout-page-side-inner">
-              <div className="layout-page-filters">
-                <div className="web-api-page-header">
-                  <Link to="/web_api/">
-                    <h1>
-                      {translate('api_documentation.page')}
-                    </h1>
-                  </Link>
-                </div>
-
-                <Search
-                  showDeprecated={showDeprecated}
-                  showInternal={showInternal}
-                  onSearch={this.handleSearch}
-                  onToggleInternal={this.handleToggleInternal}
-                  onToggleDeprecated={this.handleToggleDeprecated}
-                />
-
-                <Menu
-                  domains={this.state.domains}
-                  showDeprecated={showDeprecated}
-                  showInternal={showInternal}
-                  searchQuery={searchQuery}
-                  splat={splat}
-                />
-              </div>
-            </div>
-          </div>
-        </div>
-
-        <div className="layout-page-main">
-          <div className="layout-page-main-inner">
-            {domain &&
-              <Domain
-                key={domain.path}
-                domain={domain}
-                showDeprecated={showDeprecated}
-                showInternal={showInternal}
-                searchQuery={searchQuery}
-              />}
-          </div>
-        </div>
-      </div>
-    );
-  }
-}
-
-WebApiApp.contextTypes = {
-  router: PropTypes.object.isRequired
-};
diff --git a/server/sonar-web/src/main/js/apps/web-api/components/WebApiApp.tsx b/server/sonar-web/src/main/js/apps/web-api/components/WebApiApp.tsx
new file mode 100644 (file)
index 0000000..9a346b3
--- /dev/null
@@ -0,0 +1,191 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+import * as React from 'react';
+import * as PropTypes from 'prop-types';
+import Helmet from 'react-helmet';
+import { Link } from 'react-router';
+import { Domain as DomainType, fetchWebApi } from '../../../api/web-api';
+import Menu from './Menu';
+import Search from './Search';
+import Domain from './Domain';
+import { getActionKey, isDomainPathActive } from '../utils';
+import { scrollToElement } from '../../../helpers/scrolling';
+import { translate } from '../../../helpers/l10n';
+import '../styles/web-api.css';
+
+interface Props {
+  params: { splat?: string };
+}
+
+interface State {
+  domains: DomainType[];
+  searchQuery: string;
+  showDeprecated: boolean;
+  showInternal: boolean;
+}
+
+export default class WebApiApp extends React.PureComponent<Props, State> {
+  mounted: boolean;
+  state: State = {
+    domains: [],
+    searchQuery: '',
+    showDeprecated: false,
+    showInternal: false
+  };
+
+  static contextTypes = {
+    router: PropTypes.object.isRequired
+  };
+
+  componentDidMount() {
+    this.mounted = true;
+    this.fetchList();
+    const footer = document.getElementById('footer');
+    if (footer) {
+      footer.classList.add('search-navigator-footer');
+    }
+  }
+
+  componentDidUpdate() {
+    this.toggleInternalInitially();
+    this.scrollToAction();
+  }
+
+  componentWillUnmount() {
+    this.mounted = false;
+    const footer = document.getElementById('footer');
+    if (footer) {
+      footer.classList.remove('search-navigator-footer');
+    }
+  }
+
+  fetchList(cb?: () => void) {
+    fetchWebApi().then(domains => {
+      if (this.mounted) {
+        this.setState({ domains }, cb);
+      }
+    });
+  }
+
+  scrollToAction = () => {
+    const splat = this.props.params.splat || '';
+    const action = document.getElementById(splat);
+    if (action) {
+      scrollToElement(action, { topOffset: 20, bottomOffset: 20 });
+    } else {
+      window.scrollTo(0, 0);
+    }
+  };
+
+  toggleInternalInitially() {
+    const splat = this.props.params.splat || '';
+    const { domains, showInternal } = this.state;
+
+    if (!showInternal) {
+      domains.forEach(domain => {
+        if (domain.path === splat && domain.internal) {
+          this.setState({ showInternal: true });
+        }
+        domain.actions.forEach(action => {
+          const actionKey = getActionKey(domain.path, action.key);
+          if (actionKey === splat && action.internal) {
+            this.setState({ showInternal: true });
+          }
+        });
+      });
+    }
+  }
+
+  handleSearch = (searchQuery: string) => this.setState({ searchQuery });
+
+  handleToggleInternal = () => {
+    const splat = this.props.params.splat || '';
+    const { router } = this.context;
+    const { domains } = this.state;
+    const domain = domains.find(domain => isDomainPathActive(domain.path, splat));
+    const showInternal = !this.state.showInternal;
+
+    if (domain && domain.internal && !showInternal) {
+      router.push('/web_api');
+    }
+
+    this.setState({ showInternal });
+  };
+
+  handleToggleDeprecated = () =>
+    this.setState(state => ({ showDeprecated: !state.showDeprecated }));
+
+  render() {
+    const splat = this.props.params.splat || '';
+    const { domains, showInternal, showDeprecated, searchQuery } = this.state;
+
+    const domain = domains.find(domain => isDomainPathActive(domain.path, splat));
+
+    return (
+      <div className="layout-page">
+        <Helmet title={translate('api_documentation.page')} />
+        <div className="layout-page-side-outer">
+          <div className="layout-page-side" style={{ top: 30 }}>
+            <div className="layout-page-side-inner">
+              <div className="layout-page-filters">
+                <div className="web-api-page-header">
+                  <Link to="/web_api/">
+                    <h1>
+                      {translate('api_documentation.page')}
+                    </h1>
+                  </Link>
+                </div>
+
+                <Search
+                  showDeprecated={showDeprecated}
+                  showInternal={showInternal}
+                  onSearch={this.handleSearch}
+                  onToggleInternal={this.handleToggleInternal}
+                  onToggleDeprecated={this.handleToggleDeprecated}
+                />
+
+                <Menu
+                  domains={this.state.domains}
+                  showDeprecated={showDeprecated}
+                  showInternal={showInternal}
+                  searchQuery={searchQuery}
+                  splat={splat}
+                />
+              </div>
+            </div>
+          </div>
+        </div>
+
+        <div className="layout-page-main">
+          <div className="layout-page-main-inner">
+            {domain &&
+              <Domain
+                key={domain.path}
+                domain={domain}
+                showDeprecated={showDeprecated}
+                showInternal={showInternal}
+                searchQuery={searchQuery}
+              />}
+          </div>
+        </div>
+      </div>
+    );
+  }
+}
diff --git a/server/sonar-web/src/main/js/apps/web-api/components/__tests__/Action-test.tsx b/server/sonar-web/src/main/js/apps/web-api/components/__tests__/Action-test.tsx
new file mode 100644 (file)
index 0000000..98c97e6
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+import * as React from 'react';
+import { shallow } from 'enzyme';
+import Action from '../Action';
+
+const ACTION = {
+  key: 'foo',
+  changelog: [{ description: 'Changelog desc', version: '5.0' }],
+  description: 'Foo Desc',
+  hasResponseExample: true,
+  internal: false,
+  params: [
+    {
+      key: 'param',
+      description: 'Param desc',
+      internal: true,
+      required: true
+    }
+  ],
+  post: false
+};
+const DOMAIN = {
+  actions: [ACTION],
+  path: 'foo',
+  description: 'API Foo',
+  deprecated: false,
+  internal: false
+};
+
+const PROPS = {
+  action: ACTION,
+  domain: DOMAIN,
+  showDeprecated: false,
+  showInternal: false
+};
+
+it('should render correctly', () => {
+  expect(shallow(<Action {...PROPS} />)).toMatchSnapshot();
+});
+
+it('should display the params', () => {
+  const wrapper = shallow(<Action {...PROPS} />);
+  wrapper.setState({ showParams: true });
+  expect(wrapper.find('Params')).toMatchSnapshot();
+});
+
+it('should display the response example', () => {
+  const wrapper = shallow(<Action {...PROPS} />);
+  wrapper.setState({ showResponse: true });
+  expect(wrapper.find('ResponseExample')).toMatchSnapshot();
+});
+
+it('should display the changelog', () => {
+  const wrapper = shallow(<Action {...PROPS} />);
+  wrapper.setState({ showChangelog: true });
+  expect(wrapper.find('ActionChangelog')).toMatchSnapshot();
+});
diff --git a/server/sonar-web/src/main/js/apps/web-api/components/__tests__/ActionChangelog-test.js b/server/sonar-web/src/main/js/apps/web-api/components/__tests__/ActionChangelog-test.js
deleted file mode 100644 (file)
index 380213b..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2017 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-import React from 'react';
-import { shallow } from 'enzyme';
-import ActionChangelog from '../ActionChangelog';
-
-it('should render', () => {
-  const changelog = [
-    { version: '5.0', description: 'foo' },
-    { version: '5.1', description: 'bar' }
-  ];
-  expect(shallow(<ActionChangelog changelog={changelog} />)).toMatchSnapshot();
-});
diff --git a/server/sonar-web/src/main/js/apps/web-api/components/__tests__/ActionChangelog-test.tsx b/server/sonar-web/src/main/js/apps/web-api/components/__tests__/ActionChangelog-test.tsx
new file mode 100644 (file)
index 0000000..d05d9ec
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+import * as React from 'react';
+import { shallow } from 'enzyme';
+import ActionChangelog from '../ActionChangelog';
+
+it('should render', () => {
+  const changelog = [
+    { version: '5.0', description: 'foo' },
+    { version: '5.1', description: 'bar' }
+  ];
+  expect(shallow(<ActionChangelog changelog={changelog} />)).toMatchSnapshot();
+});
diff --git a/server/sonar-web/src/main/js/apps/web-api/components/__tests__/Domain-test.js b/server/sonar-web/src/main/js/apps/web-api/components/__tests__/Domain-test.js
deleted file mode 100644 (file)
index 5608b8c..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2017 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-import React from 'react';
-import { shallow } from 'enzyme';
-import Domain from '../Domain';
-
-it('should render deprecated actions', () => {
-  const actions = [{ key: 'foo', deprecatedSince: '5.0' }];
-  const domain = { actions, path: 'api' };
-  expect(
-    shallow(<Domain domain={domain} searchQuery="" showDeprecated={true} />)
-  ).toMatchSnapshot();
-});
-
-it('should not render deprecated actions', () => {
-  const actions = [{ key: 'foo', deprecatedSince: '5.0' }];
-  const domain = { actions, path: 'api' };
-  expect(
-    shallow(<Domain domain={domain} searchQuery="" showDeprecated={false} />)
-  ).toMatchSnapshot();
-});
-
-it('should render internal actions', () => {
-  const actions = [{ key: 'foo', internal: true }];
-  const domain = { actions, path: 'api' };
-  expect(shallow(<Domain domain={domain} searchQuery="" showInternal={true} />)).toMatchSnapshot();
-});
-
-it('should not render internal actions', () => {
-  const actions = [{ key: 'foo', internal: true }];
-  const domain = { actions, path: 'api' };
-  expect(shallow(<Domain domain={domain} searchQuery="" showInternal={false} />)).toMatchSnapshot();
-});
-
-it('should render only actions matching the query', () => {
-  const actions = [{ key: 'foo' }, { key: 'bar' }];
-  const domain = { actions, path: 'api' };
-  expect(shallow(<Domain domain={domain} searchQuery="Foo" />)).toMatchSnapshot();
-});
-
-it('should also render actions with a description matching the query', () => {
-  const actions = [{ key: 'foo', description: 'foobar' }, { key: 'bar' }, { key: 'baz' }];
-  const domain = { actions, path: 'api' };
-  expect(
-    shallow(<Domain domain={domain} searchQuery="bar" showDeprecated={false} />)
-  ).toMatchSnapshot();
-});
diff --git a/server/sonar-web/src/main/js/apps/web-api/components/__tests__/Domain-test.tsx b/server/sonar-web/src/main/js/apps/web-api/components/__tests__/Domain-test.tsx
new file mode 100644 (file)
index 0000000..4114f49
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+import * as React from 'react';
+import { shallow } from 'enzyme';
+import Domain from '../Domain';
+
+const ACTION = {
+  key: 'foo',
+  changelog: [],
+  description: 'Foo Desc',
+  hasResponseExample: false,
+  internal: false,
+  post: false
+};
+const DOMAIN = {
+  actions: [ACTION],
+  path: 'api',
+  description: 'API Desc',
+  deprecated: false,
+  internal: false
+};
+const DEFAULT_PROPS = {
+  domain: DOMAIN,
+  showDeprecated: false,
+  showInternal: false,
+  searchQuery: ''
+};
+
+it('should render deprecated actions', () => {
+  const action = { ...ACTION, deprecatedSince: '5.0' };
+  const domain = { ...DOMAIN, actions: [action] };
+  expect(
+    shallow(<Domain {...DEFAULT_PROPS} domain={domain} showDeprecated={true} />)
+  ).toMatchSnapshot();
+});
+
+it('should not render deprecated actions', () => {
+  const action = { ...ACTION, deprecatedSince: '5.0' };
+  const domain = { ...DOMAIN, actions: [action] };
+  expect(
+    shallow(<Domain {...DEFAULT_PROPS} domain={domain} showDeprecated={false} />)
+  ).toMatchSnapshot();
+});
+
+it('should render internal actions', () => {
+  const action = { ...ACTION, internal: true };
+  const domain = { ...DOMAIN, actions: [action] };
+  expect(
+    shallow(<Domain {...DEFAULT_PROPS} domain={domain} showInternal={true} />)
+  ).toMatchSnapshot();
+});
+
+it('should not render internal actions', () => {
+  const action = { ...ACTION, internal: true };
+  const domain = { ...DOMAIN, actions: [action] };
+  expect(
+    shallow(<Domain {...DEFAULT_PROPS} domain={domain} showInternal={false} />)
+  ).toMatchSnapshot();
+});
+
+it('should render only actions matching the query', () => {
+  const actions = [ACTION, { ...ACTION, key: 'bar', description: 'Bar desc' }];
+  const domain = { ...DOMAIN, actions: actions };
+  expect(
+    shallow(<Domain {...DEFAULT_PROPS} domain={domain} searchQuery="Foo" />)
+  ).toMatchSnapshot();
+});
+
+it('should also render actions with a description matching the query', () => {
+  const actions = [
+    ACTION,
+    { ...ACTION, key: 'bar', description: 'Bar desc' },
+    { ...ACTION, key: 'baz', description: 'foobar' }
+  ];
+  const domain = { ...DOMAIN, actions: actions };
+  expect(
+    shallow(<Domain {...DEFAULT_PROPS} domain={domain} searchQuery="Foo" />)
+  ).toMatchSnapshot();
+});
diff --git a/server/sonar-web/src/main/js/apps/web-api/components/__tests__/Menu-test.tsx b/server/sonar-web/src/main/js/apps/web-api/components/__tests__/Menu-test.tsx
new file mode 100644 (file)
index 0000000..198f04a
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+import * as React from 'react';
+import { shallow } from 'enzyme';
+import Menu from '../Menu';
+
+const ACTION = {
+  key: 'foo',
+  changelog: [],
+  description: 'Foo Desc',
+  hasResponseExample: false,
+  internal: false,
+  post: false
+};
+const DOMAIN1 = {
+  actions: [ACTION],
+  path: 'foo',
+  description: 'API Foo',
+  deprecated: false,
+  internal: false
+};
+const DOMAIN2 = {
+  actions: [ACTION],
+  path: 'bar',
+  description: 'API Bar',
+  deprecated: false,
+  internal: false
+};
+const PROPS = {
+  domains: [DOMAIN1, DOMAIN2],
+  showDeprecated: false,
+  showInternal: false,
+  searchQuery: '',
+  splat: ''
+};
+
+it('should render deprecated domains', () => {
+  const domain = {
+    ...DOMAIN2,
+    deprecatedSince: '5.0',
+    actions: [{ ...ACTION, deprecatedSince: '5.0' }]
+  };
+  const domains = [DOMAIN1, domain];
+  expect(shallow(<Menu {...PROPS} domains={domains} showDeprecated={true} />)).toMatchSnapshot();
+});
+
+it('should not render deprecated domains', () => {
+  const domain = {
+    ...DOMAIN2,
+    deprecatedSince: '5.0',
+    actions: [{ ...ACTION, deprecatedSince: '5.0' }]
+  };
+  const domains = [DOMAIN1, domain];
+  expect(shallow(<Menu {...PROPS} domains={domains} showDeprecated={false} />)).toMatchSnapshot();
+});
+
+it('should render internal domains', () => {
+  const domain = { ...DOMAIN2, internal: true, actions: [{ ...ACTION, internal: true }] };
+  const domains = [DOMAIN1, domain];
+  expect(shallow(<Menu {...PROPS} domains={domains} showInternal={true} />)).toMatchSnapshot();
+});
+
+it('should not render internal domains', () => {
+  const domain = { ...DOMAIN2, internal: true, actions: [{ ...ACTION, internal: true }] };
+  const domains = [DOMAIN1, domain];
+  expect(shallow(<Menu {...PROPS} domains={domains} showInternal={false} />)).toMatchSnapshot();
+});
+
+it('should render only domains with an action matching the query', () => {
+  const domain = {
+    ...DOMAIN2,
+    actions: [{ ...ACTION, key: 'bar', path: 'bar', description: 'Bar Desc' }]
+  };
+  const domains = [DOMAIN1, domain];
+  expect(shallow(<Menu {...PROPS} domains={domains} searchQuery="Foo" />)).toMatchSnapshot();
+});
+
+it('should also render domains with an actions description matching the query', () => {
+  const domain = {
+    ...DOMAIN1,
+    path: 'baz',
+    description: 'API Baz',
+    actions: [{ ...ACTION, key: 'baz', path: 'baz', description: 'barbaz' }]
+  };
+  const domains = [DOMAIN1, DOMAIN2, domain];
+  expect(shallow(<Menu {...PROPS} domains={domains} searchQuery="Bar" />)).toMatchSnapshot();
+});
diff --git a/server/sonar-web/src/main/js/apps/web-api/components/__tests__/Params-test.js b/server/sonar-web/src/main/js/apps/web-api/components/__tests__/Params-test.js
deleted file mode 100644 (file)
index e8ca685..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2017 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-import React from 'react';
-import { shallow } from 'enzyme';
-import Params from '../Params';
-
-it('should render deprecated parameters', () => {
-  const params = [
-    {
-      key: 'foo',
-      deprecatedSince: '5.0'
-    }
-  ];
-  expect(shallow(<Params params={params} showDeprecated={true} />)).toMatchSnapshot();
-});
-
-it('should not render deprecated parameters', () => {
-  const params = [
-    {
-      key: 'foo',
-      deprecatedSince: '5.0'
-    }
-  ];
-  expect(shallow(<Params params={params} showDeprecated={false} />)).toMatchSnapshot();
-});
-
-it('should render deprecated key', () => {
-  const params = [
-    {
-      key: 'foo',
-      deprecatedKey: 'foo-deprecated',
-      deprecatedKeySince: '5.0'
-    }
-  ];
-  expect(shallow(<Params params={params} showDeprecated={true} />)).toMatchSnapshot();
-});
diff --git a/server/sonar-web/src/main/js/apps/web-api/components/__tests__/Params-test.tsx b/server/sonar-web/src/main/js/apps/web-api/components/__tests__/Params-test.tsx
new file mode 100644 (file)
index 0000000..480b56f
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+import * as React from 'react';
+import { shallow } from 'enzyme';
+import Params from '../Params';
+
+const DEFAULT_PARAM = {
+  key: 'foo',
+  description: 'Foo desc',
+  internal: false,
+  required: false
+};
+
+it('should render deprecated and internal parameters', () => {
+  const params = [
+    { ...DEFAULT_PARAM, deprecatedSince: '5.0' },
+    { ...DEFAULT_PARAM, deprecatedSince: '5.0', internal: true }
+  ];
+  expect(
+    shallow(<Params params={params} showDeprecated={true} showInternal={true} />)
+  ).toMatchSnapshot();
+});
+
+it('should not render deprecated parameters', () => {
+  const params = [{ ...DEFAULT_PARAM, deprecatedSince: '5.0' }];
+  expect(
+    shallow(<Params params={params} showDeprecated={false} showInternal={false} />)
+  ).toMatchSnapshot();
+});
+
+it('should render deprecated key', () => {
+  const params = [
+    { ...DEFAULT_PARAM, deprecatedKey: 'foo-deprecated', deprecatedSince: '5.0' },
+    { ...DEFAULT_PARAM, deprecatedSince: '5.0', internal: true }
+  ];
+  expect(
+    shallow(<Params params={params} showDeprecated={true} showInternal={false} />)
+  ).toMatchSnapshot();
+});
diff --git a/server/sonar-web/src/main/js/apps/web-api/components/__tests__/ResponseExample-test.tsx b/server/sonar-web/src/main/js/apps/web-api/components/__tests__/ResponseExample-test.tsx
new file mode 100644 (file)
index 0000000..5e90e29
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+import * as React from 'react';
+import { shallow } from 'enzyme';
+import ResponseExample from '../ResponseExample';
+
+const ACTION = {
+  key: 'foo',
+  changelog: [],
+  description: 'Foo Desc',
+  hasResponseExample: false,
+  internal: false,
+  post: false
+};
+const DOMAIN = {
+  actions: [ACTION],
+  path: 'foo',
+  description: 'API Foo',
+  deprecated: false,
+  internal: false
+};
+
+const PROPS = {
+  action: ACTION,
+  domain: DOMAIN
+};
+
+it('should render correctly after fetching an example', () => {
+  const wrapper = shallow(<ResponseExample {...PROPS} />);
+  expect(wrapper).toMatchSnapshot();
+  wrapper.setState({ responseExample: { format: 'json', example: 'my example' } });
+  expect(wrapper).toMatchSnapshot();
+});
diff --git a/server/sonar-web/src/main/js/apps/web-api/components/__tests__/Search-test.tsx b/server/sonar-web/src/main/js/apps/web-api/components/__tests__/Search-test.tsx
new file mode 100644 (file)
index 0000000..a7f6a81
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+import * as React from 'react';
+import { shallow } from 'enzyme';
+import Search from '../Search';
+
+const PROPS = {
+  showDeprecated: false,
+  showInternal: false,
+  onSearch: () => {},
+  onToggleInternal: () => {},
+  onToggleDeprecated: () => {}
+};
+
+it('should render correctly', () => {
+  expect(shallow(<Search {...PROPS} />)).toMatchSnapshot();
+});
diff --git a/server/sonar-web/src/main/js/apps/web-api/components/__tests__/__snapshots__/Action-test.tsx.snap b/server/sonar-web/src/main/js/apps/web-api/components/__tests__/__snapshots__/Action-test.tsx.snap
new file mode 100644 (file)
index 0000000..02cc7f1
--- /dev/null
@@ -0,0 +1,160 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should display the changelog 1`] = `
+<ActionChangelog
+  changelog={
+    Array [
+      Object {
+        "description": "Changelog desc",
+        "version": "5.0",
+      },
+    ]
+  }
+/>
+`;
+
+exports[`should display the params 1`] = `
+<Params
+  params={
+    Array [
+      Object {
+        "description": "Param desc",
+        "internal": true,
+        "key": "param",
+        "required": true,
+      },
+    ]
+  }
+  showDeprecated={false}
+  showInternal={false}
+/>
+`;
+
+exports[`should display the response example 1`] = `
+<ResponseExample
+  action={
+    Object {
+      "changelog": Array [
+        Object {
+          "description": "Changelog desc",
+          "version": "5.0",
+        },
+      ],
+      "description": "Foo Desc",
+      "hasResponseExample": true,
+      "internal": false,
+      "key": "foo",
+      "params": Array [
+        Object {
+          "description": "Param desc",
+          "internal": true,
+          "key": "param",
+          "required": true,
+        },
+      ],
+      "post": false,
+    }
+  }
+  domain={
+    Object {
+      "actions": Array [
+        Object {
+          "changelog": Array [
+            Object {
+              "description": "Changelog desc",
+              "version": "5.0",
+            },
+          ],
+          "description": "Foo Desc",
+          "hasResponseExample": true,
+          "internal": false,
+          "key": "foo",
+          "params": Array [
+            Object {
+              "description": "Param desc",
+              "internal": true,
+              "key": "param",
+              "required": true,
+            },
+          ],
+          "post": false,
+        },
+      ],
+      "deprecated": false,
+      "description": "API Foo",
+      "internal": false,
+      "path": "foo",
+    }
+  }
+/>
+`;
+
+exports[`should render correctly 1`] = `
+<div
+  className="web-api-action"
+  id="foo/foo"
+>
+  <header
+    className="web-api-action-header"
+  >
+    <Link
+      className="spacer-right link-no-underline"
+      onlyActiveOnIndex={false}
+      style={Object {}}
+      to={
+        Object {
+          "pathname": "/web_api/foo/foo",
+        }
+      }
+    >
+      <LinkIcon />
+    </Link>
+    <h3
+      className="web-api-action-title"
+    >
+      GET
+       
+      foo/foo
+    </h3>
+  </header>
+  <div
+    className="web-api-action-description markdown"
+    dangerouslySetInnerHTML={
+      Object {
+        "__html": "Foo Desc",
+      }
+    }
+  />
+  <ul
+    className="web-api-action-actions tabs"
+  >
+    <li>
+      <a
+        className=""
+        href="#"
+        onClick={[Function]}
+      >
+        api_documentation.parameters
+      </a>
+    </li>
+    <li>
+      <a
+        className=""
+        href="#"
+        onClick={[Function]}
+      >
+        api_documentation.response_example
+      </a>
+    </li>
+    <li>
+      <a
+        className=""
+        href="#"
+        onClick={[Function]}
+      >
+        api_documentation.changelog
+      </a>
+    </li>
+  </ul>
+</div>
+`;
diff --git a/server/sonar-web/src/main/js/apps/web-api/components/__tests__/__snapshots__/ActionChangelog-test.js.snap b/server/sonar-web/src/main/js/apps/web-api/components/__tests__/__snapshots__/ActionChangelog-test.js.snap
deleted file mode 100644 (file)
index 8c3eb7a..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render 1`] = `
-<ul
-  className="big-spacer-top"
->
-  <li
-    className="spacer-top"
-  >
-    <span
-      className="spacer-right badge"
-    >
-      5.0
-    </span>
-    foo
-  </li>
-  <li
-    className="spacer-top"
-  >
-    <span
-      className="spacer-right badge"
-    >
-      5.1
-    </span>
-    bar
-  </li>
-</ul>
-`;
diff --git a/server/sonar-web/src/main/js/apps/web-api/components/__tests__/__snapshots__/ActionChangelog-test.tsx.snap b/server/sonar-web/src/main/js/apps/web-api/components/__tests__/__snapshots__/ActionChangelog-test.tsx.snap
new file mode 100644 (file)
index 0000000..8c3eb7a
--- /dev/null
@@ -0,0 +1,28 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render 1`] = `
+<ul
+  className="big-spacer-top"
+>
+  <li
+    className="spacer-top"
+  >
+    <span
+      className="spacer-right badge"
+    >
+      5.0
+    </span>
+    foo
+  </li>
+  <li
+    className="spacer-top"
+  >
+    <span
+      className="spacer-right badge"
+    >
+      5.1
+    </span>
+    bar
+  </li>
+</ul>
+`;
diff --git a/server/sonar-web/src/main/js/apps/web-api/components/__tests__/__snapshots__/Domain-test.js.snap b/server/sonar-web/src/main/js/apps/web-api/components/__tests__/__snapshots__/Domain-test.js.snap
deleted file mode 100644 (file)
index 8a1c7fd..0000000
+++ /dev/null
@@ -1,230 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should also render actions with a description matching the query 1`] = `
-<div
-  className="web-api-domain"
->
-  <header
-    className="web-api-domain-header"
-  >
-    <h2
-      className="web-api-domain-title"
-    >
-      api
-    </h2>
-  </header>
-  <div
-    className="web-api-domain-actions"
-  >
-    <Action
-      action={
-        Object {
-          "description": "foobar",
-          "key": "foo",
-        }
-      }
-      domain={
-        Object {
-          "actions": Array [
-            Object {
-              "description": "foobar",
-              "key": "foo",
-            },
-            Object {
-              "key": "bar",
-            },
-            Object {
-              "key": "baz",
-            },
-          ],
-          "path": "api",
-        }
-      }
-      showDeprecated={false}
-    />
-    <Action
-      action={
-        Object {
-          "key": "bar",
-        }
-      }
-      domain={
-        Object {
-          "actions": Array [
-            Object {
-              "description": "foobar",
-              "key": "foo",
-            },
-            Object {
-              "key": "bar",
-            },
-            Object {
-              "key": "baz",
-            },
-          ],
-          "path": "api",
-        }
-      }
-      showDeprecated={false}
-    />
-  </div>
-</div>
-`;
-
-exports[`should not render deprecated actions 1`] = `
-<div
-  className="web-api-domain"
->
-  <header
-    className="web-api-domain-header"
-  >
-    <h2
-      className="web-api-domain-title"
-    >
-      api
-    </h2>
-  </header>
-  <div
-    className="web-api-domain-actions"
-  />
-</div>
-`;
-
-exports[`should not render internal actions 1`] = `
-<div
-  className="web-api-domain"
->
-  <header
-    className="web-api-domain-header"
-  >
-    <h2
-      className="web-api-domain-title"
-    >
-      api
-    </h2>
-  </header>
-  <div
-    className="web-api-domain-actions"
-  />
-</div>
-`;
-
-exports[`should render deprecated actions 1`] = `
-<div
-  className="web-api-domain"
->
-  <header
-    className="web-api-domain-header"
-  >
-    <h2
-      className="web-api-domain-title"
-    >
-      api
-    </h2>
-  </header>
-  <div
-    className="web-api-domain-actions"
-  >
-    <Action
-      action={
-        Object {
-          "deprecatedSince": "5.0",
-          "key": "foo",
-        }
-      }
-      domain={
-        Object {
-          "actions": Array [
-            Object {
-              "deprecatedSince": "5.0",
-              "key": "foo",
-            },
-          ],
-          "path": "api",
-        }
-      }
-      showDeprecated={true}
-    />
-  </div>
-</div>
-`;
-
-exports[`should render internal actions 1`] = `
-<div
-  className="web-api-domain"
->
-  <header
-    className="web-api-domain-header"
-  >
-    <h2
-      className="web-api-domain-title"
-    >
-      api
-    </h2>
-  </header>
-  <div
-    className="web-api-domain-actions"
-  >
-    <Action
-      action={
-        Object {
-          "internal": true,
-          "key": "foo",
-        }
-      }
-      domain={
-        Object {
-          "actions": Array [
-            Object {
-              "internal": true,
-              "key": "foo",
-            },
-          ],
-          "path": "api",
-        }
-      }
-      showInternal={true}
-    />
-  </div>
-</div>
-`;
-
-exports[`should render only actions matching the query 1`] = `
-<div
-  className="web-api-domain"
->
-  <header
-    className="web-api-domain-header"
-  >
-    <h2
-      className="web-api-domain-title"
-    >
-      api
-    </h2>
-  </header>
-  <div
-    className="web-api-domain-actions"
-  >
-    <Action
-      action={
-        Object {
-          "key": "foo",
-        }
-      }
-      domain={
-        Object {
-          "actions": Array [
-            Object {
-              "key": "foo",
-            },
-            Object {
-              "key": "bar",
-            },
-          ],
-          "path": "api",
-        }
-      }
-    />
-  </div>
-</div>
-`;
diff --git a/server/sonar-web/src/main/js/apps/web-api/components/__tests__/__snapshots__/Domain-test.tsx.snap b/server/sonar-web/src/main/js/apps/web-api/components/__tests__/__snapshots__/Domain-test.tsx.snap
new file mode 100644 (file)
index 0000000..e1c93d2
--- /dev/null
@@ -0,0 +1,369 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should also render actions with a description matching the query 1`] = `
+<div
+  className="web-api-domain"
+>
+  <header
+    className="web-api-domain-header"
+  >
+    <h2
+      className="web-api-domain-title"
+    >
+      api
+    </h2>
+  </header>
+  <div
+    className="web-api-domain-description markdown"
+    dangerouslySetInnerHTML={
+      Object {
+        "__html": "API Desc",
+      }
+    }
+  />
+  <div
+    className="web-api-domain-actions"
+  >
+    <Action
+      action={
+        Object {
+          "changelog": Array [],
+          "description": "Foo Desc",
+          "hasResponseExample": false,
+          "internal": false,
+          "key": "foo",
+          "post": false,
+        }
+      }
+      domain={
+        Object {
+          "actions": Array [
+            Object {
+              "changelog": Array [],
+              "description": "Foo Desc",
+              "hasResponseExample": false,
+              "internal": false,
+              "key": "foo",
+              "post": false,
+            },
+            Object {
+              "changelog": Array [],
+              "description": "Bar desc",
+              "hasResponseExample": false,
+              "internal": false,
+              "key": "bar",
+              "post": false,
+            },
+            Object {
+              "changelog": Array [],
+              "description": "foobar",
+              "hasResponseExample": false,
+              "internal": false,
+              "key": "baz",
+              "post": false,
+            },
+          ],
+          "deprecated": false,
+          "description": "API Desc",
+          "internal": false,
+          "path": "api",
+        }
+      }
+      showDeprecated={false}
+      showInternal={false}
+    />
+    <Action
+      action={
+        Object {
+          "changelog": Array [],
+          "description": "foobar",
+          "hasResponseExample": false,
+          "internal": false,
+          "key": "baz",
+          "post": false,
+        }
+      }
+      domain={
+        Object {
+          "actions": Array [
+            Object {
+              "changelog": Array [],
+              "description": "Foo Desc",
+              "hasResponseExample": false,
+              "internal": false,
+              "key": "foo",
+              "post": false,
+            },
+            Object {
+              "changelog": Array [],
+              "description": "Bar desc",
+              "hasResponseExample": false,
+              "internal": false,
+              "key": "bar",
+              "post": false,
+            },
+            Object {
+              "changelog": Array [],
+              "description": "foobar",
+              "hasResponseExample": false,
+              "internal": false,
+              "key": "baz",
+              "post": false,
+            },
+          ],
+          "deprecated": false,
+          "description": "API Desc",
+          "internal": false,
+          "path": "api",
+        }
+      }
+      showDeprecated={false}
+      showInternal={false}
+    />
+  </div>
+</div>
+`;
+
+exports[`should not render deprecated actions 1`] = `
+<div
+  className="web-api-domain"
+>
+  <header
+    className="web-api-domain-header"
+  >
+    <h2
+      className="web-api-domain-title"
+    >
+      api
+    </h2>
+  </header>
+  <div
+    className="web-api-domain-description markdown"
+    dangerouslySetInnerHTML={
+      Object {
+        "__html": "API Desc",
+      }
+    }
+  />
+  <div
+    className="web-api-domain-actions"
+  />
+</div>
+`;
+
+exports[`should not render internal actions 1`] = `
+<div
+  className="web-api-domain"
+>
+  <header
+    className="web-api-domain-header"
+  >
+    <h2
+      className="web-api-domain-title"
+    >
+      api
+    </h2>
+  </header>
+  <div
+    className="web-api-domain-description markdown"
+    dangerouslySetInnerHTML={
+      Object {
+        "__html": "API Desc",
+      }
+    }
+  />
+  <div
+    className="web-api-domain-actions"
+  />
+</div>
+`;
+
+exports[`should render deprecated actions 1`] = `
+<div
+  className="web-api-domain"
+>
+  <header
+    className="web-api-domain-header"
+  >
+    <h2
+      className="web-api-domain-title"
+    >
+      api
+    </h2>
+  </header>
+  <div
+    className="web-api-domain-description markdown"
+    dangerouslySetInnerHTML={
+      Object {
+        "__html": "API Desc",
+      }
+    }
+  />
+  <div
+    className="web-api-domain-actions"
+  >
+    <Action
+      action={
+        Object {
+          "changelog": Array [],
+          "deprecatedSince": "5.0",
+          "description": "Foo Desc",
+          "hasResponseExample": false,
+          "internal": false,
+          "key": "foo",
+          "post": false,
+        }
+      }
+      domain={
+        Object {
+          "actions": Array [
+            Object {
+              "changelog": Array [],
+              "deprecatedSince": "5.0",
+              "description": "Foo Desc",
+              "hasResponseExample": false,
+              "internal": false,
+              "key": "foo",
+              "post": false,
+            },
+          ],
+          "deprecated": false,
+          "description": "API Desc",
+          "internal": false,
+          "path": "api",
+        }
+      }
+      showDeprecated={true}
+      showInternal={false}
+    />
+  </div>
+</div>
+`;
+
+exports[`should render internal actions 1`] = `
+<div
+  className="web-api-domain"
+>
+  <header
+    className="web-api-domain-header"
+  >
+    <h2
+      className="web-api-domain-title"
+    >
+      api
+    </h2>
+  </header>
+  <div
+    className="web-api-domain-description markdown"
+    dangerouslySetInnerHTML={
+      Object {
+        "__html": "API Desc",
+      }
+    }
+  />
+  <div
+    className="web-api-domain-actions"
+  >
+    <Action
+      action={
+        Object {
+          "changelog": Array [],
+          "description": "Foo Desc",
+          "hasResponseExample": false,
+          "internal": true,
+          "key": "foo",
+          "post": false,
+        }
+      }
+      domain={
+        Object {
+          "actions": Array [
+            Object {
+              "changelog": Array [],
+              "description": "Foo Desc",
+              "hasResponseExample": false,
+              "internal": true,
+              "key": "foo",
+              "post": false,
+            },
+          ],
+          "deprecated": false,
+          "description": "API Desc",
+          "internal": false,
+          "path": "api",
+        }
+      }
+      showDeprecated={false}
+      showInternal={true}
+    />
+  </div>
+</div>
+`;
+
+exports[`should render only actions matching the query 1`] = `
+<div
+  className="web-api-domain"
+>
+  <header
+    className="web-api-domain-header"
+  >
+    <h2
+      className="web-api-domain-title"
+    >
+      api
+    </h2>
+  </header>
+  <div
+    className="web-api-domain-description markdown"
+    dangerouslySetInnerHTML={
+      Object {
+        "__html": "API Desc",
+      }
+    }
+  />
+  <div
+    className="web-api-domain-actions"
+  >
+    <Action
+      action={
+        Object {
+          "changelog": Array [],
+          "description": "Foo Desc",
+          "hasResponseExample": false,
+          "internal": false,
+          "key": "foo",
+          "post": false,
+        }
+      }
+      domain={
+        Object {
+          "actions": Array [
+            Object {
+              "changelog": Array [],
+              "description": "Foo Desc",
+              "hasResponseExample": false,
+              "internal": false,
+              "key": "foo",
+              "post": false,
+            },
+            Object {
+              "changelog": Array [],
+              "description": "Bar desc",
+              "hasResponseExample": false,
+              "internal": false,
+              "key": "bar",
+              "post": false,
+            },
+          ],
+          "deprecated": false,
+          "description": "API Desc",
+          "internal": false,
+          "path": "api",
+        }
+      }
+      showDeprecated={false}
+      showInternal={false}
+    />
+  </div>
+</div>
+`;
diff --git a/server/sonar-web/src/main/js/apps/web-api/components/__tests__/__snapshots__/Menu-test.tsx.snap b/server/sonar-web/src/main/js/apps/web-api/components/__tests__/__snapshots__/Menu-test.tsx.snap
new file mode 100644 (file)
index 0000000..34329aa
--- /dev/null
@@ -0,0 +1,248 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should also render domains with an actions description matching the query 1`] = `
+<div
+  className="api-documentation-results panel"
+>
+  <div
+    className="list-group"
+  >
+    <Link
+      className="list-group-item"
+      onlyActiveOnIndex={false}
+      style={Object {}}
+      to="/web_api/bar"
+    >
+      <h3
+        className="list-group-item-heading"
+      >
+        bar
+      </h3>
+      <div
+        className="list-group-item-text markdown"
+        dangerouslySetInnerHTML={
+          Object {
+            "__html": "API Bar",
+          }
+        }
+      />
+    </Link>
+    <Link
+      className="list-group-item"
+      onlyActiveOnIndex={false}
+      style={Object {}}
+      to="/web_api/baz"
+    >
+      <h3
+        className="list-group-item-heading"
+      >
+        baz
+      </h3>
+      <div
+        className="list-group-item-text markdown"
+        dangerouslySetInnerHTML={
+          Object {
+            "__html": "API Baz",
+          }
+        }
+      />
+    </Link>
+  </div>
+</div>
+`;
+
+exports[`should not render deprecated domains 1`] = `
+<div
+  className="api-documentation-results panel"
+>
+  <div
+    className="list-group"
+  >
+    <Link
+      className="list-group-item"
+      onlyActiveOnIndex={false}
+      style={Object {}}
+      to="/web_api/foo"
+    >
+      <h3
+        className="list-group-item-heading"
+      >
+        foo
+      </h3>
+      <div
+        className="list-group-item-text markdown"
+        dangerouslySetInnerHTML={
+          Object {
+            "__html": "API Foo",
+          }
+        }
+      />
+    </Link>
+  </div>
+</div>
+`;
+
+exports[`should not render internal domains 1`] = `
+<div
+  className="api-documentation-results panel"
+>
+  <div
+    className="list-group"
+  >
+    <Link
+      className="list-group-item"
+      onlyActiveOnIndex={false}
+      style={Object {}}
+      to="/web_api/foo"
+    >
+      <h3
+        className="list-group-item-heading"
+      >
+        foo
+      </h3>
+      <div
+        className="list-group-item-text markdown"
+        dangerouslySetInnerHTML={
+          Object {
+            "__html": "API Foo",
+          }
+        }
+      />
+    </Link>
+  </div>
+</div>
+`;
+
+exports[`should render deprecated domains 1`] = `
+<div
+  className="api-documentation-results panel"
+>
+  <div
+    className="list-group"
+  >
+    <Link
+      className="list-group-item"
+      onlyActiveOnIndex={false}
+      style={Object {}}
+      to="/web_api/foo"
+    >
+      <h3
+        className="list-group-item-heading"
+      >
+        foo
+      </h3>
+      <div
+        className="list-group-item-text markdown"
+        dangerouslySetInnerHTML={
+          Object {
+            "__html": "API Foo",
+          }
+        }
+      />
+    </Link>
+    <Link
+      className="list-group-item"
+      onlyActiveOnIndex={false}
+      style={Object {}}
+      to="/web_api/bar"
+    >
+      <h3
+        className="list-group-item-heading"
+      >
+        bar
+      </h3>
+      <div
+        className="list-group-item-text markdown"
+        dangerouslySetInnerHTML={
+          Object {
+            "__html": "API Bar",
+          }
+        }
+      />
+    </Link>
+  </div>
+</div>
+`;
+
+exports[`should render internal domains 1`] = `
+<div
+  className="api-documentation-results panel"
+>
+  <div
+    className="list-group"
+  >
+    <Link
+      className="list-group-item"
+      onlyActiveOnIndex={false}
+      style={Object {}}
+      to="/web_api/foo"
+    >
+      <h3
+        className="list-group-item-heading"
+      >
+        foo
+      </h3>
+      <div
+        className="list-group-item-text markdown"
+        dangerouslySetInnerHTML={
+          Object {
+            "__html": "API Foo",
+          }
+        }
+      />
+    </Link>
+    <Link
+      className="list-group-item"
+      onlyActiveOnIndex={false}
+      style={Object {}}
+      to="/web_api/bar"
+    >
+      <h3
+        className="list-group-item-heading"
+      >
+        bar
+        <InternalBadge />
+      </h3>
+      <div
+        className="list-group-item-text markdown"
+        dangerouslySetInnerHTML={
+          Object {
+            "__html": "API Bar",
+          }
+        }
+      />
+    </Link>
+  </div>
+</div>
+`;
+
+exports[`should render only domains with an action matching the query 1`] = `
+<div
+  className="api-documentation-results panel"
+>
+  <div
+    className="list-group"
+  >
+    <Link
+      className="list-group-item"
+      onlyActiveOnIndex={false}
+      style={Object {}}
+      to="/web_api/foo"
+    >
+      <h3
+        className="list-group-item-heading"
+      >
+        foo
+      </h3>
+      <div
+        className="list-group-item-text markdown"
+        dangerouslySetInnerHTML={
+          Object {
+            "__html": "API Foo",
+          }
+        }
+      />
+    </Link>
+  </div>
+</div>
+`;
diff --git a/server/sonar-web/src/main/js/apps/web-api/components/__tests__/__snapshots__/Params-test.js.snap b/server/sonar-web/src/main/js/apps/web-api/components/__tests__/__snapshots__/Params-test.js.snap
deleted file mode 100644 (file)
index 294cc61..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should not render deprecated parameters 1`] = `
-<div
-  className="web-api-params"
->
-  <table>
-    <tbody />
-  </table>
-</div>
-`;
-
-exports[`should render deprecated key 1`] = `
-<div
-  className="web-api-params"
->
-  <table>
-    <tbody>
-      <tr>
-        <td
-          className="markdown"
-          style={
-            Object {
-              "width": 180,
-            }
-          }
-        >
-          <code>
-            foo
-          </code>
-          <div
-            className="little-spacer-top"
-          >
-            <code>
-              foo-deprecated
-            </code>
-          </div>
-          <div
-            className="little-spacer-top"
-          >
-            <DeprecatedBadge
-              since="5.0"
-            />
-          </div>
-          <div
-            className="note little-spacer-top"
-          >
-            optional
-          </div>
-        </td>
-        <td>
-          <div
-            className="markdown"
-            dangerouslySetInnerHTML={
-              Object {
-                "__html": undefined,
-              }
-            }
-          />
-        </td>
-        <td
-          style={
-            Object {
-              "width": 250,
-            }
-          }
-        />
-      </tr>
-    </tbody>
-  </table>
-</div>
-`;
-
-exports[`should render deprecated parameters 1`] = `
-<div
-  className="web-api-params"
->
-  <table>
-    <tbody>
-      <tr>
-        <td
-          className="markdown"
-          style={
-            Object {
-              "width": 180,
-            }
-          }
-        >
-          <code>
-            foo
-          </code>
-          <div
-            className="little-spacer-top"
-          >
-            <DeprecatedBadge
-              since="5.0"
-            />
-          </div>
-          <div
-            className="note little-spacer-top"
-          >
-            optional
-          </div>
-        </td>
-        <td>
-          <div
-            className="markdown"
-            dangerouslySetInnerHTML={
-              Object {
-                "__html": undefined,
-              }
-            }
-          />
-        </td>
-        <td
-          style={
-            Object {
-              "width": 250,
-            }
-          }
-        />
-      </tr>
-    </tbody>
-  </table>
-</div>
-`;
diff --git a/server/sonar-web/src/main/js/apps/web-api/components/__tests__/__snapshots__/Params-test.tsx.snap b/server/sonar-web/src/main/js/apps/web-api/components/__tests__/__snapshots__/Params-test.tsx.snap
new file mode 100644 (file)
index 0000000..c6a7552
--- /dev/null
@@ -0,0 +1,174 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should not render deprecated parameters 1`] = `
+<div
+  className="web-api-params"
+>
+  <table>
+    <tbody />
+  </table>
+</div>
+`;
+
+exports[`should render deprecated and internal parameters 1`] = `
+<div
+  className="web-api-params"
+>
+  <table>
+    <tbody>
+      <tr>
+        <td
+          className="markdown"
+          style={
+            Object {
+              "width": 180,
+            }
+          }
+        >
+          <code>
+            foo
+          </code>
+          <div
+            className="little-spacer-top"
+          >
+            <DeprecatedBadge
+              since="5.0"
+            />
+          </div>
+          <div
+            className="note little-spacer-top"
+          >
+            optional
+          </div>
+        </td>
+        <td>
+          <div
+            className="markdown"
+            dangerouslySetInnerHTML={
+              Object {
+                "__html": "Foo desc",
+              }
+            }
+          />
+        </td>
+        <td
+          style={
+            Object {
+              "width": 250,
+            }
+          }
+        />
+      </tr>
+      <tr>
+        <td
+          className="markdown"
+          style={
+            Object {
+              "width": 180,
+            }
+          }
+        >
+          <code>
+            foo
+          </code>
+          <div
+            className="little-spacer-top"
+          >
+            <InternalBadge />
+          </div>
+          <div
+            className="little-spacer-top"
+          >
+            <DeprecatedBadge
+              since="5.0"
+            />
+          </div>
+          <div
+            className="note little-spacer-top"
+          >
+            optional
+          </div>
+        </td>
+        <td>
+          <div
+            className="markdown"
+            dangerouslySetInnerHTML={
+              Object {
+                "__html": "Foo desc",
+              }
+            }
+          />
+        </td>
+        <td
+          style={
+            Object {
+              "width": 250,
+            }
+          }
+        />
+      </tr>
+    </tbody>
+  </table>
+</div>
+`;
+
+exports[`should render deprecated key 1`] = `
+<div
+  className="web-api-params"
+>
+  <table>
+    <tbody>
+      <tr>
+        <td
+          className="markdown"
+          style={
+            Object {
+              "width": 180,
+            }
+          }
+        >
+          <code>
+            foo
+          </code>
+          <div
+            className="little-spacer-top"
+          >
+            <DeprecatedBadge
+              since="5.0"
+            />
+          </div>
+          <div
+            className="little-spacer-top"
+          >
+            <code>
+              foo-deprecated
+            </code>
+          </div>
+          <div
+            className="note little-spacer-top"
+          >
+            optional
+          </div>
+        </td>
+        <td>
+          <div
+            className="markdown"
+            dangerouslySetInnerHTML={
+              Object {
+                "__html": "Foo desc",
+              }
+            }
+          />
+        </td>
+        <td
+          style={
+            Object {
+              "width": 250,
+            }
+          }
+        />
+      </tr>
+    </tbody>
+  </table>
+</div>
+`;
diff --git a/server/sonar-web/src/main/js/apps/web-api/components/__tests__/__snapshots__/ResponseExample-test.tsx.snap b/server/sonar-web/src/main/js/apps/web-api/components/__tests__/__snapshots__/ResponseExample-test.tsx.snap
new file mode 100644 (file)
index 0000000..fd3c800
--- /dev/null
@@ -0,0 +1,23 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly after fetching an example 1`] = `
+<div
+  className="web-api-response"
+/>
+`;
+
+exports[`should render correctly after fetching an example 2`] = `
+<div
+  className="web-api-response"
+>
+  <pre
+    style={
+      Object {
+        "whiteSpace": "pre-wrap",
+      }
+    }
+  >
+    my example
+  </pre>
+</div>
+`;
diff --git a/server/sonar-web/src/main/js/apps/web-api/components/__tests__/__snapshots__/Search-test.tsx.snap b/server/sonar-web/src/main/js/apps/web-api/components/__tests__/__snapshots__/Search-test.tsx.snap
new file mode 100644 (file)
index 0000000..2e4b787
--- /dev/null
@@ -0,0 +1,70 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly 1`] = `
+<div
+  className="web-api-search"
+>
+  <div>
+    <i
+      className="icon-search"
+    />
+    <input
+      className="spacer-left input-large"
+      onChange={[Function]}
+      placeholder="search_verb"
+      type="search"
+      value=""
+    />
+  </div>
+  <div
+    className="big-spacer-top"
+  >
+    <Checkbox
+      checked={false}
+      onCheck={[Function]}
+      thirdState={false}
+    >
+      <span
+        className="little-spacer-left"
+      >
+        api_documentation.show_internal
+      </span>
+    </Checkbox>
+    <Tooltip
+      overlay="api_documentation.internal_tooltip"
+      placement="right"
+    >
+      <span>
+        <HelpIcon
+          className="spacer-left text-info"
+        />
+      </span>
+    </Tooltip>
+  </div>
+  <div
+    className="spacer-top"
+  >
+    <Checkbox
+      checked={false}
+      onCheck={[Function]}
+      thirdState={false}
+    >
+      <span
+        className="little-spacer-left"
+      >
+        api_documentation.show_deprecated
+      </span>
+    </Checkbox>
+    <Tooltip
+      overlay="api_documentation.deprecation_tooltip"
+      placement="right"
+    >
+      <span>
+        <HelpIcon
+          className="spacer-left text-info"
+        />
+      </span>
+    </Tooltip>
+  </div>
+</div>
+`;
index 627ac47564ecff493a006279bfe3b1060878a63d..2b177063afd599d7b62e3c78e2a81f9f311f19a5 100644 (file)
   margin-top: 10px;
 }
 
+.web-api-action hr {
+  margin: 10px 0 0;
+  background-color: #ddd;
+}
+
 .web-api-params,
 .web-api-response {
   margin-top: 10px;
diff --git a/server/sonar-web/src/main/js/apps/web-api/utils.js b/server/sonar-web/src/main/js/apps/web-api/utils.js
deleted file mode 100644 (file)
index 5610c47..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2017 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-//@flow
-/*:: import type { Domain, Action } from '../../api/web-api'; */
-
-export function actionsFilter(
-  showDeprecated /*: boolean */,
-  showInternal /*: boolean */,
-  searchQuery /*: string */,
-  domain /*: Domain */,
-  action /*: Action */
-) {
-  const lowSearchQuery = searchQuery.toLowerCase();
-  return (
-    (showInternal || !action.internal) &&
-    (showDeprecated || !action.deprecatedSince) &&
-    (getActionKey(domain.path, action.key).includes(lowSearchQuery) ||
-      (action.description || '').toLowerCase().includes(lowSearchQuery))
-  );
-}
-
-export function getActionKey(domainPath /*: string */, actionKey /*: string */) {
-  return domainPath + '/' + actionKey;
-}
-
-export const isDomainPathActive = (path /*: string */, splat /*: string */) => {
-  const pathTokens = path.split('/');
-  const splatTokens = splat.split('/');
-
-  if (pathTokens.length > splatTokens.length) {
-    return false;
-  }
-
-  for (let i = 0; i < pathTokens.length; i++) {
-    if (pathTokens[i] !== splatTokens[i]) {
-      return false;
-    }
-  }
-
-  return true;
-};
diff --git a/server/sonar-web/src/main/js/apps/web-api/utils.ts b/server/sonar-web/src/main/js/apps/web-api/utils.ts
new file mode 100644 (file)
index 0000000..9614fa4
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+import { Domain, Action } from '../../api/web-api';
+
+export function actionsFilter(
+  showDeprecated: boolean,
+  showInternal: boolean,
+  searchQuery: string,
+  domain: Domain,
+  action: Action
+) {
+  const lowSearchQuery = searchQuery.toLowerCase();
+  return (
+    (showInternal || !action.internal) &&
+    (showDeprecated || !action.deprecatedSince) &&
+    (getActionKey(domain.path, action.key).includes(lowSearchQuery) ||
+      (action.description || '').toLowerCase().includes(lowSearchQuery))
+  );
+}
+
+export function getActionKey(domainPath: string, actionKey: string) {
+  return domainPath + '/' + actionKey;
+}
+
+export const isDomainPathActive = (path: string, splat: string) => {
+  const pathTokens = path.split('/');
+  const splatTokens = splat.split('/');
+
+  if (pathTokens.length > splatTokens.length) {
+    return false;
+  }
+
+  for (let i = 0; i < pathTokens.length; i++) {
+    if (pathTokens[i] !== splatTokens[i]) {
+      return false;
+    }
+  }
+
+  return true;
+};
diff --git a/server/sonar-web/src/main/js/components/icons-components/LinkIcon.js b/server/sonar-web/src/main/js/components/icons-components/LinkIcon.js
deleted file mode 100644 (file)
index 7d09ef2..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2017 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-// @flow
-import React from 'react';
-
-/*:: type Props = { className?: string, size?: number }; */
-
-export default function LinkIcon({ className, size = 14 } /*: Props */) {
-  /* eslint-disable max-len */
-  return (
-    <svg
-      xmlns="http://www.w3.org/2000/svg"
-      className={className}
-      height={size}
-      width={size}
-      viewBox="0 0 16 16">
-      <path
-        fill="currentColor"
-        d="M13.501 11.429q0-0.357-0.25-0.607l-1.857-1.857q-0.25-0.25-0.607-0.25-0.375 0-0.643 0.286 0.027 0.027 0.17 0.165t0.192 0.192 0.134 0.17 0.116 0.228 0.031 0.246q0 0.357-0.25 0.607t-0.607 0.25q-0.134 0-0.246-0.031t-0.228-0.116-0.17-0.134-0.192-0.192-0.165-0.17q-0.295 0.277-0.295 0.652 0 0.357 0.25 0.607l1.839 1.848q0.241 0.241 0.607 0.241 0.357 0 0.607-0.232l1.313-1.304q0.25-0.25 0.25-0.598zM7.224 5.134q0-0.357-0.25-0.607l-1.839-1.848q-0.25-0.25-0.607-0.25-0.348 0-0.607 0.241l-1.313 1.304q-0.25 0.25-0.25 0.598 0 0.357 0.25 0.607l1.857 1.857q0.241 0.241 0.607 0.241 0.375 0 0.643-0.277-0.027-0.027-0.17-0.165t-0.192-0.192-0.134-0.17-0.116-0.228-0.031-0.246q0-0.357 0.25-0.607t0.607-0.25q0.134 0 0.246 0.031t0.228 0.116 0.17 0.134 0.192 0.192 0.165 0.17q0.295-0.277 0.295-0.652zM15.215 11.429q0 1.071-0.759 1.813l-1.313 1.304q-0.741 0.741-1.813 0.741-1.080 0-1.821-0.759l-1.839-1.848q-0.741-0.741-0.741-1.813 0-1.098 0.786-1.866l-0.786-0.786q-0.768 0.786-1.857 0.786-1.071 0-1.821-0.75l-1.857-1.857q-0.75-0.75-0.75-1.821t0.759-1.813l1.313-1.304q0.741-0.741 1.813-0.741 1.080 0 1.821 0.759l1.839 1.848q0.741 0.741 0.741 1.813 0 1.098-0.786 1.866l0.786 0.786q0.768-0.786 1.857-0.786 1.071 0 1.821 0.75l1.857 1.857q0.75 0.75 0.75 1.821z"
-      />
-    </svg>
-  );
-}
diff --git a/server/sonar-web/src/main/js/components/icons-components/LinkIcon.tsx b/server/sonar-web/src/main/js/components/icons-components/LinkIcon.tsx
new file mode 100644 (file)
index 0000000..80cc776
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+import * as React from 'react';
+
+interface Props {
+  className?: string;
+  size?: number;
+}
+
+export default function LinkIcon({ className, size = 14 }: Props) {
+  /* eslint-disable max-len */
+  return (
+    <svg
+      xmlns="http://www.w3.org/2000/svg"
+      className={className}
+      height={size}
+      width={size}
+      viewBox="0 0 16 16">
+      <path
+        fill="currentColor"
+        d="M13.501 11.429q0-0.357-0.25-0.607l-1.857-1.857q-0.25-0.25-0.607-0.25-0.375 0-0.643 0.286 0.027 0.027 0.17 0.165t0.192 0.192 0.134 0.17 0.116 0.228 0.031 0.246q0 0.357-0.25 0.607t-0.607 0.25q-0.134 0-0.246-0.031t-0.228-0.116-0.17-0.134-0.192-0.192-0.165-0.17q-0.295 0.277-0.295 0.652 0 0.357 0.25 0.607l1.839 1.848q0.241 0.241 0.607 0.241 0.357 0 0.607-0.232l1.313-1.304q0.25-0.25 0.25-0.598zM7.224 5.134q0-0.357-0.25-0.607l-1.839-1.848q-0.25-0.25-0.607-0.25-0.348 0-0.607 0.241l-1.313 1.304q-0.25 0.25-0.25 0.598 0 0.357 0.25 0.607l1.857 1.857q0.241 0.241 0.607 0.241 0.375 0 0.643-0.277-0.027-0.027-0.17-0.165t-0.192-0.192-0.134-0.17-0.116-0.228-0.031-0.246q0-0.357 0.25-0.607t0.607-0.25q0.134 0 0.246 0.031t0.228 0.116 0.17 0.134 0.192 0.192 0.165 0.17q0.295-0.277 0.295-0.652zM15.215 11.429q0 1.071-0.759 1.813l-1.313 1.304q-0.741 0.741-1.813 0.741-1.080 0-1.821-0.759l-1.839-1.848q-0.741-0.741-0.741-1.813 0-1.098 0.786-1.866l-0.786-0.786q-0.768 0.786-1.857 0.786-1.071 0-1.821-0.75l-1.857-1.857q-0.75-0.75-0.75-1.821t0.759-1.813l1.313-1.304q0.741-0.741 1.813-0.741 1.080 0 1.821 0.759l1.839 1.848q0.741 0.741 0.741 1.813 0 1.098-0.786 1.866l0.786 0.786q0.768-0.786 1.857-0.786 1.071 0 1.821 0.75l1.857 1.857q0.75 0.75 0.75 1.821z"
+      />
+    </svg>
+  );
+}
index b494866ac8d77ec077512a199ac8ac2ec7a7ab87..d5cc057a13aeeabb81f4dc70a71a909136af065d 100644 (file)
@@ -2875,6 +2875,17 @@ api_documentation.internal_tooltip=Use at your own risk; internal services are s
 api_documentation.page=Web API
 api_documentation.show_deprecated=Show Deprecated API
 api_documentation.show_internal=Show Internal API
+api_documentation.possible_values=Possible values
+api_documentation.default_values=Default value
+api_documentation.example_values=Example value
+api_documentation.max_values=Maximum allowed values
+api_documentation.internal=internal
+api_documentation.deprecated=deprecated
+api_documentation.depracated_since_x=deprecated since {0}
+api_documentation.parameters=Parameters
+api_documentation.response_example=Response Example
+api_documentation.changelog=Changelog
+
 
 #------------------------------------------------------------------------------
 #